Why Tailscale, not a real VPN server
I looked at running my own WireGuard setup by hand … port forwarding, managing keys myself, keeping track of which peer is which. Tailscale does all of that for you, on top of WireGuard, and the actual setup on each machine ends up being a handful of lines. Every device I own is on the same tailnet now: the T620 server, my NixOS desktop, and … the one that surprised me … a MacBook Air 6,2 from 2014 that has no business running anything modern smoothly, and does it fine anyway.
The whole NixOS config, genuinely this short
{
config,
pkgs,
lib,
...
}:
{
services.tailscale.enable = true;
networking.firewall = {
enable = true;
trustedInterfaces = [ "tailscale0" ];
allowedTCPPorts = [ 22 ];
allowedUDPPorts = [ 41641 ];
};
powerManagement.resumeCommands = ''
${pkgs.systemd}/bin/systemctl restart tailscaled
'';
}
That’s it. Three real settings, not a wall of options.
Breaking down each piece
services.tailscale.enable = true; … installs and enables the
daemon. On a normal distro this is a package install plus a systemd
enable; on NixOS it’s one line that handles both.
trustedInterfaces = [ "tailscale0" ] … this is the one that
actually matters and the one I got wrong on the T620 the first time
around. Tailscale creates its own virtual network interface, and
without explicitly trusting it in the firewall, traffic coming through
the tailnet gets treated the same as traffic from the open internet …
meaning things that should just work over Tailscale (SSH, Samba, SFTP)
get blocked or, worse, silently forced through a relay because the
direct connection can’t establish properly. One line, and every service
already running is reachable over the tailnet without touching
individual port rules for each thing.
allowedTCPPorts = [ 22 ] … SSH, opened normally, nothing
Tailscale-specific about this line, just there because I want SSH
reachable.
allowedUDPPorts = [ 41641 ] … this is Tailscale’s own port for
direct peer-to-peer connection negotiation (NAT hole-punching). Without
it open, Tailscale still works, but every connection falls back to
relaying through Tailscale’s own DERP servers instead of connecting
directly device-to-device … meaning real, measurable extra latency for
absolutely no reason, every single time. I found this out by comparing
tailscale status output between two machines and noticing one said
direct and the other said relay for the exact same peer, at the
exact same location. This one line fixed the difference completely.
The suspend/resume fix, and why it’s there
powerManagement.resumeCommands = ''
${pkgs.systemd}/bin/systemctl restart tailscaled
'';
Tailscale’s daemon doesn’t reliably reconnect its tunnel on its own after a laptop wakes from sleep … the underlying network interface comes back, but the tailscaled process itself sometimes just sits there with a dead connection until something kicks it. This forces a clean restart of the daemon specifically at resume, so I never wake the machine up to find Tailscale silently disconnected and have to notice and fix it manually.
The MacBook Air, and why it just works too
The genuinely surprising part wasn’t the NixOS desktop or the Fedora server … both are machines I expected to configure carefully. It was installing Tailscale on a 2014 MacBook Air 6,2 with 4GB of RAM and expecting some kind of fight to get it running smoothly. There wasn’t one. Install the client, log in, done … same tailnet, same access to every other machine, no meaningful resource cost on hardware that struggles with plenty of far lighter software.
That’s the actual point of this whole setup for me. It’s not one clever config on one important machine … it’s the same trivial setup, repeated across genuinely different hardware and different operating systems, and every single one of them just becomes another device on the same private network with zero port forwarding on my actual router and zero manual key management on my end.
What I’d actually tell someone setting this up
Don’t skip the firewall interface trust line if you’re on NixOS or
anything with a default-deny firewall … that one line is the difference
between “Tailscale is installed” and “Tailscale actually lets your other
services through.” And check tailscale status on both ends of a
connection you care about being fast … if it says relay instead of
showing a direct IP, that’s almost always a firewall/UDP port problem,
not something wrong with Tailscale itself.