docker.recipes
Networking9 min read

Local DNS with Pi-hole and AdGuard Home

Set up network-wide ad blocking and custom local DNS records using Pi-hole or AdGuard Home in Docker.

01Why Run Local DNS?

A local DNS server provides several benefits for your home network and self-hosted services: **Ad blocking:** • Block ads and trackers at the DNS level • Works for all devices without installing anything • Blocks in-app ads that browser extensions miss **Local DNS records:** • Access services by name: nextcloud.home instead of 192.168.1.50:8080 • No need to remember IP addresses and ports • Internal services don't need public DNS **Privacy:** • DNS queries stay on your network • Use encrypted upstream DNS (DoH/DoT) • See exactly what's querying what

Pi-hole and AdGuard Home are both excellent choices. Pi-hole has more community blocklists; AdGuard has a more modern UI and built-in DoH/DoT.

02Pi-hole Setup

Pi-hole is the original DNS sinkhole for ad blocking. It's lightweight and well-documented with a huge community. **Key features:** • Extensive blocklist ecosystem • Query logging and statistics • DHCP server (optional) • Group management for different devices The container needs specific network settings to work as a DNS server:
1services:
2 pihole:
3 image: pihole/pihole:latest
4 container_name: pihole
5 hostname: pihole
6 environment:
7 - TZ=Europe/London
8 - WEBPASSWORD=${PIHOLE_PASSWORD}
9 # Use Cloudflare DNS upstream
10 - PIHOLE_DNS_=1.1.1.1;1.0.0.1
11 - DNSSEC=true
12 - QUERY_LOGGING=true
13 volumes:
14 - ./pihole/etc-pihole:/etc/pihole
15 - ./pihole/etc-dnsmasq.d:/etc/dnsmasq.d
16 ports:
17 - "53:53/tcp"
18 - "53:53/udp"
19 - "8053:80/tcp" # Web UI
20 cap_add:
21 - NET_ADMIN # Required for DHCP (optional)
22 restart: unless-stopped
23
24# Access web UI at http://your-server:8053/admin

Port 53 may conflict with systemd-resolved on Linux. Disable it first: sudo systemctl disable --now systemd-resolved

03AdGuard Home Setup

AdGuard Home is a newer alternative with a modern interface and built-in encrypted DNS support. It's particularly good if you want DNS-over-HTTPS or DNS-over-TLS. **Advantages over Pi-hole:** • Native DoH/DoT/DoQ support • Per-client settings • Modern React-based UI • Built-in HTTPS for admin panel • Active development
1services:
2 adguard:
3 image: adguard/adguardhome:latest
4 container_name: adguard
5 environment:
6 - TZ=Europe/London
7 volumes:
8 - ./adguard/work:/opt/adguardhome/work
9 - ./adguard/conf:/opt/adguardhome/conf
10 ports:
11 - "53:53/tcp"
12 - "53:53/udp"
13 - "3000:3000/tcp" # Initial setup UI
14 - "8080:80/tcp" # Web UI after setup
15 - "443:443/tcp" # HTTPS (optional)
16 - "853:853/tcp" # DNS-over-TLS
17 restart: unless-stopped
18
19# First run: access http://your-server:3000 for setup wizard
20# After setup: http://your-server:8080

AdGuard Home's first-run wizard configures everything. Choose your admin credentials and upstream DNS servers during setup.

04Adding Local DNS Records

The real power of local DNS is creating records for your self-hosted services. Access them by name instead of IP:port. **In Pi-hole:** 1. Go to Local DNS → DNS Records 2. Add entries like: nextcloud.home → 192.168.1.50 **In AdGuard Home:** 1. Go to Filters → DNS Rewrites 2. Add entries with domain and IP **Note:** This gives you the IP, but not the port. For full name:port mapping, use a reverse proxy.
1# Pi-hole: Add via command line or /etc/pihole/custom.list
2# Format: IP HOSTNAME
3192.168.1.50 nextcloud.home
4192.168.1.50 jellyfin.home
5192.168.1.50 homeassistant.home
6192.168.1.51 nas.home
7
8# Or add via dnsmasq config (/etc/dnsmasq.d/custom.conf)
9address=/home/192.168.1.50 # All *.home goes to this IP
10address=/nextcloud.local/192.168.1.50
11
12# AdGuard: Configure in the web UI under Filters → DNS rewrites
13# Or edit AdGuardHome.yaml:
14filtering:
15 rewrites:
16 - domain: "*.home"
17 answer: 192.168.1.50

05Combining with Reverse Proxy

For the best experience, combine local DNS with a reverse proxy like Traefik or Caddy. This lets you: • Access services by name without ports (nextcloud.home instead of 192.168.1.50:8080) • Get HTTPS with local certificates • Manage routing in one place **Setup:** 1. Point all *.home to your Docker host in Pi-hole/AdGuard 2. Run Traefik/Caddy on ports 80/443 3. Configure routing rules for each service
1services:
2 # DNS - points *.home to this server
3 pihole:
4 image: pihole/pihole:latest
5 volumes:
6 - ./pihole:/etc/pihole
7 - ./dnsmasq:/etc/dnsmasq.d
8 ports:
9 - "53:53/tcp"
10 - "53:53/udp"
11 - "8053:80"
12
13 # Reverse Proxy - handles *.home requests
14 traefik:
15 image: traefik:v3.0
16 command:
17 - --providers.docker=true
18 - --entrypoints.web.address=:80
19 ports:
20 - "80:80"
21 volumes:
22 - /var/run/docker.sock:/var/run/docker.sock:ro
23
24 # Service with automatic routing
25 nextcloud:
26 image: nextcloud:latest
27 labels:
28 - "traefik.enable=true"
29 - "traefik.http.routers.nextcloud.rule=Host(`nextcloud.home`)"
30 volumes:
31 - ./nextcloud:/var/www/html

Add 'address=/home/192.168.1.50' to dnsmasq to route ALL *.home domains to your Docker host.

06DHCP Integration

For DNS to work network-wide, devices need to use your DNS server. You have two options: **Option 1: Configure your router** • Set DHCP to distribute your Pi-hole/AdGuard IP as DNS • All devices automatically use it • Easiest approach if your router supports it **Option 2: Run DHCP on Pi-hole/AdGuard** • Pi-hole/AdGuard becomes your DHCP server • Disable DHCP on your router • Gives you more control and per-device tracking **Option 3: Manual configuration** • Set DNS manually on devices • Useful for testing or specific devices
1# Pi-hole with DHCP enabled
2services:
3 pihole:
4 image: pihole/pihole:latest
5 environment:
6 - PIHOLE_DNS_=1.1.1.1;1.0.0.1
7 - WEBPASSWORD=${PIHOLE_PASSWORD}
8 # Enable DHCP
9 - DHCP_ACTIVE=true
10 - DHCP_START=192.168.1.100
11 - DHCP_END=192.168.1.200
12 - DHCP_ROUTER=192.168.1.1
13 volumes:
14 - ./pihole:/etc/pihole
15 - ./dnsmasq.d:/etc/dnsmasq.d
16 ports:
17 - "53:53/tcp"
18 - "53:53/udp"
19 - "67:67/udp" # DHCP
20 - "8053:80"
21 cap_add:
22 - NET_ADMIN # Required for DHCP
23 network_mode: host # Recommended for DHCP

Never run two DHCP servers on the same network. Disable your router's DHCP before enabling it in Pi-hole/AdGuard.

07Managing Blocklists

Both Pi-hole and AdGuard come with default blocklists, but you can add more for better coverage. Be careful not to over-block—it can break legitimate services. **Recommended blocklists:** • Steven Black's hosts (comprehensive) • OISD (optimized, fewer false positives) • Energized Protection (various levels) **Testing and whitelisting:** 1. Check query logs when something breaks 2. Find the blocked domain 3. Add to whitelist 4. Common whitelists: s.youtube.com, cdn.optimizely.com
1# Pi-hole: Add blocklists via web UI or gravity command
2pihole -g # Update blocklists
3
4# Popular blocklist URLs to add:
5# https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
6# https://dbl.oisd.nl/
7# https://v.firebog.net/hosts/lists.php?type=tick
8
9# Whitelist domains
10pihole -w s.youtube.com
11pihole -w cdn.optimizely.com
12
13# AdGuard: Add via Filters → DNS Blocklists
14# Or edit AdGuardHome.yaml:
15filters:
16 - enabled: true
17 url: https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt
18 name: AdGuard DNS filter

Start with fewer blocklists and add more gradually. The OISD list is a great single list that balances blocking with compatibility.