Files
PFVCluster/docs/tailscale.md
T
mrcharles a7fbad60ab docs: end-to-end gardening — links, stale refs, tailscale.md update
Comprehensive documentation gardening across the merged repo:

- tailscale.md: fully rewritten with current ground truth. The netinfra
  pair now runs production Technitium with all knel.net records
  replicated. Both LAN IPs resolve knel.net device names and recurse
  externally. The old "NXDOMAIN / zone is stale" findings are replaced
  with the resolved state and current recommendations.
- AGENTS.md: rewritten with Gitea-compatible clickable relative links
  to all key scripts and docs. Autonomous commit/push policy
  prominently documented. SSH user corrected to localuser.
- README.md: directory table and docs table now use clickable links.
- All .md cross-references converted to Gitea-renderable relative links.
- Stale path references (ProjectCode/, Project-Tests/, ProjectDocs/)
  updated to current names (provisioning/, tests/) across all docs.
- Stale repo name "FetchApply" / "KNELServerBuild" updated to
  "PFVCluster" in actionable docs; historical AI-review docs tagged
  with an HTML comment notice.
- REFACTORING-EXAMPLES.md: tagged as historical (pre-refactor patterns).
- tests/README.md, dns-cluster-setup/README.md, docs/DEPLOYMENT.md,
  docs/SECURITY.md: path references fixed to current structure.

🤖 Generated with [Crush](https://github.com/charmassociates/crush)

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-07-28 11:28:52 -05:00

5.0 KiB

Tailscale vs. Managed DNS — Architecture Analysis

Status: RESOLVED. The pfv-netinfra-01/02 pair now runs production Technitium DNS with all knel.net records replicated from tailscale-router via the DNS cluster setup. Both LAN IPs serve authoritative records for knel.net and recurse externally. This document records the original conflict, how it was resolved, and the recommended client configuration.

1. Executive summary

Every host in this build runs the Tailscale client, and Tailscale's MagicDNS manages /etc/resolv.conf by default (pointing at 100.100.100.100). This previously conflicted with a managed resolv.conf pointing at the LAN resolvers. The root cause was that the LAN Technitium instances did not have the knel.net zone populated — that is now fixed.

The pfv-netinfra-01/02 pair now serves identical, authoritative knel.net records (replicated from production via dns-cluster-setup/). Both LAN IPs resolve knel.net device names and recurse externally. The managed resolv.conf is now safe to deploy.

Recommendation: Deploy the managed resolv.conf (.252/.253) on hosts where you want tunnel-independent DNS. Leave Tailscale managing DNS on hosts where MagicDNS device names must resolve without a LAN path (e.g. laptops off -network). See §5 for details.

2. How name resolution works today (post-cluster-setup)

Probed from sectestbed-sandbox (192.168.3.50) after the DNS cluster was deployed:

Query path External name (github.com) knel.net device name (pfv-netinfra-01.knel.net)
Via Tailscale resolver (100.100.100.100) resolves resolves → 100.70.181.72 (Tailscale CGNAT)
Direct dig @192.168.3.252 (Technitium primary, LAN) resolves (recurses) resolves100.70.181.72
Direct dig @192.168.3.253 (Technitium secondary, LAN) resolves (recurses) resolves100.70.181.72

Both LAN resolvers now serve knel.net records identically. The Technitium zone is no longer stale — it was replicated from production (tailscale-router) as part of the DNS cluster setup.

What changed

Previously (before the DNS cluster setup), querying the LAN IPs returned NXDOMAIN for knel.net device names because the Technitium knel.net zone was empty (SOA serial 2025062313, dated 2025-06-23). After replicating production config to both netinfra hosts, all 124 zones — including knel.net with all current device records — are served authoritatively on both .252 and .253.

3. The DNS server pair

Host IP Role Services
pfv-netinfra-01 192.168.3.252 Primary Technitium (authoritative, port 5300) + Pi-hole (recursive, port 53)
pfv-netinfra-02 192.168.3.253 Secondary Technitium (replicated via rsync, port 5300) + Pi-hole (recursive, port 53)

Zone replication is rsync-based (every 60s via systemd timer) because Technitium's AXFR uses port 53, which is occupied by Pi-hole on these hosts. See dns-cluster-setup/README.md for full details.

4. NTP (fully resolved)

NTP is independent of DNS: provisioning/ConfigFiles/NTP/ntp.conf points directly at the LAN IPs with no DNS dependency:

server 192.168.3.252 iburst
server 192.168.3.253 iburst

Both servers respond with stratum 2/3. The client config uses restrict rules (not interface listen) to avoid the loopback-binding bug that prevented sync. This is safe under both Tailscale-managed and LAN-pinned resolver configurations.

5. Recommendation

On fixed servers (always on-LAN)

Deploy the managed resolv.conf (provisioning/ConfigFiles/Resolv/):

  • Points at .252/.253 with failover
  • knel.net records resolve on both servers
  • External names recurse on both servers
  • DNS survives tailscaled outages (unlike Tailscale-managed DNS)

To prevent Tailscale from overwriting the managed file:

tailscale up --accept-dns=false

On laptops / roaming hosts

Let Tailscale manage DNS (default accept-dns=true):

  • MagicDNS resolves knel.net device names via the tunnel
  • No dependency on LAN reachability
  • Accept the tailscaled dependency (if the tunnel is down, you're off-network anyway)

6. Known items / future work

  1. Pi-hole upstream configuration. Pi-hole on both hosts should forward to the local Technitium instance (port 5300) for knel.net and to an external resolver for everything else. Verify this is configured on both nodes.
  2. Zone transfer via AXFR. Currently using rsync because Technitium's AXFR expects port 53. If Technitium's listen port can be changed, or Pi-hole can be configured to proxy AXFR, the rsync timer could be replaced with native DNS zone transfer.
  3. accept-dns=false automation. The provisioning code should set --accept-dns=false on Tailscale during setup (after deploying the managed resolv.conf) so Tailscale doesn't overwrite it on reboot.