Why I Run AdGuard Home on a VPS Instead of Locally

May 2026 6 min read

adguardtailscaleself-hosteddnsnetworking

A few months ago I wanted to stop paying for Pi-hole's cloud alternative and stop worrying about DNS queries leaving my network unencrypted. I also wanted scheduled blocking — not just for ads, but for specific domains during work hours. AdGuard Home on a VPS behind Tailscale solved all of it.

Here's exactly how I set it up.

Why a VPS instead of locally

The obvious option is running AdGuard Home on a Raspberry Pi or spare machine at home. I didn't want to depend on my home network being up, and I wanted the same DNS filtering on my phone when I'm out — without running a public resolver.

A VPS on Tailscale is the answer. AdGuard Home listens only on the Tailscale interface. Every device on my tailnet uses it as its DNS server. Nobody outside the tailnet can touch it.

Installing AdGuard Home

On a fresh Ubuntu VPS:

curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

By default it tries to bind to all interfaces on port 53. We don't want that.

Locking it to Tailscale only

Find your VPS's Tailscale IP:

tailscale ip -4
# e.g. 100.64.0.1

In AdGuard Home's config (/opt/AdGuardHome/AdGuardHome.yaml), set the DNS bind host to that IP only:

dns:
  bind_host: 100.64.0.1
  port: 53

Restart AdGuard Home. Now DNS only responds on the tailnet. The web UI is also reachable at http://100.64.0.1:3000 — no public exposure needed.

Pointing devices at it

On each device, set the DNS server to your VPS's Tailscale IP. How you do this varies:

  • Linux: Edit /etc/resolv.conf or set it in NetworkManager
  • iOS/Android: In WiFi settings, set DNS manually to the Tailscale IP (this only works on WiFi — more on mobile later)
  • Windows: Network adapter settings, set preferred DNS

If you use Tailscale's MagicDNS, you can push the DNS server automatically to all devices from the admin console. I've had some inconsistency with this on Android so I set it manually.

Blocklists

The defaults are fine to start. I use:

  • AdGuard DNS filter (built-in)
  • EasyList
  • Peter Lowe's Ad and tracking server list

For social media blocking I add custom rules directly in the "Custom filtering rules" section:

||twitter.com^
||x.com^
||instagram.com^
||youtube.com^
||reddit.com^

Scheduled blocking

This is the part that actually changes behavior. AdGuard Home doesn't have native scheduling, so I use a cron job to swap between two rule files.

Two files: block-social.txt (with the rules above) and allow-social.txt (empty). A cron job on the VPS swaps which one AdGuard loads at 9am and 6pm on weekdays by hitting the AdGuard Home API:

# Enable blocking at 9am Mon-Fri
0 9 * * 1-5 curl -s -u admin:password -X PUT \
  http://100.64.0.1:3000/control/filtering/set_rules \
  -H "Content-Type: application/json" \
  -d '{"rules":["||twitter.com^","||x.com^","||instagram.com^","||youtube.com^"]}'

# Disable at 6pm
0 18 * * 1-5 curl -s -u admin:password -X PUT \
  http://100.64.0.1:3000/control/filtering/set_rules \
  -H "Content-Type: application/json" \
  -d '{"rules":[]}'

It's crude but it works. The API is fully documented if you want something more sophisticated.

The mobile gap

When my phone is on WiFi, it uses the Tailscale DNS. When I switch to mobile data, Tailscale is still running but Android's DNS behavior gets weird — some apps bypass the configured server entirely.

The cleanest fix is setting your tailnet's DNS in the Tailscale admin console under "DNS > Nameservers > Override local DNS." This forces all DNS through your resolver when Tailscale is active regardless of network. I've been running this for a few weeks and it's been stable.

iOS is more reliable about respecting the DNS setting.

Encryption

AdGuard Home supports DNS-over-HTTPS and DNS-over-TLS. Since traffic is already on WireGuard (Tailscale), adding another encryption layer on top is redundant for tailnet devices. I don't bother. For the upstream resolvers AdGuard uses to resolve queries, I use Cloudflare's DoH endpoint — that traffic leaves the VPS and should be encrypted.

What you end up with

Every device on your tailnet gets ad blocking, tracker blocking, and whatever domain rules you set — without running anything at home, without exposing a public DNS resolver, and without paying for a managed service. The whole setup costs whatever your VPS costs. Mine is $4/month.