AdGuard Home replaces your router's DNS with one that filters ads, trackers and malware at the network level, and gives you per-device dashboards and query logs. It's the drop-in alternative to Pi-hole that people switch to because the UI is nicer and setup is one container.
What it is
A DNS resolver that applies blocklists before the query leaves your network. You point each device (or your router, which covers everything) at it, and every ad domain resolves to nothing. Per-client settings mean the kids' devices can get stricter filtering than yours.
Before you start
- DNS needs port 53. Bind it with
network_mode: hostor map53:53/tcpand53:53/udp— only mapping 53/tcp gives you a resolver that mysteriously fails on half your devices. - Change your router's DHCP pool to hand out the AdGuard IP as DNS, or set it manually on every device. The container running isn't the point; the clients pointing at it is.
- Keep your router as a secondary DNS. If AdGuard goes down, a fallback avoids a dead network — but it also unblocks ads, so use it deliberately.
1 — Write the compose file
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
network_mode: host
volumes:
- ./work:/opt/adguardhome/work
- ./conf:/opt/adguardhome/conf
healthcheck:
test: ["CMD", "/opt/adguardhealthcheck"]
interval: 30s
timeout: 5s
retries: 3
2 — Start it and complete the wizard
mkdir -p ~/services/adguard/{work,conf}
cd ~/services/adguard
docker compose up -d
docker compose logs -f adguardhome | grep -i "started\|dns"
3 — First-run setup
- Set the DNS upstream resolvers. Cloudflare (
1.1.1.1,1.0.0.1) and Quad9 (9.9.9.9) are the common picks; use94.140.14.14if you want the filtering that Quad9 adds on top. - Leave Blocklists defaults on. AdGuard DNS filter plus AdGuard default filter will block a surprising amount already; be ready to unbreak a site or two.
- In Clients, set your router as a client and apply per-device rules — that's the payoff over a global blocklist.
- Enable Query log retention but keep it short. Long retention is a privacy liability and grows the SQLite file without adding value.
- Update your router's DHCP to point at the AdGuard host. Test with
dig @adguard-host example.comand confirm a known ad domain returns0.0.0.0.
4 — Daily use
# is DNS actually filtering?
nslookup doubleclick.net $(hostname -I | awk '{print $1}')
# container health + quick stats
docker stats --no-stream adguardhome