Step 1: Basic Architecture
The following diagram provides overview of the solution:
- Two (2) adguard servers, each with their own IP address
- An additional IP address on each adguard server which is ‘clustered’ (HA) via keepalived.
In this solution clients will point to the keepalived (VIP) addresses, if a host fails clients wil have instantanous failover of DNS and will notice any failures.
Step 2: AdGuard Docker
We will deploy two AdGuard servers each with a docker container, isolating its configuration and work directory in a seperate directory structure:
# mkdir /opt/adguardhome
# mkdir /opt/adguardhome/work
# mkdir /opt/adguardhome/conf
# chmod 700 /opt/adguardhome/workCode language: PHP (php)
Create the docker compose configuration file /opt/adguardhome/docker-compose.yml
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguard
network_mode: host
volumes:
- /opt/adguardhome/work:/opt/adguardhome/work
- /opt/adguardhome/conf:/opt/adguardhome/conf
environment:
- TZ=Europe/Amsterdam
restart: unless-stoppedCode language: JavaScript (javascript)
Start the docker container and check its status:
# cd /opt/adguardhome
# docker compose up -d
# docker psCode language: PHP (php)
This is the moment that adguard is reachable via its webinterface and I configure the following extra details, which i skip in this blog:
- DNS Settings: define upstream servers
- DNS Settings: define upstream subdomain forwarders and reverse
- DNS Settings: define rate limiting
- Encryption settings: define SSL certificates
- Define DNS Blocklists
- etc
After this your basic adguard should be complete.
Step 3: Keepalived
So we will configure a keepalived cluster where each host has an active ip-address and is standby for the remote host. Lets first install the packages:
# apt install keepalivedCode language: PHP (php)
On the first adguard (01) server we define the following configuration file /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
admin@domain.com
}
notification_email_from adguard-01@domain.com
smtp_server 192.168.0.240
smtp_connect_timeout 30
router_id adguard-01
enable_script_security
script_user root
max_auto_priority -1
}
vrrp_script chk_adguard {
script "/usr/bin/pgrep -f AdGuardHome"
interval 3 # check every 3 seconds
weight -20 # drop priority by 20 if check fails → triggers failover
fall 2 # fail after 2 bad checks
rise 2 # recover after 2 good checks
}
vrrp_instance VI_1_IPv6 {
state MASTER
interface ens33
smtp_alert
virtual_router_id 10
priority 200
advert_int 1
virtual_ipaddress {
2a1a:381:13c:2::70/64 dev ens33
}
track_script {
chk_adguard
}
}
vrrp_instance VI_1_IPv4 {
state MASTER
interface ens33
smtp_alert
virtual_router_id 10
priority 200
advert_int 1
virtual_ipaddress {
192.168.0.70/27 dev ens33
}
track_script {
chk_adguard
}
}
vrrp_instance VI_2_IPv6 {
state BACKUP
interface ens33
smtp_alert
virtual_router_id 11
priority 150
advert_int 1
virtual_ipaddress {
2a1a:381:13c:2::71/64 dev ens33
}
track_script {
chk_adguard
}
}
vrrp_instance VI_2_IPv4 {
state BACKUP
interface ens33
smtp_alert
virtual_router_id 11
priority 150
advert_int 1
virtual_ipaddress {
192.168.0.71/27 dev ens33
}
track_script {
chk_adguard
}
}Code language: PHP (php)
Start the adguard (01) keepalived service, it should host all the IP’s as the second is not online:
# systemctl enable keepalived
# systemctl start keepalived
# tail -f /var/log/syslog
# ip addr list dev ens33Code language: PHP (php)
On the second adguard (02) server we define the following configuration file /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email_from adguard-02@domain.com
smtp_server 192.168.0.240
smtp_connect_timeout 30
router_id adguard-02
enable_script_security
script_user root
max_auto_priority -1
}
vrrp_script chk_adguard {
script "/usr/bin/pgrep -f AdGuardHome"
interval 3 # check every 3 seconds
weight -20 # drop priority by 20 if check fails → triggers failover
fall 2 # fail after 2 bad checks
rise 2 # recover after 2 good checks
}
vrrp_instance VI_1_IPv6 {
state BACKUP
interface ens33
smtp_alert
virtual_router_id 10
priority 150
advert_int 1
virtual_ipaddress {
2a1a:381:13c:2::70/64 dev ens33
}
track_script {
chk_adguard
}
}
vrrp_instance VI_1_IPv4 {
state BACKUP
interface ens33
smtp_alert
virtual_router_id 10
priority 150
advert_int 1
virtual_ipaddress {
192.168.0.70/27 dev ens33
}
track_script {
chk_adguard
}
}
vrrp_instance VI_2_IPv6 {
state MASTER
interface ens33
smtp_alert
virtual_router_id 11
priority 200
advert_int 1
virtual_ipaddress {
2a1a:381:13c:2::71/64 dev ens33
}
track_script {
chk_adguard
}
}
vrrp_instance VI_2_IPv4 {
state MASTER
interface ens33
smtp_alert
virtual_router_id 11
priority 200
advert_int 1
virtual_ipaddress {
192.168.0.71/27 dev ens33
}
track_script {
chk_adguard
}
}Code language: PHP (php)
Start the adguard (02) keepalived service, it should host all its own ip’s, now each adguard hosts is master ip and is backup to the other:
# systemctl enable keepalived
# systemctl start keepalived
# tail -f /var/log/syslog
# ip addr list dev ens33Code language: PHP (php)