Kituwa IT · Self-hosting guides

Install AdGuard Home with Docker Compose

Network-wide ad blocking and DNS

DNSad blockingPi-hole alternative

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.

Category
Network & proxy
License
GPL-3.0
Needs
UDP/53 + host network
Image
adguard/adguardhome

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: host or map 53:53/tcp and 53: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

Command / configuration
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

With network_mode: host there's no port mapping — the container binds 53, 80 and 443 directly. It's the only reliable way to run a DNS server in Docker without fighting the port binding.

2 — Start it and complete the wizard

Command / configuration
mkdir -p ~/services/adguard/{work,conf}
cd ~/services/adguard
docker compose up -d
docker compose logs -f adguardhome | grep -i "started\|dns"

The setup wizard is at http://yourhost:3000 and only runs once. Bind the web interface to port 80 afterwards and the wizard URL stops responding — which is the intended behaviour, not a bug.

3 — First-run setup

  1. Set the DNS upstream resolvers. Cloudflare (1.1.1.1, 1.0.0.1) and Quad9 (9.9.9.9) are the common picks; use 94.140.14.14 if you want the filtering that Quad9 adds on top.
  2. 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.
  3. In Clients, set your router as a client and apply per-device rules — that's the payoff over a global blocklist.
  4. Enable Query log retention but keep it short. Long retention is a privacy liability and grows the SQLite file without adding value.
  5. Update your router's DHCP to point at the AdGuard host. Test with dig @adguard-host example.com and confirm a known ad domain returns 0.0.0.0.

4 — Daily use

Command / configuration
# is DNS actually filtering?
nslookup doubleclick.net $(hostname -I | awk '{print $1}')

# container health + quick stats
docker stats --no-stream adguardhome
Don't run a DHCP server in the same container setThere are containers that bundle DNS and DHCP together. Running one alongside your router's DHCP leads to two servers answering, clients picking either at random, and an intermittent internet outage you can't reproduce. Pick one device to be the DHCP server.

Help when you need it

Want help getting this running?

We can help with a supported Linux host, application setup, migration or troubleshooting. Contact us to confirm the software, scope and scheduling before ordering.

Related guides

← Browse all 30 guides · Back to top