AdGuard Home DNS server blocking ads on VPS

Install AdGuard Home on VPS: Self-Hosted DNS Ad Blocker

Updated August 20, 2026 · DNS · Privacy · Network

AdGuard Home is a self-hosted network-level ad blocker that works as a DNS server. It blocks ads, trackers, and malware domains before they ever reach your devices — no browser extensions needed. Set it up once on your VPS and every device on your network gets protection: Android, iOS, Windows, macOS, and Linux.

Unlike Pi-hole, AdGuard Home ships with built-in DNS over HTTPS (DoH) and DNS over TLS (DoT) — encrypting your DNS queries so your ISP or any eavesdropper cannot see what domains you resolve.

System Requirements

Note: On modern Ubuntu, systemd-resolved occupies port 53 by default. You must disable its stub listener before AdGuard Home can bind to port 53.

Step 1: Disable systemd-resolved Stub Listener

Check whether something is already listening on port 53, then disable the systemd-resolved stub if needed.

# Check who owns port 53
sudo ss -tulnp | grep :53

# Disable the stub listener
sudo mkdir -p /etc/systemd/resolved.conf.d/
cat <<'EOF' | sudo tee /etc/systemd/resolved.conf.d/adguard.conf
[Resolve]
DNSStubListener=no
EOF

sudo systemctl restart systemd-resolved

# Confirm port 53 is now free
sudo ss -tulnp | grep :53

Step 2: Download and Install AdGuard Home

AdGuard Home ships as a single static binary — no runtime dependencies required.

# Quick install via official script (downloads latest release)
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

# Or manually download the binary (recommended for production)
AGH_VERSION=$(curl -s https://api.github.com/repos/AdguardTeam/AdGuardHome/releases/latest \
  | grep tag_name | cut -d '"' -f4)
wget -qO /tmp/AdGuardHome.tar.gz \
  "https://github.com/AdguardTeam/AdGuardHome/releases/download/${AGH_VERSION}/AdGuardHome_linux_amd64.tar.gz"

tar -xzf /tmp/AdGuardHome.tar.gz -C /tmp/
sudo mv /tmp/AdGuardHome/AdGuardHome /usr/local/bin/
sudo chmod +x /usr/local/bin/AdGuardHome

Step 3: Install as a systemd Service

# Create working directories
sudo mkdir -p /etc/adguardhome /var/lib/adguardhome

# If you used the install script, the service is already registered.
# For a manual install, create a systemd unit:
cat <<'EOF' | sudo tee /etc/systemd/system/adguardhome.service
[Unit]
Description=AdGuard Home: Network-level blocker
After=network.target

[Service]
ExecStart=/usr/local/bin/AdGuardHome -c /etc/adguardhome/AdGuardHome.yaml -w /var/lib/adguardhome
Restart=always
RestartSec=5s
User=root

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now adguardhome
sudo systemctl status adguardhome

Step 4: Initial Setup via Web UI

Open http://YOUR_VPS_IP:3000 in your browser and follow the setup wizard:

  1. Choose the network interface to listen on (select All interfaces for a VPS)
  2. Set Admin Web Interface port (3000 or 80)
  3. Set DNS Server port to 53
  4. Create an admin username and password
  5. Click Next then Apply to finish
Security Tip: After setup, close port 3000 in your firewall if using port 80 for the dashboard, or put AdGuard Home behind Nginx with a valid SSL certificate.

Step 5: Add DNS Blocklists

In the dashboard go to Filters → DNS blocklists → Add blocklist. These are the most popular lists:

BlocklistURLDomains blocked
AdGuard DNS filterhttps://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt~50,000
AdAway Defaulthttps://adaway.org/hosts.txt~15,000
Steven Black Hostshttps://raw.githubusercontent.com/StevenBlack/hosts/master/hosts~100,000
MalwareDomainListhttps://www.malwaredomainlist.com/hostslist/hosts.txt~1,500
# Check filter status via API
curl -s http://localhost:3000/control/filtering/status | python3 -m json.tool

# Check blocking stats
curl -s http://localhost:3000/control/stats | python3 -m json.tool | grep -E "blocked|total"

Step 6: Enable DNS over HTTPS and DNS over TLS

AdGuard Home handles DoH and DoT natively. You need a TLS certificate for your domain first (Let's Encrypt recommended).

# In the Web UI go to: Settings → Encryption settings
# Fill in:
#   Server name: dns.example.com
#   HTTPS port: 443
#   DNS-over-TLS port: 853
#   Certificate path: /etc/letsencrypt/live/dns.example.com/fullchain.pem
#   Private key path: /etc/letsencrypt/live/dns.example.com/privkey.pem

# Test DoH
curl -sH 'accept: application/dns-json' \
  'https://dns.example.com/dns-query?name=google.com&type=A' | python3 -m json.tool

# Test DoT (requires knot-dnsutils: apt install knot-dnsutils)
kdig -d @dns.example.com +tls-ca +tls-host=dns.example.com google.com

Step 7: Configure Upstream DNS

Go to Settings → DNS settings → Upstream DNS servers and add trusted upstream resolvers:

# Recommended upstream DNS (enter in Web UI)
# Cloudflare — fast and privacy-respecting
https://1.1.1.1/dns-query
https://1.0.0.1/dns-query

# Quad9 — blocks malware at the upstream level
https://9.9.9.9/dns-query

# Google
https://8.8.8.8/dns-query

# Equivalent YAML config in AdGuardHome.yaml
upstream_dns:
  - https://1.1.1.1/dns-query
  - https://1.0.0.1/dns-query
  - https://9.9.9.9/dns-query
upstream_mode: parallel
Tip: Enable Parallel requests in DNS settings so AdGuard Home queries all upstreams simultaneously and uses whichever replies first — this noticeably reduces average DNS latency.

Step 8: Point Your Devices at AdGuard Home

Configure DNS on your devices or router to point at your VPS IP address:


Verify AdGuard Home Is Working Correctly

# Check service status
sudo systemctl status adguardhome

# Verify which ports are listening
sudo ss -tulnp | grep -E ':53|:3000|:443|:853'

# Test DNS resolution through AdGuard Home
dig @127.0.0.1 google.com
dig @127.0.0.1 doubleclick.net    # Should return 0.0.0.0 or NXDOMAIN

# Check blocking statistics
curl -s http://localhost:3000/control/stats | python3 -m json.tool

# Stream real-time logs
sudo journalctl -u adguardhome -f
Tip: Query doubleclick.net or ads.google.com to confirm blocking is active — you should receive 0.0.0.0 or NXDOMAIN instead of the real ad-server IP.

Troubleshooting Common Issues

Error: "bind: address already in use" on port 53

Port 53 is occupied by systemd-resolved or dnsmasq. You must stop those services before AdGuard Home can claim the port.

# Find what owns port 53
sudo ss -tulnp | grep :53
sudo lsof -i :53

# Disable systemd-resolved stub
echo -e "[Resolve]\nDNSStubListener=no" | sudo tee /etc/systemd/resolved.conf.d/stub.conf
sudo systemctl restart systemd-resolved

# If dnsmasq is running
sudo systemctl stop dnsmasq
sudo systemctl disable dnsmasq

Error: DNS queries fail — "dial tcp: no such host"

AdGuard Home cannot reach its upstream DNS servers. Check your firewall and upstream configuration.

# Test upstream connectivity directly from the VPS
dig @1.1.1.1 google.com
curl -s "https://1.1.1.1/dns-query?name=google.com&type=A"

# Check outbound firewall rules
sudo iptables -L OUTPUT -n --line-numbers | grep -E "53|443"

# For troubleshooting, temporarily switch to plain UDP upstream
# Web UI → Settings → DNS → change DoH URLs to plain IPs (8.8.8.8)

Error: Dashboard returns "Connection refused"

The service is not running or the port is blocked by a firewall. Check service status and open the required ports.

# Check service
sudo systemctl status adguardhome
sudo journalctl -u adguardhome --no-pager -n 50

# Open ports with UFW
sudo ufw allow 3000/tcp comment 'AdGuard Home setup'
sudo ufw allow 53/tcp comment 'DNS TCP'
sudo ufw allow 53/udp comment 'DNS UDP'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS / DoH'
sudo ufw allow 853/tcp comment 'DoT'

Websites load slowly after switching DNS

High upstream latency or a cold cache can slow initial lookups. Add multiple upstreams and enable parallel queries.

# Compare upstream latency
for ns in 1.1.1.1 8.8.8.8 9.9.9.9; do
  echo -n "$ns: "
  dig @$ns google.com | grep "Query time"
done

# In Web UI enable:
# Settings → DNS → Load Balancing: Parallel
# Settings → DNS → Cache size: 4000000 (4M entries)

AdGuard Home blocked a site I need

Add the domain to your custom whitelist rules to exempt it from all blocklists.

# Web UI → Filters → Custom filtering rules → add:
@@||example.com^              # whitelist entire domain
@@||sub.example.com^          # whitelist only a subdomain

# Check which filter matched a blocked domain:
# Web UI → Query Log → click the blocked query → "Matched filter"

Frequently Asked Questions

How does AdGuard Home compare to Pi-hole?

Both block ads via DNS, but AdGuard Home ships with built-in DoH, DoT, and DNSCrypt support — no extra tools like cloudflared or stunnel required. Pi-hole is well-suited for Raspberry Pi on a home LAN; AdGuard Home is a better fit when you want an encrypted, publicly-accessible DNS resolver on a VPS. AdGuard Home's web interface is also more modern and requires no separate PHP stack.

Is it safe to run AdGuard Home on a public VPS?

Yes, if you restrict access properly. An unrestricted open resolver can be abused for DNS amplification attacks. Use the Allowed clients setting in the dashboard to limit access to trusted IPs, or expose only DoH/DoT (which require a client to know your domain) and keep plain port 53 firewalled. Also enable rate limiting to prevent abuse.

How much RAM and CPU does AdGuard Home use?

At idle, AdGuard Home uses roughly 30–80 MB of RAM and negligible CPU. Loading large blocklists may temporarily push RAM to ~200 MB. A 512 MB VPS handles a small home network or team of under 100 clients without issue, sustaining thousands of DNS queries per second.