Runbook: Tailscale¶
How the tailnet is wired and the non-obvious behaviors that bite. Tailscale is not managed from
this repo (no config file here) — it's daemon state on av plus the admin console. This is the
written record. Companion: docs/runbooks/dns.md (the DNS model leans directly on the routes below).
Tailnet:
anaconda-perch.ts.net·av= machineascertain-verse,100.98.53.7/fd7a:115c:a1e0::4001:3507· operator:skill-lava(sotailscale set/uponavneed no sudo) · MagicDNS suffix:anaconda-perch.ts.net.
1. Two kinds of address — the distinction everything hinges on¶
Every tailnet node has a native address (100.x + a fd7a:… ULA) reachable by every peer
over the WireGuard mesh, no opt-in required. Separately, a node can act as a subnet router and
advertise routes to other IPs/CIDRs; those are reachable only by peers that have accepted
routes (--accept-routes, off by default on Linux; on by default on mobile). This split is the
root of both the DNS design (§3) and the sharing gotcha (§4).
2. av as a subnet router¶
av advertises its own LAN addresses as /32 and /128 routes so off-LAN tailnet devices can reach
LAN services. Current state (tailscale status --json → Self.PrimaryRoutes = the approved set):
| Route | Purpose | Status |
|---|---|---|
192.168.86.49/32 |
av's LAN IPv4 (the A record) reachable off-LAN |
✅ approved |
fd00:6176::49/128 |
av's LAN IPv6 ULA (the fd00:6176 AAAA) reachable off-LAN |
⚠️ advertise + approve pending (2026-08-02) |
0.0.0.0/0, ::/0 |
av offered as an exit node | ✅ approved (available to peers) |
- IPv6 forwarding is on (
net.ipv6.conf.all.forwarding=1,ip_forward=1) — required for the subnet router; already set, no sysctl change needed for the/128. - Advertising ≠ active. A newly advertised route stays unusable until approved in the admin
console (Machines →
ascertain-verse→ ⋯ → Edit route settings; exit nodes are approved the same way). No auto-approver — approval is manual. Check subnet routes withtailscale status --json | jq '.Self.PrimaryRoutes'; exit-node approval shows asSelf.ExitNodeOption: true. - Set what av advertises (operator, no sudo):
tailscale set --advertise-routes=192.168.86.49/32,fd00:6176::49/128 --advertise-exit-node— the two subnet routes plus the exit-node offer. (av previously also advertised192.168.86.33/32; removed 2026-07-29 as unneeded.)
3. How DNS depends on this (see dns.md)¶
Public DNS publishes, for every *.fmm.house name, A .49 + two AAAAs: fd00:6176 (LAN ULA) and
fd7a (native). Each audience uses the address it can route to (Happy Eyeballs races them):
- LAN device →
.49/fd00:6176directly (same link). - On-tailnet, off-LAN, accepts routes →
.49/fd00:6176via the approved/32+/128. - On-tailnet, off-LAN, doesn't accept routes →
fd7a(native; the routes are invisible to it). - Shared-in user (see §4) →
fd7aonly.
fd7a is published specifically so the last two cases work — dropping it (a brief 2026-07-19
experiment) broke node sharing.
4. Node sharing — the gotcha ⚠️¶
You share individual machines out to other people's tailnets (the device-of-shared-to-user peers).
Sharing a machine exposes only that machine's own native Tailscale address — never its subnet
routes. Straight from Tailscale's docs: "Shared machines do not advertise subnets to the tailnets
they're shared into."
Consequence for us: a person you've shared av with can reach av's 100.98.53.7 / fd7a:…, but
not 192.168.86.49/32 or fd00:6176::49/128. So when they resolve bz.fmm.house (public DNS →
.49 + fd00:6176 + fd7a), the only address they can actually route to is fd7a. That is why the
public zone must keep fd7a published even though LAN/tailnet clients prefer fd00:6176.
- AdGuard is irrelevant to shared users — they're on their own tailnet and resolve
fmm.housevia public DNS, neverav's AdGuard. (AdGuard servesfd00:6176only; seedns.md §2b.) - If a shared user ever needs full subnet access (not just
av), the alternative is to invite them into this tailnet instead of sharing a node — invited users do get subnet routers. Bigger blast radius; not currently done.
5. Exit nodes¶
av is an approved exit node (ExitNodeOption: true, §2) — tailnet peers may route all their
traffic out through it. av itself is not using an exit node (ExitNodeID empty). Other peers
also offering exit-node service: homeassistant, teka, kvm-teka, bedroom-a-box. Nothing in the
homelab depends on exit nodes; listed for inventory.
6. Operations¶
tailscale status # peers, who's online, who advertises what
tailscale status --json | jq '.Self.PrimaryRoutes' # approved routes on av
tailscale debug prefs | jq '{OperatorUser,RouteAll,AdvertiseRoutes,ExitNodeID}'
tailscale set --advertise-routes=<csv> # (re)advertise subnet routes — then APPROVE in the console
tailscale set --accept-routes=true # this node uses others' subnet routes
- Approval and sharing are console-only — the CLI can advertise/accept, but approving a route or
sharing a node is done at https://login.tailscale.com/admin/machines. Route acceptance is a
per-device local pref and is not visible from
av(not instatus/netmap/API) — the only way to know is to check the device or test. - Reboots:
av's Tailscale comes back on its own; the LUKS/boot fragility is a Docker concern, not a Tailscale one (seedns.md §5d).
7. Cross-references¶
docs/runbooks/dns.md— the resolution model that rides on §2's routes (§1 table, §7).docs/architecture.md— network model summary.- Memory:
dns-spec-and-reboot-fragility.