Network-wide DNS filtering with AdGuard Home

Ad Assassin

© Photo by Lisa Marie Theck on Unsplash

© Photo by Lisa Marie Theck on Unsplash

Article from Issue 301/2025
Author(s):

Do you need a simple solution to block ads, trackers, phishing, and malware sites on your local network? Configure AdGuard Home as your DNS server for comprehensive network protection.

When you're browsing the web at home, numerous websites track your digital activity with online trackers, display ads that consume your precious bandwidth and screen space, and occasionally lead you to phishing or malware sites. While you could install an ad blocker and/or antivirus software on all your devices, you would need to continually keep them updated.

While on-device ad blockers and antivirus software are still useful for an extra layer of protection, an alternative solution lies within the Domain Name System (DNS). Nearly every attempt to access a network host involves domain names that need translating into IP addresses. You're likely using a DNS server operated by your Internet service provider or Google. However, by setting up your own DNS server at home, you gain full control over this translation from domain names to IP addresses. With the appropriate filters on your own DNS server, you can block access to unwanted or malicious websites without needing to install or configure any client-side software on your devices.

AdGuard Home [1] open source software lets you do just that. After installing AdGuard Home on a Raspberry Pi, another Linux server, or even on a compatible router, all you need to do is configure your DHCP server to direct all DHCP clients to use AdGuard Home's IP address as their required DNS server. AdGuard Home has a web interface to manage blocklists, view logs of DNS queries, set client-specific rules, and more. In this article, I'll demonstrate how to set up AdGuard Home to protect devices on your local network.

AdGuard Home as an Encrypted DNS Server

While using encrypted protocols for AdGuard Home's upstream DNS servers is always advisable, these protocols can also be used by your clients for secure DNS queries to AdGuard Home. In this article, I don't use this approach, because the AdGuard Home instances are on your local network, and I assume that you trust this network. However, encryption is recommended if operating AdGuard Home on a virtual private server (VPS) on the Internet or on an untrusted local network (shared with people that you don't trust). You can configure this by clicking on Settings, Encryption settings, and then Enable Encryption. This also enables HTTPS for AdGuard Home's admin interface. Note that you need a valid TLS certificate to be able to use AdGuard Home as an encrypted DNS resolver. Moreover, don't forget to add the right port mappings to your docker-compose.yml file: 80:80, 443:443, and 443:443/udp for DNS-over-HTTPS; 853:853 for DNS-over-TLS; and 853:853/udp for DNS-over-QUIC.

Requirements

A DNS server is a critical component of your network infrastructure. If your DNS server is offline, no domains are resolved, resulting in a situation similar to losing Internet access. In such cases, activities such as web browsing, email, and video conferencing become impossible. Therefore, it's highly recommended to run at least two DNS servers at home, in this case two instances of AdGuard Home. Some routers, like certain home routers by GL.iNet [2], have AdGuard Home built in. You can also install AdGuard Home on an OpenWrt [3] router. An alternative is to install AdGuard Home on a Raspberry Pi, any other Linux server, or in a virtual machine. In this article, I'll assume that you run AdGuard Home in a Docker container on two Linux machines.

Next, the machines running AdGuard Home must always have the same IP address. To do this, you can either assign a static IP address or set up a DHCP reservation in your DHCP server to always allocate the same IP address to these machines based on their MAC address. Then, in your DHCP server's configuration (usually found in your router's web interface), add your AdGuard Home machines' IP addresses to the list of DNS servers. This way, every device requesting an IP address from your DHCP server will not only receive an IP address but also the DNS servers to use. If your existing DHCP server isn't flexible enough for your liking, AdGuard Home can also function as a DHCP server for your network.

Before installing AdGuard Home, make sure that you meet all of these requirements. While the DHCP configuration must wait until after the installation of AdGuard Home, it's important to already have a clear understanding beforehand of how you need to configure it later.

Installing the Docker Container

On a Debian 12 server, install Docker and Docker Compose with

sudo apt install docker.io docker-compose

and grant your user access to the Docker daemon with

sudo usermod -aG docker $USER

After logging out and back in to apply group membership, create a data and config directory for the AdGuard Home container:

$ mkdir -p $HOME/containers/adguard-home/{work,conf}

Next, add the AdGuard Home service definition to a docker-compose.yml file (Listing 1). These are the minimal ports the container needs: port 53 for DNS over both TCP and UDP, and port 3000 for accessing the admin interface. While it would be more secure to place the admin interface behind a reverse proxy for HTTPS access, that topic is beyond the scope of this article. AdGuard Home also supports DNS over HTTPS, DNS over TLS, DNS over QUIC, and DNSCrypt, which all require additional ports. These technologies will be discussed later in this article.

Listing 1

The AdGuard Home Service Definition

01 version: "3"
02 services:
03   adguard-home:
04     image: adguard/adguardhome:latest
05     container_name: adguard-home
06     ports:
07       - "53:53/udp"
08       - "53:53"
09       - "3000:3000"
10     restart: unless-stopped
11     volumes:
12       - /home/koan/containers/adguard-home/work:/opt/adguardhome/work
13       - /home/koan/containers/adguard-home/conf:/opt/adguardhome/conf

Launch the container with

docker-compose up -d

Once the latest AdGuard Home image is pulled, the container starts with its admin interface accessible on http://IP:3000, where IP is your Docker host's IP address. First, you will be prompted to follow an installation wizard (Figure 1). Click on Get Started. Then, select All interfaces for the Listen interface for both the admin web interface and the DNS server (Figure 2). Modify the port for the admin web interface to 3000, or keep the default port 80 and modify your docker-compose.yml file after the last installation step to export port 80 instead of 3000.

Figure 1: After starting the container, the installation wizard walks you through the steps to install and configure AdGuard Home.
Figure 2: Select the appropriate interfaces and ports.

In the next step, choose a username and password for access to the admin web interface. Upon clicking Next, the wizard explains how to configure your devices to use AdGuard Home's DNS server. Click Next, and then Open Dashboard. After logging in with the username and password you set, you'll see an initially empty dashboard (Figure 3).

Figure 3: Immediately after installation, AdGuard Home's dashboard is empty.

Synchronizing Multiple DNS Servers

As explained before, using a single DNS server poses risks because it becomes a single point of failure. Therefore, install at least one additional AdGuard Home instance on another computer. Once you have these two DNS servers set, you will next need to configure multiple instances. To prevent potential issues arising from different settings in your DNS servers, you'll need to synchronize their configurations.

Fortunately, AdGuardHome sync [4] was designed for this particular purpose. AdGuardHome sync is also deployable in a Docker container. You will define one of your AdGuard Home instances as the origin, and the other instances as replicas. After this, AdGuardHome sync continuously synchronizes any configuration changes on the origin instance to the replicas.

To do this, create a directory for AdGuardHome sync on one of your Docker hosts (it doesn't even have to be one of the hosts running your AdGuard Home instances):

$ mkdir -p $HOME/containers/adguard-home-sync

In this directory, create a file adguardhome-sync.yaml and copy the contents from the example configuration file in the project's README file on GitHub. Then tailor adguardhome-sync.yaml to your setup. Specifically, define the URL and credentials for your origin and replicas, and enable the API and metrics to get consolidated statistics, as shown in Listing 2.

Listing 2

Customizing adguardhome-sync.yaml

01 origin:
02   url: http://192.168.0.2:3000
03   username: admin
04   password: password
05
06 replicas:
07   - url: http://192.168.0.3:3000
08     username: admin
09     password: password
10   - url: http://192.168.0.4:3000
11     username: admin
12     password: password
13
14 api:
15   port: 8080
16   username: username
17   password: password
18   darkMode: true
19   metrics:
20     enabled: true
21     scrapeInterval: 30s
22     queryLogLimit: 10000

Next, add the AdGuardHome sync container to your docker-compose.yml file (Listing 3).

Listing 3

Adding the AdGuardHome sync Container

01 services:
02   adguard-home-sync:
03     image: ghcr.io/bakito/adguardhome-sync
04     container_name: adguard-home-sync
05     command: run --config /config/adguardhome-sync.yaml
06     volumes:
07       - /home/koan/containers/adguard-home-sync/adguardhome-sync.yaml:/config/adguardhome-sync.yaml
08     ports:
09       - 8080:8080
10     restart: unless-stopped

Launch the container with

docker-compose up -d

If successful, AdGuardHome sync's web interface becomes available on port 8080. Enter the username and password set in the api section, after which you'll see a basic dashboard displaying consolidated statistics from all of your AdGuard Home instances, links to the origin's and replicas' admin web interfaces, and a button to synchronize their configurations manually. By default, configurations automatically synchronize every two hours. You can adjust this via the cron variable (by default "0 */2 * * *") in the configuration file.

Buy this article as PDF

Download Article PDF now with Express Checkout
Price $2.95
(incl. VAT)

Buy Linux Magazine

Related content

  • Privacy Appliances

    A Raspberry Pi with the right software filters out annoying ads and nasty trackers for end devices on your local network.

  • WireGuard Easy

    WireGuard is a less complex VPN solution compared to OpenVPN and IPsec. WireGuard Easy simplifies the process even further by allowing you to operate a VPN and manage clients through a user-friendly web interface.

  • WireGuard

    A recent addition to the Linux kernel, WireGuard lets you build a VPN tunnel that relies on encryption to reduce potential security issues.

  • PiVPN

    With PiVPN, a system administrator can build a small private network and let end users attach to it themselves – and use it for running games.

  • Squid at Home

    Are your children wearing out their eyeballs on the Internet? Squid will help you impose some time limits and filter out inappropriate content.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News