# Self-host AdGuard Home on a VPS

> Run AdGuard Home on a VPS as a private ad-blocking DNS server for your devices, over WireGuard, Tailscale or DNS-over-HTTPS, without an open resolver.

Source: https://vpsnine.com/help/self-host-adguard-home · Updated: 2026-10-21

To self-host AdGuard Home on a VPS, install it with AdGuard's official script, finish its setup without exposing the wizard, and let only your own devices query it, over a VPN or DNS-over-HTTPS. On VPSNine the [AdGuard Home one-click app](https://vpsnine.com/apps/adguard) does all of that and leaves you to choose how your devices connect.

The part that matters most is who may ask it questions. A DNS server that answers anyone on the internet is an open resolver, and open resolvers get abused for attacks. Ours answers only private, VPN and loopback addresses until you add yours.

## What you need

- The Budget plan is plenty for a personal or family resolver. AdGuard publishes no minimum; blocklists and the query log are what use memory, so keep the log's retention modest on Budget. The [plans page](https://vpsnine.com/plans) has the specs.
- A way for your devices to reach it: WireGuard, Tailscale, or a domain for DNS-over-HTTPS such as `dns.example.com`.

A server across the internet adds a little delay to every lookup. That's fine for your phone and laptop wherever you are; for a whole home network, a small computer at home does the job better.

## Install it with the one-click app

Order a server with the [AdGuard Home app](https://vpsnine.com/apps/adguard). It installs AdGuard Home with AdGuard's script to `/opt/AdGuardHome` as a systemd service, completes the first-run setup through its API while port 3000 is closed to the internet, and writes the admin password to a file only root can read. The web interface then listens on `127.0.0.1:3000`, and DNS on port 53 resolves only for `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, Tailscale's address range, private IPv6 (unique local) addresses and loopback.

1. From your computer, open an SSH tunnel to the web interface:

   ```bash
   ssh -L 3000:127.0.0.1:3000 root@203.0.113.10
   ```

   In that session, run `cat /root/adguard-admin.txt` for the password, then open `http://localhost:3000` and log in as `admin`.

2. Choose how your devices reach it:
   - **WireGuard**: a server gets one app, so add WireGuard by hand with our [WireGuard tutorial](https://vpsnine.com/tutorials/wireguard-vpn-server-ubuntu) and set the clients' DNS to `10.9.0.1`. The tunnel's addresses are already allowed.
   - **Tailscale**: install Tailscale on the server and join your tailnet (our [Tailscale guide](https://vpsnine.com/help/tailscale-setup-script) uses Tailscale's own install script), then point your tailnet's DNS at the server's Tailscale address. Tailscale's range is already allowed.
   - **Your home's IP address**: add it in **Settings**, **DNS settings**, **Access settings**, under allowed clients.
   - **DNS-over-HTTPS** from your own domain: see the next section.

To check it's running, `systemctl status AdGuardHome` on the server should show it active.

## Put it on your domain with HTTPS

DNS-over-HTTPS works on phones and browsers anywhere, with no VPN. Point an `A` record for `dns.example.com` at the server, allow ports 80 and 443 in [the panel firewall](https://vpsnine.com/help/server-firewall), then run:

```bash
vps9-https dns.example.com
```

It installs Caddy, which gets and renews the certificate and passes requests to AdGuard Home on `127.0.0.1:3000`. Before that, its AdGuard step changes one setting in `/opt/AdGuardHome/AdGuardHome.yaml` so AdGuard Home accepts DNS-over-HTTPS over plain HTTP from Caddy on the same server, and restarts the service. The web interface is then also at `https://dns.example.com`, behind the admin password.

Next, in **Settings**, **DNS settings**, **Access settings**, add a ClientID for each device (a short name such as `laptop`) to the allowed clients. Each device then uses its own address:

```text
https://dns.example.com/dns-query/laptop
```

A device that leaves off the ClientID, or uses one you haven't allowed, gets no answers.

## Doing it by hand on another server

The [AdGuard Home README](https://github.com/AdguardTeam/AdGuardHome) gives the automated install:

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

It installs AdGuard Home as a service with its setup wizard on port 3000. Keep 3000 closed to the internet and reach the wizard through an SSH tunnel, as above, because whoever finishes it sets the admin password. In the wizard, put the web interface on `127.0.0.1` and DNS on port 53.

On Ubuntu, systemd-resolved already holds port 53; the fix is in the troubleshooting below. Then, before anything else, restrict **Access settings** to your own clients so you're not running an open resolver, and close port 53 in your firewall to everyone you don't need.

## Updates and backups

Update from the web interface when it offers a new version, or on the server:

```bash
/opt/AdGuardHome/AdGuardHome --update
```

The one-click app turns on the operating system's automatic security updates. The whole configuration is `/opt/AdGuardHome/AdGuardHome.yaml` and the `data` folder next to it, so back up both and copy them off the server. [Backups you should run](https://vpsnine.com/help/backups-you-should-run) shows how to schedule it.

The query log is on by default and stays on your server. Turn it off, or shorten how long it keeps entries, in **Settings**, **General settings**.

## When it goes wrong

- **Your queries get no answer**: your address isn't an allowed client. From home, `dig @203.0.113.10 example.com` times out until you add your public IP in **Access settings**. If your home IP changes often, use WireGuard, Tailscale or DNS-over-HTTPS with a ClientID instead.
- **`bind: address already in use` on port 53**: systemd-resolved's stub listener holds it. The one-click app already applies AdGuard's fix; by hand, create `/etc/systemd/resolved.conf.d/adguardhome.conf` with the lines below, then run `ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf` and `systemctl reload-or-restart systemd-resolved`.

  ```ini
  [Resolve]
  DNS=127.0.0.1
  DNSStubListener=no
  ```

- **DNS-over-HTTPS fails on one device**: the ClientID in its address isn't in the allowed list, or DNS for `dns.example.com` doesn't point at the server yet. Check with `getent hosts dns.example.com` on the server and run `vps9-https dns.example.com` again once it resolves.
