Home Network Update
I spent the day changing how my home network works. Or rather, how I make services on my home network available when I'm on the go.
I run two servers at home. My NAS, which uses Docker Compose to provide a bunch of useful tools, mostly for internal use, and a mini server that runs my Home Assistant setup.
For the last few years, I exposed Home Assistant directly to the Internet using a port forward on my FritzBox router and a DuckDNS dynamic DNS setup. If I needed access to something else on my network, I could open a WireGuard VPN connection to my NAS – again using a port forward.
Exposing my Home Assistant directly to the Internet isn't great, of course. And I also started using more services on my NAS that I wanted to access on the go.
So today I streamlined a couple of things:
I now use Tailscale like all the cool kids. However, I use it more like a traditional VPN by simply using its subnet routing feature to make my whole LAN available. For that, I don't rely on their “MagicDNS”. Instead, I use what I already had in place: a public domain setup that points to my NAS's internal IP. The NAS runs Traefik and uses ACME DNS-01 to get certificates for that domain.
Basically, a request for https//myservice.69b.place always resolves to 192.168.1.33. Tailscale now just makes sure that this IP is reachable from my phone, even when I'm not at home.
Because I want to keep as much of my infrastructure defined as code as possible, I had two options for setting it up:
- as a “native” NixOS service, or
- as a Docker Compose setup
I decided to go for the latter because it made the subnet routing setup a tiny bit easier.
I also tried to keep as much of the Tailscale configuration itself in code as possible. The most important part of the configuration is the “policy”, which defines what connected devices are allowed to do. Luckily, this policy can be pushed via a GitHub Action. So the repository that defines my Docker Compose setup now also contains said policy and pushes it automatically to Tailscale whenever I merge a new one.
One thing I'm a bit wary of is that the whole Tailscale network currently depends on Google Authentication. It was simple to set up, but should I ever want to switch to a different Identity Provider, I'll need to set up the Tailscale part again. Hopefully, my precautions, including having checked in everything important, will help with that.
Once the whole Tailscale thing was done, making my Home Assistant available was pretty simple. I just dropped the DuckDNS and Nginx SSL proxy apps, added my NAS as a Trusted Proxy in Home Assistant, and added a route in Traefik.
No more port forwards and easy access to internal services from everywhere. 🤩
Then there was one more thing. I use Watchtower to keep my Docker stacks up to date. For stuff I actually code myself, I usually let GitHub Actions build and publish a Docker image. At the end of the build process, I want to ping Watchtower to have it fetch the new image. This was impossible without another port forward in the old setup.
The new setup allows me to use a “Funnel” to expose a local service via Tailscale to the public Internet. Even better, it allows me to expose just a certain path. So now the Watchtower API is reachable from the outside while everything else stays private. Perfect.
The whole setup is in my public Docker infrastructure repository if you want more details.
