What is AdGuard Home?
AdGuard Home is a network-wide ad and tracker blocker that works as a DNS server. Point your router at it and every device on the network, including phones, smart TVs and game consoles, gets ads, trackers and malware domains blocked without installing anything. It also offers encrypted upstream DNS, per-client rules, parental controls and an optional DHCP server. AdGuard Home is open source under the GPL-3.0 license.
Requirements
- Any small Linux machine. A Raspberry Pi or a 1 vCPU VM with 256 MB of RAM handles a household easily.
- Docker Engine and Docker Compose v2.
- A static LAN IP for the server (set a DHCP reservation in your router), because every device will send DNS queries to it.
Step 1: Prepare the server
This guide assumes Ubuntu 24.04 with Docker installed from the official Docker Engine guide.
Ubuntu's systemd-resolved already listens on port 53, so Docker cannot bind it. The official AdGuard Home docs fix this by disabling the stub listener:
sudo mkdir -p /etc/systemd/resolved.conf.d
printf '[Resolve]\nDNS=127.0.0.1\nDNSStubListener=no\n' | sudo tee /etc/systemd/resolved.conf.d/adguardhome.conf
sudo mv /etc/resolv.conf /etc/resolv.conf.backup
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemctl reload-or-restart systemd-resolved
Then create the folders:
mkdir -p ~/adguardhome/work ~/adguardhome/conf && cd ~/adguardhome
Step 2: Create the Docker Compose file
Save this as docker-compose.yml:
services:
adguardhome:
image: adguard/adguardhome:v0.107.79
container_name: adguardhome
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "3000:3000/tcp"
# Encrypted DNS, once you have a certificate:
# - "853:853/tcp"
# - "853:853/udp"
volumes:
- ./work:/opt/adguardhome/work
- ./conf:/opt/adguardhome/conf
The two volumes keep the query log, statistics and filter lists (work) and the AdGuardHome.yaml configuration (conf). Only DNS and the web UI are published. Add the encrypted DNS ports when you need them.
If you want AdGuard Home to be your DHCP server too, the official docs require host networking instead of port mappings: replace the ports: block with network_mode: host.
Step 3: Start and open the app
docker compose up -d
Open http://YOUR_SERVER_IP:3000 to start the setup wizard. On the "Admin Web Interface" screen, set the port to 3000 so it matches the Compose mapping (the default of 80 is not published here). Leave the DNS server on port 53, create the admin username and a long password, and finish.
Now sign in and open Filters, DNS blocklists to see the default AdGuard DNS filter. Under Settings, DNS settings, pick encrypted upstreams such as https://dns.quad9.net/dns-query. Finally, set your router's DHCP DNS server to the AdGuard Home IP, or point one device at it first to test.
Step 4: Put it behind HTTPS
The admin panel can go behind Caddy on the same host:
adguard.example.com {
reverse_proxy 127.0.0.1:3000
}
Once that works, change the UI mapping to "127.0.0.1:3000:3000/tcp". Docker-published ports bypass ufw, so firewall rules alone do not hide the panel. The same applies to port 53: on a home network behind NAT that is fine, but on a VPS bind it to a VPN address, for example "100.64.0.10:53:53/udp" for Tailscale, so you do not run an open resolver. For DNS-over-HTTPS or DNS-over-TLS, add a certificate under Settings, Encryption settings and publish 853.
Backups and upgrades
Everything lives in the two folders. A short stop gives a consistent copy:
docker compose stop && tar czf adguard-$(date +%F).tgz conf work && docker compose start
conf/AdGuardHome.yaml alone restores all settings, clients and filter choices. To upgrade, change the image tag and run:
docker compose pull && docker compose up -d
Use the image tag for updates; the built-in updater in the web UI is meant for the standalone binary, not Docker.
Troubleshooting
- "address already in use" on port 53:
systemd-resolvedis still running its stub listener. Recheck Step 1, or find the process withsudo ss -lunp | grep :53. - Ads still appear on one device: the browser or device uses its own DNS-over-HTTPS resolver. Turn off "secure DNS" in the browser settings so queries go through AdGuard Home.
- Some sites break: check Query Log for the blocked domain and add it to the allowlist with one click.
- Server itself cannot resolve names: the container is down while the host points at
127.0.0.1. Start it again, or add a fallback upstream in theresolved.conf.dfile.
Next steps
Add more blocklists, set per-client rules for kids' devices, enable DNS-over-HTTPS for phones outside the house through a VPN, and run a second instance on another machine so DNS keeps working during maintenance.
Spotted something out of date? Tell us and we will update the guide.