Start your 3-day free trial
Sign up to experience all premium features at no cost.
*Available only to new users. Each user is limited to one trial.


A safe AdGuard Home setup runs the resolver on one LAN host, answers only the devices you list, and sends chosen domains to their own upstream DNS while everything else uses one encrypted default. You trial it on a single device, verify filtering and leaks, and keep a tested way back.
Key Takeaways:
- Pin one release, verify its checksum, and record the host's resolver before changing anything.
- Free port 53 from the systemd-resolved stub listener in a way you can reverse.
- Firewall rules and the allowed-clients list both decide who gets answers; set both.
- Domain-specific upstreams send local or company names to their own servers.
- Undo the device first, then uninstall and restore the resolver.
Plan for a native Ubuntu 24.04 LTS x64 host on your home LAN, or a VPS reachable only over a private network, plus one test device you control. The procedure targets AdGuard Home v0.107.79, released on 18 August 2026.[1] This procedure is based on the official sources listed below; a complete end-to-end test has not been performed.
AdGuard documents the archive install, the service commands, and the ports: TCP 3000 for the first-run wizard, TCP 80 for the web interface by default, and UDP 53 for DNS.[2] The old GitHub wiki now carries an outdated notice and points to the Knowledge Base, so prefer the Knowledge Base when commands differ.[3]
An always-on resolver is a maintenance commitment; weigh it with the self-hosting responsibilities overview. This guide differs from the Pi-hole single-device trial and from running your own recursive Unbound resolver: AdGuard Home forwards queries and lets you pick an upstream per domain. Domain blocking also has limits that no resolver removes; see how DNS ad blocking actually works.
Stop if the host is shared production, managed by someone else, or reachable from the internet on port 53. Never expose this resolver publicly.
AdGuard Home accepts plain DNS, DNS-over-TLS (tls://), DNS-over-HTTPS (https://), DNS-over-QUIC (quic://) and DNS stamps as upstreams. A line such as [/example.local/] followed by a server sends that domain and its subdomains to that server, and # means "use the default upstreams".[4]
| Query type | Suggested upstream | Why |
|---|---|---|
| Public names | One encrypted default upstream | Your ISP no longer sees plain lookups |
Router-local names such as .lan | The router's LAN address | Only the router knows those names |
| Company or lab domains | That network's internal resolver | Public resolvers cannot answer them |
| Reverse lookups for private addresses | Private reverse DNS servers field | AdGuard requires private ranges there |
Save the current resolver state so you can restore it exactly:
readlink -f /etc/resolv.conf
resolvectl status
sudo ss -lntup
On Ubuntu, systemd-resolved runs a stub listener on 127.0.0.53 and 127.0.0.54, and /etc/resolv.conf normally points to the stub file.[5] Write down the LAN interface, the host's LAN address, the test device's address, and the admin device's address.
Download the release while host DNS still works, and verify it against the published checksums:
cd "$(mktemp -d)"
VER='v0.107.79'
BASE="https://github.com/AdguardTeam/AdGuardHome/releases/download/$VER"
curl -fLO "$BASE/AdGuardHome_linux_amd64.tar.gz"
curl -fLO "$BASE/checksums.txt"
sha256sum -c --ignore-missing checksums.txt
tar -xzf AdGuardHome_linux_amd64.tar.gz
sudo mv AdGuardHome /opt/AdGuardHome
Continue only when the checksum line reports OK. If /opt/AdGuardHome already exists, stop and find out who installed it.
The first run listens on 0.0.0.0:3000, so any LAN device could reach the wizard.[2] Under an already reviewed UFW policy that denies inbound traffic by default, allow only what this trial needs; replace the interface and addresses:[6]
LAN_IF='enp1s0'
TEST_V4='192.168.1.25'
ADMIN_V4='192.168.1.10'
sudo ufw allow in on "$LAN_IF" from "$TEST_V4" to any port 53 proto udp
sudo ufw allow in on "$LAN_IF" from "$TEST_V4" to any port 53 proto tcp
sudo ufw allow in on "$LAN_IF" from "$ADMIN_V4" to any port 3000 proto tcp
sudo ufw status numbered
Keep your SSH rule and a local console. If UFW is inactive, set up a default-deny policy first instead of skipping this step.
DNSStubListener=no disables the stub, and drop-ins in /etc/systemd/resolved.conf.d/ override the main file.[7] AdGuard's FAQ gives this manual fix and says the DNS=127.0.0.1 line is necessary:[8]
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
sudo ss -lntup | grep ':53 '
The last command should show nothing on port 53. Host lookups now fail until AdGuard Home answers on 127.0.0.1, which is why the download came first. The wizard also offers a Fix button for this conflict; the manual route leaves you a file you can delete later.[8]
cd /opt/AdGuardHome
sudo ./AdGuardHome -s install
sudo ./AdGuardHome -s status
From the admin device, open http://HOST_LAN_IP:3000. In the wizard, set the admin web interface to the host's LAN address on port 3000 and the DNS server to the LAN address on port 53. Create an admin account with a long unique password.[2]
Edit the configuration only while the service is stopped, because a running instance overwrites file changes.[9] Change just these keys inside their existing sections:
sudo /opt/AdGuardHome/AdGuardHome -s stop
sudoedit /opt/AdGuardHome/AdGuardHome.yaml
http:
address: 192.168.1.53:3000
dns:
bind_hosts:
- 127.0.0.1
- 192.168.1.53
port: 53
allowed_clients:
- 127.0.0.1
- 192.168.1.25
querylog:
enabled: true
interval: 24h
statistics:
interval: 24h
bind_hosts limits where DNS is served, and a non-empty allowed_clients list means only those addresses get answers.[9] Loopback stays listed because the host itself now resolves through 127.0.0.1. Query-log rotation accepts 1h to 8760h; one day is enough for a trial. Set anonymize_client_ip: true under dns if you do not need per-client logs.[9]
sudo /opt/AdGuardHome/AdGuardHome --check-config --config /opt/AdGuardHome/AdGuardHome.yaml
sudo /opt/AdGuardHome/AdGuardHome -s start
getent hosts example.com
AdGuard recommends the Allowed clients field under Settings → DNS settings → Access settings when the client count is known, and warns that open resolvers invite abuse.[10]
On the test device, set DNS manually to the host's LAN address only. Leave no public alternate resolver, and turn off browser secure DNS in a test profile so lookups really reach AdGuard Home. From that device:
nslookup example.com 192.168.1.53
nslookup example.com
Both lookups should appear in the Query log with the test device's address. If only the explicit query appears, the device still uses another resolver.
In Settings → DNS settings → Upstream DNS servers, enter one upstream per line; replace the router and company addresses:
https://unfiltered.adguard-dns.com/dns-query
[/lan/]192.168.1.1
[/corp.example/]10.20.0.53
[/public.corp.example/]#
The first line is AdGuard DNS's non-filtering DNS-over-HTTPS address, so filtering stays on your own instance.[11] Because DoH upstreams are hostnames, keep a plain resolver such as 94.140.14.140 in the bootstrap DNS field (bootstrap_dns).[9][11] The last line returns one subdomain to the default upstream; [/*.corp.example/] would match only subdomains, not corp.example itself.[4]
Put the router address in Private reverse DNS servers, because AdGuard routes private-range reverse lookups only there.[4] Repeat the Step 6 lookups, then query a .lan name and check the log's upstream column.
Under Filters → Custom filtering rules, add ||example.org^, which blocks the domain and its subdomains. Then add @@||example.org^ to unblock it; lines starting with ! or # are comments.[12]
| Check method | Expected observation | If it fails |
|---|---|---|
nslookup example.org with only the block rule | Logged as blocked | Confirm the device uses the host and rules saved |
| Same query with the exception added | Logged as allowed again | Remove any $important rule that overrides exceptions |
Query a .lan name | Answer comes from the router | Check the [/lan/] line and the router address |
| Query from an unlisted device you own | No answer | Fix allowed_clients or the firewall |
| Run a DNS leak test on the test device | Only the default upstream's resolvers appear | Look for alternate resolvers, IPv6 DNS or browser DNS |
Use this DNS leak check for the last row. IPv6 DNS is a separate path: either configure and restrict an IPv6 listener or label the trial IPv4-only. Delete both test rules afterward.
Restore the test device's original DNS settings and confirm a fresh lookup works before touching the host. AdGuard warns to repoint devices before uninstalling, then run the uninstall command and remove the directory.[8]
sudo /opt/AdGuardHome/AdGuardHome -s uninstall
sudo rm /etc/systemd/resolved.conf.d/adguardhome.conf
sudo rm /etc/resolv.conf
sudo mv /etc/resolv.conf.backup /etc/resolv.conf
sudo systemctl restart systemd-resolved
getent hosts example.com
Compare readlink -f /etc/resolv.conf and resolvectl status with Step 1. Delete only the UFW rules this trial added, by number. Keep a private copy of AdGuardHome.yaml if you may return, then remove /opt/AdGuardHome.
allowed_clients.Yes. You only turn off its stub listener with a drop-in; systemd-resolved keeps running and forwards host lookups to 127.0.0.1.
Another program, usually the systemd-resolved stub, already holds port 53. Apply the Step 3 drop-in or use the wizard's Fix button.
A # after a domain block tells AdGuard Home to use the default upstreams for that domain instead of a specific server.
They are optional but sensible for public names, because plain upstream queries are visible to your network path and ISP.
No. An open resolver attracts abuse; keep DNS on the LAN or a private network and list allowed clients explicitly.
DNS rules block whole domains. Ads served from the same domain as the content, cached pages and browser DNS can bypass them.
Not by itself. Restore each device's DNS first, then remove the resolved drop-in and put back the saved resolv.conf link.
Disclaimer: These steps are compiled from official documentation and are not a record of completed testing. Use only hosts and devices you are authorized to change, and keep a working recovery path.
Sources:
Sources checked 14 October 2026.
Related Articles:
Sign up to experience all premium features at no cost.
*Available only to new users. Each user is limited to one trial.





