DEV Community

Cover image for Run NextDNS and Tailscale together without breaking MagicDNS
pratikbin
pratikbin

Posted on

Run NextDNS and Tailscale together without breaking MagicDNS

If you ssh into a tailnet host by name and your terminal answers Unknown host, NextDNS is probably eating your queries before Tailscale sees them.

Here's why, and a one-command fix.

The conflict

NextDNS ships an Apple Configuration Profile (apple.nextdns.io) that installs a system-wide DNS-over-HTTPS handler. The profile is tidy, signed, and ten-second setup — but it captures every query, including ones meant for your tailnet.

Tailscale's MagicDNS lives at 100.100.100.100. Names like mybox.tailnet-name.ts.net only resolve there. NextDNS doesn't know your tailnet, so it asks the public DNS root, gets NXDOMAIN, and your shell gives up.

The usual macOS escape hatch — dropping a file in /etc/resolver/ — looks like it works:

echo "nameserver 100.100.100.100" | sudo tee /etc/resolver/your-tailnet.ts.net
Enter fullscreen mode Exit fullscreen mode

scutil --dns even shows the new resolver. But Configuration Profiles outrank /etc/resolver, so the file is ignored. Silent failure.

The fix

Replace the profile with NextDNS's CLI client. The CLI supports per-domain forwarders. Same profile, same blocklists, same dashboard — plus split DNS.

1. Remove the Apple profile

System Settings → General → Device Management → NextDNS → Remove

2. Install the CLI

brew install nextdns/tap/nextdns
Enter fullscreen mode Exit fullscreen mode

3. Install with a forwarder for your tailnet

sudo nextdns install \
  -profile YOUR_PROFILE_ID \
  -forwarder 'your-tailnet.ts.net=100.100.100.100' \
  -forwarder 'ts.net=100.100.100.100' \
  -report-client-info
Enter fullscreen mode Exit fullscreen mode

The format is DOMAIN=SERVER, not the dnsmasq-style /DOMAIN/SERVER — the CLI rejects slashes with a confusing "not a valid IP address" error.

The second forwarder catches MagicDNS short names and any other *.ts.net host. Drop it if you only want one tailnet.

4. Verify

dig mybox.your-tailnet.ts.net    # → 100.x.y.z (Tailscale)
dig example.com                   # → public IP via NextDNS
ping mybox.your-tailnet.ts.net    # works in your shell, not just dig
Enter fullscreen mode Exit fullscreen mode

Last check matters. dig ignores the resolver chain; ping, curl, and your apps don't. If both pass, you're done.

Why this works

The NextDNS daemon listens on 127.0.0.1:53 and becomes the system resolver. For each query it checks forwarders first, then falls back to the NextDNS DoH endpoint. Tailscale's 100.100.100.100 only needs to be reachable, which it is whenever tailscaled is running.

NextDNS keeps filtering, analytics, and parental controls. Tailscale keeps MagicDNS. No fights.

The takeaway

System-wide DNS-over-HTTPS profiles are convenient until you need split DNS. If you run a VPN with its own resolver — Tailscale, ZeroTier, WireGuard with dns= — switch to a daemon that supports forwarders. Five minutes, no recurring pain.

Top comments (0)