Tailscale DNS on Docker Hosts¶
Applies to: any Archon fleet node running both Tailscale and Docker Work item: WI-305 Last updated: 2026-04-26
Problem¶
Tailscale's MagicDNS (accept-dns=true) overwrites /etc/resolv.conf to point at its local DNS proxy (100.100.100.100). If the proxy cannot fetch upstream resolver config from the Tailscale control plane (indicated by the health check message "Tailscale failed to fetch the DNS configuration of your device: exit status 1"), it returns SERVFAIL for all queries.
Docker containers inherit this broken resolver. The symptom is ENOTFOUND or SERVFAIL on all outbound DNS from containers and the host.
Root cause (caneast-site1-node2, confirmed 2026-04-26)¶
- Tailscale registered 100.100.100.100 as the global DNS server in both
/etc/resolv.confand systemd-resolved via D-Bus. - The Tailscale control plane could not push DNS config to the device (health check: exit status 1), so the proxy had no upstream resolvers.
- All DNS queries returned SERVFAIL -- from the host and from Docker containers.
Permanent fix¶
Apply on the affected node:
Write a static /etc/resolv.conf bypassing the Tailscale proxy:
sudo tee /etc/resolv.conf > /dev/null << 'EOF'
# Static resolv.conf -- Tailscale accept-dns=false
nameserver REDACTED
nameserver REDACTED
nameserver 1.1.1.1
EOF
Verify Tailscale does not restore it on restart:
sudo systemctl restart tailscaled
sleep 5
cat /etc/resolv.conf # should still show the static content
Why a static file survives restart¶
With accept-dns=false (persisted as CorpDNS: false in Tailscale prefs), tailscaled does not write or manage /etc/resolv.conf. The static file is safe across reboots.
Removing the daemon.json workaround¶
If an interim Docker daemon.json DNS override was applied:
sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak
sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{}
EOF
sudo systemctl restart docker
Docker then inherits resolvers from the host's /etc/resolv.conf automatically. Verify inside a container:
docker exec <container> cat /etc/resolv.conf
# ExtServers line should show the LAN resolvers, not 100.100.100.100
Trade-off¶
accept-dns=false disables Tailscale MagicDNS short-name resolution (e.g. caneast-site1-node3 without the .ts.net suffix) for Tailscale peers on this node. On caneast-site1-node2 this was already non-functional before the change. Tailscale peer-to-peer connectivity (IP-based) is unaffected.
Rollback¶
sudo tailscale set --accept-dns=true
sudo cp /etc/resolv.conf.tailscale-pre-WI305 /etc/resolv.conf
sudo cp /etc/docker/daemon.json.pre-WI305 /etc/docker/daemon.json
sudo systemctl restart docker
Validation checklist¶
tailscale debug prefs | grep CorpDNSshowsfalsenslookup google.comon the host returns a result, server is REDACTEDdocker exec <container> cat /etc/resolv.confshows LAN resolvers in ExtServerstailscale statusshows node still connected- Key services respond: Homepage (3000), Uptime Kuma (3001), Grafana (3002)