How to Self-Host AdGuard Home: DNS Ad Blocker (Pi-hole Alternative) 2026
TL;DR
AdGuard Home (GPL 3.0, ~24K GitHub stars, Go) is a network-wide DNS ad and tracker blocker — every device on your network (phone, TV, smart home) gets ads blocked without installing anything per-device. Compare AdGuard Home vs Pi-hole: AdGuard Home has a better UI, built-in DNS-over-HTTPS/TLS, per-client rules, and parental controls; Pi-hole has a larger community and more integrations. Both work. AdGuard Home wins for new installs in 2026.
Key Takeaways
- AdGuard Home: GPL 3.0, ~24K stars — network-wide DNS blocker, better than Pi-hole UI
- DNS-over-HTTPS/TLS: Built-in encrypted DNS server (no need for external dnscrypt-proxy)
- Per-device rules: Allow YouTube on the TV but block it everywhere else
- Parental controls: Block adult content or specific categories by device
- DHCP server: Can replace your router's DHCP (assigns DNS automatically)
- Statistics: Detailed query logs, blocked per domain, per client
AdGuard Home vs Pi-hole
| Feature | AdGuard Home | Pi-hole |
|---|---|---|
| License | GPL 3.0 | EUPL 1.2 |
| GitHub Stars | ~24K | ~48K |
| Language | Go | PHP + Python |
| UI | Modern, polished | Functional |
| DNS-over-HTTPS | Built-in | Via dnscrypt-proxy |
| DNS-over-TLS | Built-in | Via Unbound |
| Per-client rules | Yes | Limited (groups) |
| Parental controls | Yes | Via external lists |
| DHCP server | Yes | Yes |
| Regex blocking | Yes | Yes |
| RAM | ~30MB | ~150MB |
| Raspberry Pi | Yes | Yes (default) |
Part 1: Docker Setup
# docker-compose.yml
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
network_mode: host # Required for DNS (port 53)
volumes:
- adguard_work:/opt/adguardhome/work
- adguard_conf:/opt/adguardhome/conf
# network_mode: host means ports aren't mapped here
volumes:
adguard_work:
adguard_conf:
docker compose up -d
Visit http://your-server:3000 → setup wizard.
Without Host Networking (if port 53 is taken)
services:
adguardhome:
image: adguard/adguardhome:latest
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "3000:3000/tcp" # Admin UI
- "80:80/tcp" # HTTP
- "443:443/tcp" # HTTPS
- "853:853/tcp" # DNS-over-TLS
volumes:
- adguard_work:/opt/adguardhome/work
- adguard_conf:/opt/adguardhome/conf
If port 53 is in use (systemd-resolved on Ubuntu):
# Disable systemd-resolved's DNS stub:
sudo sed -i 's/#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf
sudo systemctl restart systemd-resolved
Part 2: HTTPS Web UI with Caddy
adguard.yourdomain.com {
reverse_proxy localhost:3000
}
Part 3: Setup Wizard
- Visit
http://your-server:3000 - Set admin username and password
- Set listen interfaces
- Finish setup
Then visit http://your-server:3000/install or the main dashboard.
Part 4: Point Your Network at AdGuard Home
Option A: Router DNS (Entire Network)
Log into your router → DHCP settings → Set DNS server to your AdGuard Home IP:
DNS Server 1: 192.168.1.X (your server's LAN IP)
DNS Server 2: 1.1.1.1 (Cloudflare as fallback)
Every device that uses DHCP now uses AdGuard Home for DNS.
Option B: Per-Device DNS
Configure specific devices to use your server's IP as DNS:
# macOS:
# System Preferences → Network → Advanced → DNS → add your server IP
# iPhone:
# Settings → Wi-Fi → [Network] → Configure DNS → Manual → add IP
# Linux:
# /etc/resolv.conf or systemd-resolved configuration
Option C: AdGuard Home as DHCP Server
Replace your router's DHCP with AdGuard Home:
- Settings → DHCP → Enable DHCP server
- Set IP range, gateway, DNS (itself: 192.168.1.X)
- Disable DHCP on your router
Every device auto-receives AdGuard Home as DNS.
Part 5: Blocklists
Settings → Filters → Blocklists → Add Blocklist
Recommended lists:
AdGuard DNS filter (built-in — good default)
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts # Steven Black's combined list
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/pro.txt # HaGeZi Pro
https://adaway.org/hosts.txt # Mobile ads
https://raw.githubusercontent.com/DandelionSprout/adfilt/master/GameConsoleAdblockList.txt # Gaming
After adding lists: Settings → Filters → Update Now
Custom block rules:
# /etc/adguardhome/conf/AdGuardHome.yaml
# Or in the UI: Filters → Custom Filtering Rules
# Block a domain:
||analytics.example.com^
# Allow a domain (override blocklist):
@@||youtube.com^$important
# Block all subdomains:
||*.ads.example.com^
# Regex block:
/tracking|analytics|telemetry/
Part 6: DNS-over-HTTPS (DoH)
Enable encrypted DNS for privacy:
- Settings → Encryption → Enable HTTPS / DNS-over-HTTPS
- Add your domain certificate (or let AdGuard use Let's Encrypt)
- DoH URL:
https://adguard.yourdomain.com/dns-query
Configure on clients:
- iOS 14+: Settings → Wi-Fi → DNS → DNS-over-HTTPS
- Firefox: Network Settings → Enable DNS-over-HTTPS → Custom → your URL
- macOS:
.mobileconfigprofile installation
Or use DNS-over-TLS on port 853: adguard.yourdomain.com:853
Part 7: Per-Client Rules
Set different rules for different devices:
- Client Settings → + Add Client
- Identify by: MAC address, IP, or client name (from DHCP)
- Per-client settings:
- Use custom upstreams: Point to a different DNS resolver
- Safe search: Force safe search on Google/YouTube
- Parental control: Block adult content categories
- Custom filter rules: Allow/block specific domains only for this device
Example setup:
TV (192.168.1.10): Block social media, allow streaming services
Kids' iPad (MAC: AA:BB:CC:DD:EE:FF): Parental control: on, safe search: on
Work laptop: No restrictions
Part 8: Query Log and Statistics
Dashboard → Statistics:
- Total DNS queries per day
- % blocked
- Top blocked domains
- Top clients by query count
- Top queried domains
Query Log → Filter by client, status, domain:
# Find what a specific device is querying:
Filter: client = 192.168.1.15
# Find all blocked queries:
Filter: status = blocked
# Find if a domain was blocked or allowed:
Filter: domain = analytics.google.com
Maintenance
# Update AdGuard Home:
docker compose pull
docker compose up -d
# Logs:
docker compose logs -f adguardhome
# Backup config:
tar -czf adguard-config-$(date +%Y%m%d).tar.gz \
$(docker volume inspect adguardhome_adguard_conf --format '{{.Mountpoint}}')
# Update blocklists:
# Filters → Update Now (or set auto-update schedule)
# Check DNS resolution:
dig @192.168.1.X ads.google.com # Should return 0.0.0.0
dig @192.168.1.X google.com # Should return real IP
See all open source privacy and networking tools at OSSAlt.com/categories/privacy.