Good Tests, Straightforward Migration

December 16, 2025

Good Tests, Straightforward Migration

Return on investment while moving to Grants in Tailscale

One of my favourite blog posts and generally, favourite thing I did, was use test driven development with my Tailscale ACL. I’m pretty much a noob when it comes to software engineering, even though it was the basis of my degree, but I read a lot about it and have great colleagues who have decades of experience in it. One thing that always came up, was test driven development. If you’re not familiar, the very very basic idea is that when writing code, you write your test first. That test, will fail and you subsequently write code that will have the test pass. You would then refactor this code as time goes on, following the pattern of red, green and refactor. Or rephrased slightly; failing test, passing test, refactor.

This is great especially for Tailscale. When an ACL test fails, it can very clearly tell you why. A pseudo code example would be like, evans-lovely-desktop expected allow port 80, got drop. So my test was testing for port 80 to be open on my machine called “evans-lovely-desktop” and complained because it wasn’t. So, just write the ACL rule to say open this port, rerun the tests and they pass! Here’s some code snippets from my ACL, first off, a test:

  "tests": [
    {
      // Evan should be able to reach 8080 on gateway
      "src": "evan@example.com",
      "accept": ["gateway:8080"]
    },

And then the actual rule that satisfies that test:

  "grants": [
    // Evan can reach port 8080 on gateway
    { "src": ["evan@example.com"], "dst": ["gateway"], "ip": ["8080"] },

Obviously I’m just talking about this at a personal level, but think of this on a much grander scale. Imagine an enterprise having complete test driven coverage of their access controls into their network? Sounds pretty good to me anyway! The eagle eyed among you, who also know Tailscale, and of course read my blog post I linked above, will notice I am now using Grants, where as previously I did not. What’s up with that?

Grants are the next generation of ACLs for Tailscale. Tailscale themselves are good in that they’ve continued to support the legacy system and look set to continue to do so. But, Grants are very much the future. One clear distinction between the two systems is that ACLs only worked on the network layer. But Grants work on both the network layer and the application layer. Something I’ve yet to try but really looking forward to trying, is that Grants are also routing aware. So, for example I could write a rule to say “hey send all traffic from my personal devices via Mullvad”. Which, is something I really want to do, time is just a fickle thing!

So, I wanted to migrate from my legacy setup, to Grants. I also took this as another opportunity to try out Claude via GitHub Copilot Chat being a bit of a consultant. Thank god they’re an unpaid consultant as far as my circumstances go! Here’s how my flow went.

  • Changed the acls keyword to grants and removed the "action: "accept" from all my rules as grants now does an implicit accept when you write the rule.
  • The main thing that caught me out, was the change in formatting for port access. Bear in mind of course, actually reading the docs can help a lot with anything in life. But really the main change here is going from host:port entries in the destination field, to "ip": ["22"] being a separate field
  • Rolled the above changes through the entire grants stanza

My tests did exactly as I thought they would and were failing throughout haha. But, I had entered that refactoring phase. When I changed to Grants, naturally there was complaints about syntax and things like that. But all I was doing was refactoring an existing rule to be compliant with Grants. Once I did one and reran the tests, it started complaining about the next failure, so I knew that the access I originally had tested for, was back in place on the new Grants setup.

Besides some Copilot hallucinations, my migration effort was very smooth. Obviously, I am just one person, with perhaps an over engineered Tailnet. But if there’s one habit I’ve kept up, it’s writing tests for my access control. And as demonstrated to me by doing this migration to Grants, it’s really paid dividends. I have many plans for my Tailscale setup, like I mentioned, introducing the use of via into my network to make traffic flow places that I want it to flow to. I’d love to try and get exit nodes setup at some of the homes of my brothers who live abroad too. I’ll be writing again soon about some changes in my setup for the Tailscale Kubernetes Operator, which has helped me achieve much better availability of my services when doing things like patching my cluster at home!

Thank you!

You could of consumed content on any website, but you went ahead and consumed my content, so I'm very grateful! If you liked this, then you might like this other piece of content I worked on.

Reflecting on how things have been recently

Photographer

I've no real claim to fame when it comes to good photos, so it's why the header photo for this post was shot by Nguyen Dang Hoang Nhu . You can find some more photos from them on Unsplash. Unsplash is a great place to source photos for your website, presentation and more! But it wouldn't be anything without the photographers who put in the work.

Find Them On Unsplash

Support what I do

I write for the love and passion I have for technology. Just reading and sharing my articles is more than enough. But if you want to offer more direct support, then you can support the running costs of my website by donating via Stripe. Only do so if you feel I have truly delivered value, but as I said, your readership is more than enough already. Thank you :)

Support My Work

GitHub Profile

Visit My GitHub

LinkedIn

Connect With Me

Support my content

Support What I Do!

My CV / Resume

Download Here

Email

contact at evanday dot dev

Client Agreement

Read Here