Tailscale docker debug
Picks and Shovels for digging AI
npx -y skills add rshade/agent-skills --skill tailscale-docker-debugAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Diagnose Tailscale connectivity and DNS failures inside Docker containers. Detects userspace vs kernel mode, DNS resolver conflicts, TUN interface issues, and multi-tailnet mismatches. Use when Tailscale peers connect by IP but MagicDNS names fail, or when containers fall back to userspace networking unexpectedly. Also use when a customer deploys Tailscale in Docker or Podman and reports DNS not working, or when migrating from docker run to docker compose breaks TUN functionality.
SKILL.md
5.6 KB, as published. Nobody here has run it
Tailscale Docker Debug
Diagnose and fix Tailscale connectivity and DNS issues inside Docker containers. Runs six sequential checks covering the full debugging chain from container runtime mode through MagicDNS resolution.
What this skill does
- Detects whether the container runs in kernel or userspace mode.
- Verifies the TUN interface exists with a Tailscale IP.
- Checks the DNS resolver chain for misrouted queries.
- Confirms 100.100.100.100 routes through the container's Tailscale.
- Detects multi-tailnet conflicts between host and container.
- Validates MagicDNS end-to-end with a name resolution test.
Common triggers
- Customer reports "DNS doesn't work" inside Docker/Podman containers
- Host on one tailnet, containers on a different tailnet
- Compose file has
NET_ADMINand/dev/net/tunbut Tailscale still runs in userspace mode - Migration from
docker runtodocker composebreaks TUN
Diagnostic workflow
Run each step in order. Stop at the first failure and apply the fix before continuing — later steps depend on earlier ones.
Step 1 — Detect container runtime mode
docker logs <container> 2>&1 | grep -iE "tun|userspace|netstack"
Pass: Logs show tun "tailscale0" — kernel mode. Proceed to step 2.
Fail: Logs show --tun=userspace-networking. The official
tailscale/tailscale image defaults to userspace via containerboot
regardless of capabilities.
Fix: Set TS_USERSPACE=false in environment. Use devices: (not
volumes:) for /dev/net/tun. Add cap_add: [NET_ADMIN, SYS_MODULE].
See references/compose-configuration-matrix.md for the full config.
Step 2 — Verify TUN interface exists
docker exec <container> ip addr show tailscale0
Pass: Interface shows a 100.x.y.z/32 address. Proceed to step 3.
Fail: No tailscale0 interface even with TS_USERSPACE=false.
Fix: Change /dev/net/tun from volumes: to devices: in compose.
Verify the device exists in the container with major/minor 10, 200.
Confirm cap_add: [NET_ADMIN, SYS_MODULE].
Step 3 — Check DNS resolver chain
docker exec <container> cat /etc/resolv.conf
Examine three things:
nameserver— expect127.0.0.11(Docker embedded DNS)- External servers — should forward to
100.100.100.100 search— should match the container's tailnet, not the host's
Fail indicators:
ExtServers: [host(127.0.0.53)]— Docker forwards to host systemd-resolved instead of Tailscale- Search domain belongs to a different tailnet
Fix: Add dns: [100.100.100.100] to each service in compose.
See references/dns-resolver-chain.md for the full resolution path.
Step 4 — Verify 100.100.100.100 routing
docker exec <container> ip route get 100.100.100.100
Pass: Routes via tailscale0 or a local interface.
Fail: Routes via eth0 or Docker gateway (e.g., via 172.18.0.1)
— DNS queries escape to the host.
docker exec <container> ss -ulnp | grep 100.100
Fix: This is a symptom of step 1 (userspace mode) or step 2 (missing TUN). Fix those first.
Step 5 — Detect multi-tailnet conflict
docker exec <container> tailscale status | head -1
docker exec <container> grep search /etc/resolv.conf
Compare the tailnet shown in tailscale status against the search
domain in resolv.conf.
Fail: Search domain (inherited from host) doesn't match the
container's tailnet. Example: host on tucuxi-lungfish.ts.net,
container on tail9a660c.ts.net.
Fix: Add dns_search: [<correct-tailnet>.ts.net] in compose, or
use FQDNs exclusively. Root cause is Docker inheriting the host's
resolv.conf search domain.
Step 6 — Verify MagicDNS end-to-end
docker exec <container> tailscale dns status | head -3
Pass: Shows Tailscale DNS: enabled.
Fail: Shows Tailscale DNS: disabled.
Fix: Set TS_ACCEPT_DNS=true in environment.
Final validation:
docker exec <container> nslookup <peer>.<tailnet>.ts.net 100.100.100.100
docker exec <container> ping -c 1 <peer>.<tailnet>.ts.net
If both succeed, MagicDNS is working correctly inside the container.
Error handling
Do not silently skip a failed check. Report the specific failure with
the fix before continuing. If a fix requires restarting the container,
instruct the user to recreate it (docker compose up -d) and rerun the
workflow from step 1.
The log message getting OS base config is not supported is non-fatal
— Tailscale cannot read the container's DNS config directly. Fix DNS
via the compose file instead.
References
references/compose-configuration-matrix.md— minimum compose config for kernel-mode Tailscale with MagicDNS, setting-by-setting breakdownreferences/dns-resolver-chain.md— full DNS resolution path through Docker embedded DNS, short name vs FQDN conflictreferences/common-failures.md— symptom-based lookup table with root causes and fixes