Skip to content

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)

  1. Tailscale registered 100.100.100.100 as the global DNS server in both /etc/resolv.conf and systemd-resolved via D-Bus.
  2. The Tailscale control plane could not push DNS config to the device (health check: exit status 1), so the proxy had no upstream resolvers.
  3. All DNS queries returned SERVFAIL -- from the host and from Docker containers.

Permanent fix

Apply on the affected node:

sudo tailscale set --accept-dns=false

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 CorpDNS shows false
  • nslookup google.com on the host returns a result, server is REDACTED
  • docker exec <container> cat /etc/resolv.conf shows LAN resolvers in ExtServers
  • tailscale status shows node still connected
  • Key services respond: Homepage (3000), Uptime Kuma (3001), Grafana (3002)