Skip to main content

Overview

MagicDNS is Tailscale’s automatic DNS configuration feature that allows you to access devices and services on your tailnet using simple hostnames instead of IP addresses. When enabled, you can connect to services using names like service-name instead of 100.x.y.z. Benefits of MagicDNS:
  • Access services using memorable hostnames
  • Automatic DNS updates when IPs change
  • Split DNS support for accessing both tailnet and internet resources
  • HTTPS certificate integration with Tailscale’s certificate authority

Enabling MagicDNS

Network-Wide Configuration

  1. Navigate to the Tailscale DNS settings
  2. Click “Enable MagicDNS”
  3. Optionally configure a custom domain suffix (e.g., tail1234.ts.net)

Per-Service Configuration

Once MagicDNS is enabled on your network, configure individual services to use it:
services:
  tailscale:
    image: tailscale/tailscale:latest
    container_name: tailscale-${SERVICE}
    hostname: ${SERVICE}
    environment:
      - TS_AUTHKEY=${TS_AUTHKEY}
      - TS_STATE_DIR=/var/lib/tailscale
      - TS_ACCEPT_DNS=true  # Enable MagicDNS
      - TS_USERSPACE=false
      - TS_AUTH_ONCE=true
    volumes:
      - ./ts/state:/var/lib/tailscale
    devices:
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - net_admin
    restart: always

TS_ACCEPT_DNS Configuration

The TS_ACCEPT_DNS environment variable controls whether the Tailscale container accepts DNS configuration from your tailnet:
environment:
  - TS_ACCEPT_DNS=true
When enabled:
  • The container uses MagicDNS for hostname resolution
  • Services can be accessed via their Tailscale hostnames
  • DNS queries are split between tailnet and internet domains
When disabled (default):
  • The container uses the system’s default DNS
  • Manual DNS configuration may be required
In the service template and exit node configurations, TS_ACCEPT_DNS=true is commented out by default. Uncomment it when you want to use MagicDNS:
#- TS_ACCEPT_DNS=true # Uncomment when using MagicDNS

Using MagicDNS with Services

Accessing Services by Hostname

Once configured, access your services using their hostname:
# Instead of: http://100.64.1.5:8080
curl http://service-name:8080

# Or with your tailnet domain:
curl http://service-name.tail1234.ts.net:8080

HTTPS with MagicDNS

Combine MagicDNS with Tailscale’s HTTPS certificates for secure access:
services:
  tailscale:
    image: tailscale/tailscale:latest
    container_name: tailscale-${SERVICE}
    hostname: ${SERVICE}
    environment:
      - TS_AUTHKEY=${TS_AUTHKEY}
      - TS_STATE_DIR=/var/lib/tailscale
      - TS_ACCEPT_DNS=true
      - TS_CERT_DOMAIN=${TS_CERT_DOMAIN}  # e.g., service-name.tail1234.ts.net
      - TS_USERSPACE=false
    volumes:
      - ./ts/state:/var/lib/tailscale
    devices:
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - net_admin
    restart: always
Access via HTTPS:
curl https://service-name.tail1234.ts.net

DNS Configuration Patterns

Pattern 1: MagicDNS Only

Use Tailscale’s DNS exclusively:
environment:
  - TS_ACCEPT_DNS=true
# No custom dns: section

Pattern 2: MagicDNS with Fallback

Use MagicDNS but specify custom DNS servers as fallback:
environment:
  - TS_ACCEPT_DNS=true
dns:
  - ${DNS_SERVER}  # e.g., 1.1.1.1 or 8.8.8.8
The exit node example uses this pattern to ensure DNS resolution works even if MagicDNS is not configured.

Pattern 3: Custom DNS Only

Bypass MagicDNS and use specific DNS servers:
environment:
  - TS_ACCEPT_DNS=false
dns:
  - 1.1.1.1
  - 1.0.0.1

Split DNS Configuration

Configure custom DNS resolvers for specific domains in your Tailscale admin console:

Example: Internal Domain Resolution

  1. Go to DNS settings
  2. Under “Nameservers”, add a custom resolver:
    • Domain: internal.company.com
    • Nameserver: 100.64.1.10 (your internal DNS server)
  3. Queries for *.internal.company.com will route to your internal DNS
  4. All other queries use MagicDNS or public DNS

Docker Compose Integration

services:
  # Internal DNS server
  internal-dns:
    image: coredns/coredns:latest
    network_mode: service:tailscale
    depends_on:
      tailscale:
        condition: service_healthy
    volumes:
      - ./Corefile:/etc/coredns/Corefile

  tailscale:
    image: tailscale/tailscale:latest
    hostname: dns-server
    environment:
      - TS_AUTHKEY=${TS_AUTHKEY}
      - TS_ACCEPT_DNS=true
    volumes:
      - ./ts/state:/var/lib/tailscale
    devices:
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - net_admin
    restart: always

Troubleshooting

Hostnames Not Resolving

Check MagicDNS is enabled:
tailscale status --json | grep MagicDNSSuffix
Verify TS_ACCEPT_DNS:
docker exec tailscale-${SERVICE} env | grep TS_ACCEPT_DNS
Test DNS resolution inside the container:
docker exec tailscale-${SERVICE} nslookup other-service

DNS Resolution Conflicts

Problem: System DNS conflicts with Tailscale DNS Solution: Use the dns: section to explicitly set DNS servers:
dns:
  - 1.1.1.1
  - 1.0.0.1

Service-to-Service DNS

Problem: Containers can’t resolve each other’s MagicDNS names Solution: Ensure both containers have TS_ACCEPT_DNS=true and are on the same tailnet:
services:
  service-a:
    # ... tailscale configuration with TS_ACCEPT_DNS=true
  
  service-b:
    # ... tailscale configuration with TS_ACCEPT_DNS=true

DNS Leaks

When using exit nodes, verify DNS queries route through the exit node:
# Should show exit node's DNS resolver
curl https://dnsleaktest.com
If DNS is leaking:
environment:
  - TS_ACCEPT_DNS=true  # Force use of tailnet DNS
# Remove custom dns: section

Best Practices

Choose service hostnames that clearly identify their purpose:
  • plex-server instead of server1
  • home-assistant instead of ha
  • monitoring-grafana instead of grafana
Enable MagicDNS at the network level rather than per-device for consistency across all services.
When using split DNS or custom resolvers, document the configuration in your service README:
## DNS Configuration
- Internal domain: `*.internal.company.com``100.64.1.10`
- All other queries use MagicDNS
Always test DNS resolution after deploying a service:
# From another device on your tailnet
ping service-name
nslookup service-name

Examples from ScaleTail

Both the service template and exit node configurations include MagicDNS support as a commented option: From /source/services/tailscale-exit-node/compose.yaml:
environment:
  #- TS_ACCEPT_DNS=true # Uncomment when using MagicDNS
From /source/templates/service-template/compose.yaml:
environment:
  #- TS_ACCEPT_DNS=true # Uncomment when using MagicDNS
Simply uncomment this line and restart the service to enable MagicDNS.

Exit Nodes

Route traffic through your network

Custom Services

Create your own service configurations

Additional Reading

Build docs developers (and LLMs) love