Series · The Quiet Machine · Part 4
Reaching the Home Server From Anywhere With Tailscale
Tailscale made the box reachable from the Mac: no port forward, no password ever crossing the internet.
Everything up to this point (the BIOS restraint, the SSH hardening) worked because I was on the LAN. Reaching the box from outside the house while keeping that “no internet exposure” posture intact needed Tailscale, and the philosophy stays the same: max reach, still private.
WireGuard without running a server
Tailscale is a WireGuard mesh with the coordination handled for you. You don’t rent a VPS or manage keys by hand. Every device you sign in becomes a peer on a private network (a “tailnet”) and finds the others directly. For a personal handful of machines it’s free; you only start paying once it’s a team.
Headscale is the self-hosted alternative if you don’t want a hosted control plane, but that’s a server to run, which is exactly what I was trying to avoid.
The reality had two traps.
Gotcha 1: the browser that wouldn’t open
Tailscale’s default sign-in expects a local browser for OAuth. The box is headless, driven entirely over SSH, so there’s no browser on the machine itself to pop; tailscale up just sat there printing an auth URL.
That URL works fine copied to any device — a phone, the Mac, wherever — you open it, authorize, done. But the cleaner move skips the browser step entirely: generate a pre-authorized auth key in the admin console and hand it to the daemon.
tailscale up --authkey=tskey-auth-xxxxxxxxxxxx
No browser, no interactive dance — the key was generated once for this join and not kept afterward.
Gotcha 2: the “Tags” trap
While generating that key, the admin console offers a Tags toggle. Looks harmless (tags are how you label devices for access-control rules), so I flipped it on. It didn’t work.
The catch: a tag has to be declared in your ACL policy file’s tagOwners before an auth key can apply it. For a real fleet you’d set that up deliberately. For a personal key joining two of my own devices, tags are pure overhead. Leave Tags off: the moment I generated a plain, untagged key, the box joined on the first try.
The proof it costs nothing
The part that worried me: a hosted service like this might route my traffic through its own servers, adding latency and maybe a bandwidth cap on the free plan, a real tax if every SSH keystroke and file copy round-tripped through it.
It doesn’t. Tailscale’s relays (DERP) are only a fallback for when two peers can’t punch a direct path. At home, my Mac and the box are on the same LAN, and Tailscale figures that out: a direct path over the LAN, not through a relay, at five milliseconds, straight across my own switch. The WireGuard encryption still rides on top, but the packets never leave the house, so on the same network there’s no relay detour and no metered bandwidth. Only when I’m away, and a direct path can’t form through both NATs, does it fall back to a relay.
One firewall detail bit me. I’d locked sshd to LocalSubnet when I hardened it: LAN only. Over the tailnet, my Mac shows up with a tailnet address, which isn’t in my local subnet, so the connection got silently refused. I widened the SSH scope to include the tailnet, alongside the LAN.
A later audit found the Windows default SSH rule — the one that ships enabled, open to any address — was still sitting next to the hardened one. I disabled it. Still no path from the open internet.
Planning for the day Tailscale itself is down
Tailscale can go down anywhere I am, so I built the fallback in layers:
- At home, skip Tailscale entirely. A plain LAN alias in SSH config hits the box by its static IP, no dependency on any mesh. It’s the floor, working whether Tailscale is running or not.
- Self-heal. A Windows Scheduled Task restarts Tailscale or sshd if either stops running, meant to catch most transient outages before I’d notice.
- Survive a power cut with nobody home. This is where the SSH hardening and the BIOS restraint pay off: sshd is a boot-level service, AC Back is set to Always On, and the box is on wired Ethernet, so after an outage it powers itself back up, brings up the network, and answers SSH without anyone touching it. Tailscale, I assumed, would come back the same way.
The honest limit
If I’m away and Tailscale is fully down, the box is unreachable, by design. There’s no inbound port to fall back to, and I refuse to open one. At that point, the fix was documented but not built: a reverse SSH tunnel to a free-tier VPS (Oracle) or a Cloudflare Tunnel, where the box dials out and stays outbound-only. No listening port ever opens at home. I’d rather be honestly unreachable than quietly exposed.
The last piece is mundane and I use it constantly: a Windows SMB share on the box, mounted on the Mac, reachable over LAN or tailnet, behind a dedicated low-privilege account, so both machines see one folder.
Next up: the first reboot after all this tuning, and the one thing that broke: a service that came up perfectly next to one that quietly refused to start until someone logged in.