Following Part 1
of the series, the first component to be set up is the AdGuard Home DNS server. I chose this because it also blocks ads and unwanted services which enables my VPN clients to have a better web browsing experience. Aside from this, I get a useful GUI to view resolutions requests and to configure custom domains in an easy-to-use manner. I did contemplate utilizing dnsmasq
but finally decided on AdGuard Home.
The Docker Compose file and configuration of AdGuard Home is located in /containers/adguardhome
base folder.
/containers/adguardhome/docker-compose.yaml
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
volumes:
- '/containers/adguardhome/work:/opt/adguardhome/work'
- '/containers/adguardhome/config:/opt/adguardhome/conf'
networks:
- webproxy
ports:
- '192.168.200.1:3000:30003/tcp' # initial setup port
- '192.168.250.1:53:53/tcp' # listen for DNS on webproxy interface (tcp)
- '192.168.250.1:53:53/udp' # listen for DNS on webproxy interface (udp)
- '192.168.200.1:53:53/tcp' # listen for DNS on wireguard interface (tcp)
- '192.168.200.1:53:53/udp' # listen for DNS on wireguard interface (udp)
networks:
webproxy:
external: true
In this setup, I decided to have AdGuard Home listen on 3 interfaces
- the Docker webproxy
interface so I can force Docker to route all DNS requests to THIS DNS.
- the wireguard
interface so I can give the option for all my Wireguard clients to route all DNS requests to THIS DNS.
With this done, I run docker compose up
to bring this container up and for it to create the necessary folders. With that out of the way, from my Wireguard client, I connect to http://192.168.200.1:3000/ allowing me to configure AdGuard Home. I always change the Admin Web Interface listen port from 80
to 8000
. Ensure the DNS server is set to listen on ALL interfaces port 53. The last step is to choose a strong username and password combination. Continue with the setup until the launch dashboard option. Since we haven’t exposed port 8000
, our attempt to connect to it will fail.

With the setup done, I terminate this container using CTRL+C and edit /containers/adguardhome/docker-compose.yaml
again to remove the '192.168.200.1:3000:30003/tcp'
. I no longer need it since I will be using caddy
to access the AdGuard Home Admin UI.
I start the container back up using docker compose up -d
to have it running perpetually.
Firewall
My VPS runs ufw
as the firewall frontend so I have a rule that allows DNS traffic to traverse between the interfaces without being blocked. As the DNS server is not exposed on any of the public IP, this approach ensures there is no situation where a service or container will not be able to resolve any DNS queries
ufw allow proto udp from any to any port 53
ufw allow proto tcp from any to any port 53
The next step is to force Docker to use our new DNS server for all its requests. This is a key item to ensure any resolution to custom domain names succeeds and returns the correct IP address for the domain.
DNS for Docker
Create or edit the file /etc/docker/daemon.json
and ensure a similar line to the following exists in it
{
"dns": [
"192.168.250.1"
]
}
using the IP address of the webproxy
interface to force all containers to use this specific DNS instance. Make sure to restart Docker for these changes to take effect.
DNS for VPS
The last step is to force the VPS to route all DNS requests to this AdGuard Home instance. My instance uses systemd-networkd
with systemd-resolved
to set the IP address so I modified my existing network configuration file at /etc/systemd/network/20-wired.network
with the following contents
[Match]
Name=enp1s0
[Network]
DHCP=yes
IPv6PrivacyExtensions=yes
Address=2404:1:2:3::1001/128
Address=2404:1:2:3::9999/128
DNS=192.168.250.1 # IP address of the `webproxy` interface
I prefer to reboot my VPS after all these changes to make sure there is nothing lingering in the background. After a successful reboot, I verify the availability by using the dig
command to resolve a domain of my choice and checking the AdGuard home logs for the query.
After this, my VPS will use AdGuard Home for all its DNS resolution. With this in place, we can move on to
Now we can proceed to Part 3 of the guide, setting up the Smallstep Certificate Authority server.