AdGuard Home Setup: Private DNS With Split Upstreams

AdGuard Home Setup: Private DNS With Split Upstreams

Marcus Reid
October 14, 2026· 11 min read

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.

What does this AdGuard Home setup need?

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.

Which upstream should answer which names?

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 typeSuggested upstreamWhy
Public namesOne encrypted default upstreamYour ISP no longer sees plain lookups
Router-local names such as .lanThe router's LAN addressOnly the router knows those names
Company or lab domainsThat network's internal resolverPublic resolvers cannot answer them
Reverse lookups for private addressesPrivate reverse DNS servers fieldAdGuard requires private ranges there

Step 1: Record the baseline and fetch a pinned release

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.

Step 2: Close the firewall before the first start

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.

Step 3: Resolve the AdGuard Home port 53 conflict

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]

Step 4: Install the service and finish the wizard

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]

Step 5: Narrow listeners, clients and logs

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]

Step 6: Point one device and confirm queries arrive

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.

Step 7: Configure AdGuard Home upstream DNS by domain

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.

Step 8: Verify filtering, one exception and leaks

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 methodExpected observationIf it fails
nslookup example.org with only the block ruleLogged as blockedConfirm the device uses the host and rules saved
Same query with the exception addedLogged as allowed againRemove any $important rule that overrides exceptions
Query a .lan nameAnswer comes from the routerCheck the [/lan/] line and the router address
Query from an unlisted device you ownNo answerFix allowed_clients or the firewall
Run a DNS leak test on the test deviceOnly the default upstream's resolvers appearLook 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.

Step 9: Undo the device change and uninstall

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.

Summary

  • Pin and verify the release, and record the resolver before changing it.
  • Free port 53 with a drop-in you can delete, not by disabling the resolver blindly.
  • Restrict answers with both firewall rules and allowed_clients.
  • Route local and company domains to their own upstreams; keep one encrypted default.
  • Restore devices first, then uninstall and return the host to its old resolver.

FAQ

Can AdGuard Home run without disabling systemd-resolved?

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.

Why does the wizard say address already in use?

Another program, usually the systemd-resolved stub, already holds port 53. Apply the Step 3 drop-in or use the wizard's Fix button.

What does the hash sign mean in an upstream line?

A # after a domain block tells AdGuard Home to use the default upstreams for that domain instead of a specific server.

Do I need encrypted upstreams?

They are optional but sensible for public names, because plain upstream queries are visible to your network path and ISP.

Is it safe to open port 53 to the internet?

No. An open resolver attracts abuse; keep DNS on the LAN or a private network and list allowed clients explicitly.

Why do some ads still appear after blocking works?

DNS rules block whole domains. Ads served from the same domain as the content, cached pages and browser DNS can bypass them.

Does uninstalling AdGuard Home restore my DNS?

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:

  1. AdGuard Home v0.107.79 release — https://github.com/AdguardTeam/AdGuardHome/releases/tag/v0.107.79
  2. AdGuard Home Getting Started — https://adguard-dns.io/kb/adguard-home/getting-started/
  3. AdGuard Home Wiki — https://github.com/AdguardTeam/AdGuardHome/wiki
  4. AdGuard Home Wiki: Configuration — https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration
  5. Ubuntu Manpage: systemd-resolved.service — https://manpages.ubuntu.com/manpages/noble/man8/systemd-resolved.service.8.html
  6. Ubuntu Firewall — https://ubuntu.com/server/docs/how-to/security/firewalls/
  7. Ubuntu Manpage: resolved.conf — https://manpages.ubuntu.com/manpages/noble/man5/resolved.conf.5.html
  8. AdGuard Home FAQ — https://adguard-dns.io/kb/adguard-home/faq/
  9. AdGuard Home Configuration — https://adguard-dns.io/kb/adguard-home/configuration/
  10. AdGuard Home Running Securely — https://adguard-dns.io/kb/adguard-home/running-securely/
  11. AdGuard DNS Known DNS Providers — https://adguard-dns.io/kb/general/dns-providers/
  12. AdGuard DNS Filtering Rules Syntax — https://adguard-dns.io/kb/general/dns-filtering-syntax/

Sources checked 14 October 2026.


Related Articles:

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.

AdGuard Home Setup: Private DNS With Split Upstreams | AethoVPN