How to Set Up AdGuard Home on a VPS
Install AdGuard Home on Ubuntu, complete the first-run wizard, lock the web UI, enable DNS-over-HTTPS and DNS-over-TLS, point devices at your resolver, and avoid running an open DNS server that the whole internet can abuse.

AdGuard Home is a self-hosted DNS sinkhole and recursive-style resolver with a web interface. It can block ads, trackers and malware domains for every device that uses it as DNS — phones, laptops, smart TVs, and other VPS projects. Unlike a browser extension, it works even for apps that ignore hosts files. Running it on a VPS is useful when you want the same filtering on the road, or when you do not want a Raspberry Pi on your home network.
The dangerous default you must not ship is an open resolver: if UDP/TCP 53 is reachable from the whole internet with no access control, strangers will use your VPS for DNS amplification and you will get abuse complaints. This guide installs AdGuard Home on Ubuntu, binds DNS to localhost or a private WireGuard interface unless you deliberately expose encrypted DNS, puts the dashboard on HTTPS, and shows how laptops and phones can use DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT) without opening classic port 53 to the world.
What AdGuard Home is good for
Pi-hole is the usual comparison. AdGuard Home is a single binary with a built-in web UI, optional encrypted DNS frontends, and per-client settings. You can run it in Docker or as a systemd service. On a Hiddence VPS it pairs well with a private VPN: devices join WireGuard, send DNS to the VPS over the tunnel, and never expose port 53 publicly.
- Network-wide blocking without installing an app on every device
- DoH (443) and DoT (853) so DNS is not plain text on public Wi-Fi
- Query log and statistics so you can see which device talks to which domain
- Custom upstreams (Quad9, Cloudflare, or your own Unbound)
- Small footprint — a 1 GB VPS can filter a household plus a few extra clients
Requirements
You need a domain if you want a trusted certificate for DoH/DoT and for the dashboard. You can test on HTTP and the server IP first, but do not leave it that way. If systemd-resolved already owns port 53 on Ubuntu, we will free it before AdGuard Home binds DNS.
- Ubuntu 22.04 or 24.04 VPS with root/sudo
- 1 GB RAM is enough for personal use
- A domain or subdomain (dns.example.com) with an A record to the VPS
- SSH access; optional WireGuard if you want DNS only inside a tunnel
Step 1: Free port 53 and install AdGuard Home
Ubuntu Server often runs systemd-resolved as a stub on 127.0.0.53:53. AdGuard Home wants 53 on the interfaces you choose. The installer can do this, but doing it explicitly avoids a half-broken DNS on the VPS itself (you still need the server to resolve packages).
ssh root@YOUR_VPS_IP
apt update && apt -y upgrade
apt -y install curl ca-certificates
# See who owns port 53:
ss -tulpn | grep ':53'
# Typical Ubuntu fix: stop stub listener, point the OS at a temporary resolver
mkdir -p /etc/systemd/resolved.conf.d
cat >/etc/systemd/resolved.conf.d/adguardhome.conf <<'EOF'
[Resolve]
DNS=1.1.1.1
DNSStubListener=no
EOF
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
systemctl restart systemd-resolved
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -vStep 2: First-run wizard
The installer prints a URL, usually http://YOUR_IP:3000/. Open it, create an admin user with a long password, and choose listen addresses. For a public VPS, a safe first setup is: Admin Web on 127.0.0.1:3000 (you will put Caddy in front) or on 80/443 after TLS; DNS listen on 127.0.0.1:53 plus a VPN interface, not on 0.0.0.0:53. If you truly need LAN-style DNS for friends, prefer DoH/DoT on 443/853 with authentication, not open 53/udp.
Pick upstream DNS servers you trust. Many people use https://dns.quad9.net/dns-query or Cloudflare. Enable parallel requests if you want faster failover. Turn on the default filter lists, then add more later — enabling fifty lists on day one makes debugging impossible when a site breaks.
Step 3: Reverse proxy and HTTPS for the dashboard
Once the wizard finishes, AdGuard Home typically moves the UI to port 80. That collides with Caddy or Nginx if you also host sites. A clean pattern is: AdGuard Home web on 127.0.0.1:8080, DNS on 127.0.0.1:53, Caddy on 443 for both the dashboard and DoH.
# In AdGuard Home settings, bind the web UI to 127.0.0.1:8080
# Example Caddyfile:
dns.example.com {
reverse_proxy 127.0.0.1:8080
}
# After Caddy is up:
curl -I https://dns.example.comStep 4: Enable DNS-over-HTTPS and DNS-over-TLS
In Encryption settings, enable encryption, set the server name to dns.example.com, and point AdGuard Home at your certificate files — either the ones Caddy stores, or certificates AdGuard Home obtains itself if it listens on 443. DoH is usually https://dns.example.com/dns-query. DoT is dns.example.com:853. If Caddy already owns 443, let Caddy terminate TLS and reverse-proxy the DoH path to AdGuard Home's plain HTTP DoH port, or let AdGuard Home listen on 443 and put the dashboard on another subdomain.
Verify with a client before you change every device. On a laptop with a modern curl:
curl -H 'accept: application/dns-json' 'https://dns.example.com/dns-query?name=example.com&type=A'
# DoT test (kdig from knot-dnsutils, if installed):
# kdig @dns.example.com +tls-ca +tls-host=dns.example.com example.comStep 5: Point real devices at your resolver
Windows 11 and recent Android builds can use a DoH template. iOS can use a configuration profile or a client that supports DoH. Firefox and Chromium also allow a custom DoH URL. For a home router, set WAN DNS only if the router supports DoT/DoH; otherwise run WireGuard and set DNS to the VPS VPN IP so classic DNS never crosses the internet.
- Android 9+: Private DNS (DoT) → dns.example.com
- Firefox: Settings → Network → DNS over HTTPS → custom URL https://dns.example.com/dns-query
- Apple devices: a signed mobileconfig or an app that supports DoH/DoT
- Other VPS: set resolv.conf or systemd-resolved to the WireGuard IP of this AdGuard instance
- Avoid setting this VPS IP as DNS on random public networks without encryption
Step 6: Firewall — close open recursive DNS
This is the section that prevents a nasty surprise. Allow SSH, HTTPS, and optionally 853/tcp for DoT. Do not allow 53/udp from 0.0.0.0/0 unless you have a very specific, rate-limited, authenticated design — and even then, you probably should not.
ufw allow OpenSSH
ufw allow 443/tcp comment 'dashboard + DoH'
ufw allow 853/tcp comment 'DoT'
# If DNS is only on WireGuard (example iface wg0, 10.8.0.1):
# ufw allow in on wg0 to any port 53 proto udp
ufw enable
ufw status verbose
# Confirm 53 is not public:
ss -tulpn | grep ':53'Filters, allowlists and clients
Start with AdGuard's default DNS filter and one malware list. When a site misbehaves, check the query log, then add a specific allowlist rule rather than disabling all blocking. Use client names (by IP or by ClientID in the DoH URL) so you can apply stricter lists to a smart TV and looser lists to a work laptop. Enable safe search only if you actually want it — it surprises people who did not ask for rewritten Google results.
- Query log: find the blocked domain, then whitelist if it is a false positive
- Client settings: different blocklists per device
- Disallowed clients: block ranges you do not own
- Rate limiting: turn on if you ever expose more than a handful of users
Troubleshooting
If the VPS itself cannot apt update, you broke local DNS while freeing port 53 — put a static resolver in resolved.conf as shown above. If devices 'have internet' but ads still load, they are bypassing your DNS (hardcoded resolvers, DoH in the browser, or an app using its own DNS). If the dashboard is empty, you are looking at the wrong instance or still hitting port 3000 after the wizard moved the UI.
- apt fails: check /etc/resolv.conf and systemd-resolved
- Port 53 in use: ss -tulpn, disable stub listener
- DoH certificate errors: hostname must match the cert SAN
- Ads still visible: browser DoH to another provider overrides the OS
- High RAM: query log + too many filter lists — trim lists and shorten log retention
Security checklist
The web UI is an admin panel. Unique password, HTTPS only, and do not publish the URL. Keep AdGuard Home updated; the install script and the UI both expose an update path. Restrict 443 if only your devices should use DoH — HTTP basic auth on the DoH path or WireGuard-only access is much safer than a famous open resolver.
- No public 53/udp
- HTTPS on the dashboard
- Strong admin password, stored in a password manager
- Prefer WireGuard + internal DNS for family devices
- Backup AdGuardHome.yaml off the server
Tips
- Back up /opt/AdGuardHome/AdGuardHome.yaml before every upgrade
- Use a dedicated subdomain; do not share it with an unrelated CMS
- If you already run Caddy, let Caddy own 443 and keep AdGuard Home on localhost
- Document the DoH URL for your devices — you will forget it
- Pair with the SSH hardening and firewall guides so the VPS is not only 'DNS-secure'
AdGuard Home on a VPS is straightforward: free port 53 locally, run the installer, finish the wizard with a strong admin password, put the UI on HTTPS, enable DoH/DoT, and keep classic DNS off the public internet. Point devices at your encrypted endpoint or at a VPN IP, start with a small set of filters, and use the query log when something breaks. That is a private resolver you actually control — not a public open DNS that will get your VPS listed in abuse databases.