Files
homelab-optimized/docs/networking/ADGUARD_DNS_MESH.md
Gitea Mirror Bot 61e87cd8d4
Some checks failed
Documentation / Deploy to GitHub Pages (push) Has been cancelled
Documentation / Build Docusaurus (push) Has been cancelled
Sanitized mirror from private repository - 2026-04-16 09:20:47 UTC
2026-04-16 09:20:47 +00:00

5.6 KiB

AdGuard DNS Mesh

Network-wide ad blocking and split-horizon DNS for all Headscale mesh nodes.

Architecture

                    Headscale (Calypso)
                    pushes DNS config to all nodes
                           │
                    ┌──────┴──────┐
                    ▼              ▼
          Calypso AdGuard    Atlantis AdGuard
          100.103.48.78:53   100.83.230.112:53
          (primary)          (backup)
                    │              │
                    └──────┬──────┘
                           ▼
                  All Tailscale nodes
                  (ad blocking + split-horizon)

How It Works

  1. Headscale pushes two DNS nameservers (Tailscale IPs) to all connected nodes
  2. Each node resolves DNS through Calypso AdGuard (primary) or Atlantis AdGuard (fallback)
  3. AdGuard provides ad blocking (filter lists) and split-horizon DNS (38 rewrites for internal services)
  4. Upstream DNS uses DoH: AdGuard DNS, Cloudflare, Quad9, Google, LibreDNS

Headscale DNS Config

File: /volume1/docker/headscale/config/config.yaml on Calypso Repo: hosts/synology/calypso/headscale-config.yaml

dns:
  magic_dns: true
  base_domain: tail.vish.gg
  nameservers:
    global:
      - 100.103.48.78    # Calypso AdGuard (Tailscale IP)
      - 100.83.230.112   # Atlantis AdGuard (Tailscale IP)

Using Tailscale IPs (not LAN IPs) ensures remote nodes (Seattle, Jellyfish, mobile devices, GL.iNet routers) can reach the DNS servers.

Split-Horizon DNS Rewrites (38 rules)

Both Calypso and Atlantis AdGuard instances have identical rewrites:

Domain Answer Purpose
*.vish.gg 100.85.21.51 Wildcard → matrix-ubuntu (NPM)
pt.vish.gg 192.168.0.154 Portainer (direct, not proxied)
sso.vish.gg 192.168.0.154 Authentik SSO
git.vish.gg 192.168.0.154 Gitea
dash.vish.gg 192.168.0.154 Homarr dashboard
gf.vish.gg 192.168.0.154 Grafana
headscale.vish.gg 192.168.0.250 Headscale server
derp.vish.gg 192.168.0.250 DERP relay (Calypso)
derp-atl.vish.gg 192.168.0.200 DERP relay (Atlantis)
derp-sea.vish.gg 100.82.197.124 DERP relay (Seattle)
turn.thevish.io 192.168.0.200 TURN server
*.tail.vish.gg per-node Tailscale IP MagicDNS node records (12)
*.vish.local per-node Tailscale IP Local aliases (8)
*.crista.home per-node Tailscale IP Crista network aliases (2)
*.thevish.io 100.85.21.51 thevish.io wildcard
*.crista.love 100.85.21.51 crista.love wildcard

Node Status

Node accept-dns Split-Horizon Ad Blocking Notes
homelab-vm enabled Yes Yes
atlantis enabled Yes Yes
seattle enabled Yes Yes Remote VPS
nuc enabled Yes Yes
pi-5 enabled Yes Yes
matrix-ubuntu enabled Yes Yes
jellyfish enabled Yes Yes No dig/nslookup, verified via python
calypso enabled N/A N/A IS the AdGuard server; Synology can't override resolv.conf
setillo enabled No Yes (local) Synology limitation; has own local AdGuard
guava N/A N/A Via LAN TrueNAS app; uses Calypso AdGuard at 192.168.0.250 on LAN

Mobile devices, GL.iNet routers, and Home Assistant use default --accept-dns=true and inherit DNS from Headscale automatically.

Rollback

Immediate (~2 min) - revert Headscale DNS to LAN IPs

ssh calypso 'sed -i "s/100.103.48.78/192.168.0.250/" /volume1/docker/headscale/config/config.yaml && \
             sed -i "s/100.83.230.112/192.168.68.100/" /volume1/docker/headscale/config/config.yaml'
# Restart headscale via Portainer or:
ssh calypso '/usr/local/bin/docker restart headscale'

Per-node override

# On the affected node:
tailscale set --accept-dns=false

Nuclear - bypass Tailscale DNS entirely

echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf

Symptoms

Symptom Cause Fix
DNS resolution hangs Both AdGuard containers down Restart AdGuard on Calypso/Atlantis
Wrong split-horizon (public IP) Rewrite missing on responding AdGuard Add missing rewrite via AdGuard UI
One node can't resolve Tailscale tunnel down tailscale ping calypso to diagnose

AdGuard Instances

Instance Host LAN IP Tailscale IP Web UI Role
Calypso Synology 192.168.0.250:9080 100.103.48.78:9080 http://192.168.0.250:9080 Primary
Atlantis Synology 192.168.0.200:9080 100.83.230.112:9080 http://192.168.0.200:9080 Backup
NUC Intel NUC 192.168.68.100:9080 100.72.55.21:9080 http://192.168.68.100:9080 Local (Concord subnet)
Setillo Synology 192.168.69.x 100.125.0.20 host network Local (remote site)

Maintenance

When adding a new split-horizon rewrite, add it to both Calypso and Atlantis AdGuard instances to keep them in sync. Use the AdGuard web UI or API:

# Calypso (via MCP tool or API)
curl -u vish:PASSWORD -X POST http://192.168.0.250:9080/control/rewrite/add \
  -H 'Content-Type: application/json' \
  -d '{"domain":"new.vish.gg","answer":"192.168.0.154"}'

# Atlantis (same, different host)
curl -u vish:PASSWORD -X POST http://192.168.0.200:9080/control/rewrite/add \
  -H 'Content-Type: application/json' \
  -d '{"domain":"new.vish.gg","answer":"192.168.0.154"}'

Deployed: 2026-03-31 Config: hosts/synology/calypso/headscale-config.yaml