Tailscale five years later: what changed in my personal mesh
In late 2021 I wrote Easily build your own network with Tailscale. The pitch was simple: drop OpenVPN, install a client, log in, get a stable 100.x address that works from anywhere.
That part still holds. What changed is everything around it. The mesh is no longer “a few laptops and one Proxmox box.” It is multiple sites, advertised home LAN routes, reverse proxies, camera streams, and NFS mounts that need to keep working when I am on the same Wi-Fi as the server and when I am halfway across the region.
This is the boring version of five years later: what I run now, and what bit me along the way.
Then vs now
In 2021 the mental model was one flat personal network over WireGuard. Devices talked to each other by Tailscale IP. Subnet routing was optional. ACLs were “maybe later.”
Today the shape looks more like this:
- A few named nodes that stay up (
homeland,berlin, and a smaller one I treat as secondary) - Proxmox on more than one site, with services split between LXC and VMs
- Frigate (NVR) in more than one place, plus go2rtc for camera restreams
- Nginx Proxy Manager in front of internal HTTP services
- NFS for bulk media / recordings on at least one node
- Phones and laptops as clients, not servers
I still install Tailscale the same way. The difference is I now treat the mesh as infrastructure instead of a convenience VPN I forget about until travel day.
The LAN still matters
Early on I caught myself thinking “everything is on Tailscale, so the home LAN matters less.” That was wrong for anything that moves real traffic locally.
Cameras, NFS, and Frigate recordings want the fast path. When I am at home, the laptop should hit the NAS or the NVR on the wired or Wi-Fi network instead of bouncing through a relay or a longer mesh hop when ethernet is right there. Tailscale is how I reach the lab from outside and how sites talk to each other. It is a poor substitute for a clean layout on site.
So the rule I use now: inside one building, bulk and latency-sensitive traffic stays on the home network. Everything cross-site or away from home rides Tailscale, and browser entrypoints I want on a hostname go through a reverse proxy on a node I can reach over the mesh.
Two kinds of routing
People say Tailscale “picks the shortest path.” That claim covers node-to-node traffic and stops there, which confused me for a while.
Between Tailscale nodes (laptop to berlin, phone to a 100.x address), Tailscale does path selection. Direct WireGuard when it can, relay when it must. That is the “works from anywhere” story from the 2021 post. I still trust that part.
Subnet routes are different. When a node advertises a home LAN range, an admin approves it, and a client accepts subnet routes, that client installs those destinations so traffic to e.g. 192.168.x.y can go into Tailscale toward the advertising node. The client does not first ask “am I already on that LAN?” before installing the route. Windows, macOS, and phones accept subnet routes by default. Linux needs tailscale set --accept-routes.
Good path selection between mesh peers is a separate feature from “send this private home IP out the ethernet port because I am sitting on that network.”
If you only run Tailscale node-to-node and never advertise home ranges, you can skip the next section.
Subnet routes earned their keep
Advertising a home subnet into the tailnet is the feature that turned “SSH to one box” into “the lab is reachable.” ACLs matter more once routes exist, because a tagged laptop can suddenly see a whole 192.168.x.0/24 instead of one host.
Things I route on purpose:
- Camera / IoT segments I need from another site or from a jump host
- Management networks for Proxmox or out-of-band bits I refuse to expose on the public internet
- Selected LAN ranges so a phone on cellular can open an internal service without a separate VPN profile
Things I do not route blindly:
- Guest Wi-Fi
- Entire “all of home” if a narrower range is enough
- Two sites both using the same private ranges (for example both on
192.168.1.0/24) with no plan
If two houses both love 192.168.1.0/24, pick one side to renumber or only advertise specific hosts. I would rather fix addressing once than debug “why does this IP mean different machines depending on which route wins.”
Where accept-routes bit me on Linux
This is the bug that cost me real time, so it gets its own section.
The failure mode: a Linux box lives on a home LAN, and it also accepts that same range (or an overlapping one) as a subnet route from the tailnet. Traffic you expected to stay on the wire starts following the mesh instead. Peer path selection between nodes keeps working the whole time, which is part of why the problem is hard to spot.
On Linux, accepted subnet routes are not ordinary routes that politely lose to “I am directly on this network.” Tailscale puts them in a separate route table (table 52) and installs a rule so that table is checked before the normal one. That is intentional. Tailscale’s stated reason is safety on untrusted networks: if you are on coffee-shop Wi-Fi that also uses 192.168.1.0/24, and your office advertises 192.168.1.0/24, they do not want the coffee shop to win and quietly eat traffic meant for the office.
The other side of that tradeoff: always-on lab servers on a network you trust get the same priority rules. NPM backends, NFS mounts, and http://192.168.x.y admin UIs start following the mesh path. That path can work, blackhole, or hold up fine until a reboot changes the answer. This class of breakage has been reported for years by other people running similar setups.
Symptoms I hit:
- Reverse proxy targets on LAN IPs timed out only from certain nodes
- NFS looked mounted then stalled
- A service that answered on the host’s own subnet became unreachable after a Tailscale upgrade or reconnect
The fix that stuck for me kept subnet routes and changed who accepts them:
- Be deliberate about which nodes accept routes. Many servers only need other nodes’
100.xaddresses and never need accept-routes at all. - On nodes that must accept routes and also sit on a real home LAN, prefer the local interface for the local ranges (a small
ip rule/ table pin so home traffic stays on the physical NIC). - Point reverse proxies and mounts at addresses that stay stable under that policy (often the node’s Tailscale IP, or a hostname that resolves the way you intend, rather than a LAN IP that flips behavior).
I keep a small local script so the home ranges stay glued to the physical NIC. Without that pin, any always-on Linux lab node that also sees advertised home subnets can lose its own LAN to table 52 after an upgrade or reconnect.
Do not casually enable accept-routes on a server that already sits on the LAN you advertise elsewhere, until you know those destinations still leave via the real network interface after Tailscale comes up.
ACLs stopped being optional
With three clients the default “nodes can talk” policy is fine. With subnet routes, tags, and a roommate or friend device once in a while, defaults get scary.
I moved to tags and destination-based rules. The exact policy file is personal, but the shape is:
- Tags for
server,client,camera-net(or similar) - Servers accept SSH/HTTPS/admin ports from clients
- Clients do not need to accept inbound from the camera subnet
- Subnet route exposure is granted to roles that need it, rather than every device on the tailnet
Once you advertise a home subnet, a lost laptop can see a whole network instead of one VPS. Write the ACL before you advertise the route.
How I reach web UIs now
I used to port-forward or SSH-tunnel random admin ports. Managing that got old once the service count grew.
Pattern that replaced most of it:
- Service listens on localhost or the LAN only on the lab node
- Nginx Proxy Manager (or any reverse proxy) sits on a node I can reach over Tailscale
- DNS name (sometimes a real domain, sometimes MagicDNS) points at the proxy’s Tailscale IP
- HTTPS terminates at the proxy; upstream is internal
Frigate is the obvious example in my setup: open the NVR on a hostname when I am on the tailnet, without opening an inbound port on the home router. Same idea for other dashboards.
MagicDNS alone is enough for quick SSH (ssh berlin). For browser apps I still like a proper hostname and a proxy so cookies, TLS, and path routing behave like a normal service.
What runs where
- Proxmox still anchors the heavy nodes. Some workloads fit LXC; others (Docker-heavy stacks, odd kernel needs) stay in VMs.
- Frigate exists in more than one place for site-local cameras. Cross-site I restream when I need a view, rather than dragging every camera feed across the internet full time.
- NFS holds bulky recordings/media on the node with the disks. Mounts are explicit; I do not pretend the mesh makes network storage as safe as local disk.
- Secondary / smaller nodes are fine for lightweight services and as another hop on the tailnet. Not everything needs to be a full hypervisor.
Habits that stuck
- Tailscale as the default remote access layer for a personal lab
- Subnet routes for specific ranges, with ACLs written first
- Reverse proxy on the mesh instead of opening internet ports for admin UIs
- Boring hostnames and a small number of always-on nodes with clear roles
- Documenting which machines accept routes, and any local-LAN preference pins, so future me does not “fix” things back into a broken state
Mistakes I stopped making
- Advertising the same private ranges from two sites without renumbering
- Turning on accept-routes everywhere “for convenience”
- Pointing critical mounts and proxy upstreams at LAN IPs on nodes where those destinations can flip onto the mesh
- Assuming bulk camera or NFS traffic is fine over a relay path without checking
- Skipping tags until “later” once friends or spare devices join the tailnet
Compared to the 2021 post
The old post was a migration story: I was tired of maintaining OpenVPN, and Tailscale took that chore away. That recommendation stands for personal use.
Five years on, installing the client and getting node-to-node mesh is still the easy part. The work moved to the edges: addressing when two sites collide, who accepts subnet routes, ACLs, and which services should never leave the building on a skinny path.
If you are still on the single-site, no-subnet-routes setup from my first post, you do not need most of this yet. When you add a second site or advertise a home LAN into the tailnet, come back and treat routes and ACLs as the real install step. And if something on the LAN “randomly” breaks only on Linux after accept-routes, check whether table 52 is winning before you blame the app.
I still would not go back to running my own VPN concentrator for this. I would start the ACL file earlier, and I would not confuse “mesh path selection” with “home LAN route priority.”