Tech Digest

Networking

AdGuard Home

DNS blocker with encrypted upstreams, per-client rules and its own DoH/DoT server

NetworkingGPL-3.0Maturearm64 builds
Last reviewed Profile maintained against the project's own documentation
Operational load
2 / 5
Light
Idle memory
60 MB
typical use ~150 MB
Moving parts
1
containers in a normal deployment
Backup shape
Embedded key-value store
needs a dump or a stop

AdGuard Home is a filtering DNS server that blocks ads and trackers for a whole network and speaks DNS-over-HTTPS, DNS-over-TLS, DNS-over-QUIC and DNSCrypt both as a client and as a server. It replaces hosted filtering services and the Pi-hole plus cloudflared combination.

Our verdict on AdGuard Home#

Choose AdGuard Home over Pi-hole when you want encryption and per-client policy without adding a second daemon. It speaks DNS-over-HTTPS, DNS-over-TLS, DNS-over-QUIC and DNSCrypt as an upstream client and as a server, so your phone can use your home resolver over 853 from a cafe with no VPN, and there is no cloudflared or stubby sidecar to keep alive. Per-client configuration is first class: a client identified by IP, MAC, ClientID or its own DoH URL path can have different upstreams, different blocklists and different safe-search settings, all in the same UI. What you trade away is Pi-hole's group model and its much larger body of community lists and how-tos. Be honest about the version number too: eight years in it is still 0.107.x (0.107.79, August 2026), and the config carries a schema_version that bumps and rewrites your YAML on upgrade. It is dependable software that does not do semantic versioning.

Who AdGuard Home is for#

Choose it if

  • Anyone who wants encrypted upstreams out of the box instead of running cloudflared next to Pi-hole
  • A household with genuinely different policy per device, where a phone, a work laptop and a kid's tablet each need their own upstreams and lists
  • Remote clients: exposing DoT on 853 or DoH on 443 lets a laptop keep your filtering off the LAN, which Pi-hole cannot do alone
  • Router and NAS owners, since builds exist for 386, armv6, armv7, arm64, amd64 and ppc64le

Look elsewhere if

  • You depend on Pi-hole's group management or a specific Pi-hole-only list ecosystem and integration
  • You want your resolver's configuration managed as immutable declarative config, since AdGuard Home rewrites its own YAML at runtime
  • You need OIDC-backed admin access; it is basic auth against local users and nothing else

What running it actually looks like#

One container, two volumes: /opt/adguardhome/work for data and /opt/adguardhome/conf for AdGuardHome.yaml. You almost always want host networking or a long port list: 53/tcp and 53/udp, 3000/tcp for the first-run wizard, then 80 for the interface, 443 for DoH, 853 for DoT and DoQ, 5443 for DNSCrypt, and 67/68 if you use the built-in DHCP server. Free port 53 first, because systemd-resolved holds it on Ubuntu. First boot serves a setup wizard on 3000 where you pick the web port and create the admin user; after that the wizard is gone and 3000 stops mattering, which catches people out when they cannot find the UI again. Upgrades are AdGuardHome --update or a tag bump plus restart, and the binary migrates the YAML schema on start.

Resource profile#

Memory
60 MB idle, around 150 MB in ordinary use. Go binary; the driver is total filtering rules loaded into memory, so adding a few million-line blocklists is what moves this number, not query rate.
CPU and acceleration
Negligible for plain DNS. TLS and QUIC handshakes for inbound DoH/DoT/DoQ clients are the real cost, and a filter-list refresh briefly recompiles the rule engine.
Storage growth
The downloaded filter lists and querylog.json dominate, easily a few hundred megabytes if you enable a long query log retention. Both are disposable.
Operational load
2 of 5, Light. One binary, one YAML file, upgrades are usually a restart. It stays at 2 because config schema migrations are one-way, the process rewrites its own config file, and it is on the critical path for every device's name resolution.

Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.

Data and backup surface#

Two directories. conf/AdGuardHome.yaml is the entire configuration: the bcrypt hash of every admin password, all upstreams, every hand-written filtering rule, every client definition and the DHCP static leases. It is plain text, small, and the sanest backup is committing it to a private git repo on a schedule. work/data holds stats.db and sessions.db (BoltDB) plus querylog.json, and work/data/filters holds cached copies of your subscribed blocklists. The filters directory and the query log are entirely regenerable and are almost all of the size on disk, so exclude them. Losing stats.db costs you the dashboard graphs and nothing else. Stop the service before copying the YAML, because a running AdGuard Home will overwrite it.

Derived backup shape

Embedded key-value store. Stop the service and copy its data directory, or use the project's own export command. There is no dump utility to run against it while it is live.

Traps and surprises#

It overwrites AdGuardHome.yaml while running

The documentation says it directly: edits made to the config file while the process is running are lost, because AdGuard Home serializes its in-memory state back over the file whenever settings change. Any workflow built on Ansible templating the YAML, or on a quick vi to add an upstream, has to stop the service, edit, then start. This is also why config management of AdGuard Home is awkward compared with a resolver that only reads its config.

schema_version migrations are one-way

Every release that changes config layout bumps schema_version and rewrites your YAML on first start. 0.107.74 went from 33 to 34 and reorganized the HTTP and TLS settings for DNS-over-HTTPS. Downgrading afterwards fails, because older builds do not understand the newer schema. Copy AdGuardHome.yaml somewhere else before any upgrade; that copy is your only rollback.

The setup wizard on 3000 exists exactly once

First boot serves the installer on 3000. You choose the real web port there (commonly 80 or 3000 again) and create the admin. After that, 3000 is no longer the UI unless you picked it, and people who published only 3000 in their compose file lose access to their own resolver. Decide the web port before first boot and publish it, or you will be editing the YAML by hand to get back in.

Serving DoH on 443 collides with your reverse proxy

Inbound DNS-over-HTTPS wants 443, and DoT and DoQ want 853 with a real certificate for the hostname clients dial. On a host already running Caddy, Traefik or Nginx Proxy Manager on 443, one of them loses. The workable arrangements are giving AdGuard Home a separate IP, proxying the DoH path through your existing terminator, or moving DoH to a non-standard port that clients let you specify in the URL.

The edge channel changed under people in 0.107.79

0.107.79 switched the edge channel to a new UI and a new versioning scheme, and deprecated the strict_sni_check parameter. Edge builds are not a beta of the next stable in the usual sense and can carry interface and config changes that stable has not seen. If AdGuard Home is the only resolver on your network, stay on the release channel; there is no second DNS server to fall back to while you debug.

Specifications#

Category
Networking, DNS and remote access
Licence
GPL-3.0 (Copyleft)
Written in
Go, with a React web interface
First release
2018
Maturity
Mature
Datastore
A single YAML config file plus BoltDB files for stats and sessions; the query log is a JSON lines file
Default ports
53, 80, 443, 853, 3000
Ships as
docker, native binary, router firmware package
arm64 builds
Yes
Identity
Local accounts only. Local users defined in AdGuardHome.yaml with bcrypt hashes, served over HTTP basic auth. No OIDC, no LDAP, no plugin path.
Replaces
NextDNS, AdGuard DNS, Cloudflare Gateway
Project site
adguard.com/adguard-home/overview.html
Source
github.com/AdguardTeam/AdGuardHome
Documentation
github.com/AdguardTeam/AdGuardHome/wiki

Alternatives to AdGuard Home#

Everything else in networking, dns and remote access, closest in operational weight first.

ToolOps loadIdle RAMLicence
Nginx Proxy Manager2, Light100 MBMIT
Pi-hole2, Light100 MBEUPL-1.2
wg-easy2, Light90 MBAGPL-3.0-only
Caddy1, Set and forget25 MBApache-2.0
Headscale3, Moderate40 MBBSD-3-Clause
Technitium DNS Server3, Moderate130 MBGPL-3.0

Where AdGuard Home comes up elsewhere#

Sources#

Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.

  1. Repository README, licence and feature comparison
  2. Official changelog, versions and schema migrations
  3. Official wiki, Docker ports and volumes
  4. Official Docker image, published architectures

Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.