๐Ÿ—๏ธ Project Overview

This project addresses a Single Point of Failure (SPOF) in home network infrastructure. By implementing a high-availability (HA) DNS cluster using AdGuard Home and Keepalived, I have ensured that network-wide ad-blocking and DNS resolution remain active even if the primary server fails.


๐Ÿ› ๏ธ Toolset & Hardware

Tool Purpose Environment
Truthwatcher Primary DNS Node Proxmox VM (Ubuntu/Debian)
Pattern Secondary DNS Node Raspberry Pi 2B+ (DietPi)
Keepalived VRRP Failover Management Linux Service
AdGuard Home DNS Sinkhole / Security Application
AdGuardHome-Sync Configuration Mirroring Go Binary (ARMv7)
Uptime Kuma Health Monitoring Monitoring Suite

๐Ÿ”„ The Process

Phase 1: High Availability (Layer 3)

I configured the Virtual Router Redundancy Protocol (VRRP) to create a “Floating IP” (Virtual IP). This allows devices to point to one address that automatically moves to the active server.

Primary Node Config (/etc/keepalived/keepalived.conf):

vrrp_instance VI_DNS {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass <password>
    }
    virtual_ipaddress {
        10.0.0.231       # IPv4 VIP
        fd00::231/64     # IPv6 VIP
    }
}

Phase 2: Configuration Sync (Layer 7)

Because AdGuard Home stores its own local database, I used adguardhome-sync on the Raspberry Pi to “pull” the rules from the VM every 5 minutes.

Sync Config (/etc/adguardhome-sync.yaml):

YAML
origin:
  url: [http://10.0.0.230:80](http://10.0.0.230:80)
  username: vm_admin
  password: vm_password
replicas:
  - url: http://localhost:8083
    username: pi_admin
    password: pi_password
cron: "*/5 * * * * 

๐Ÿงช Verification & Health Script

I developed a custom bash script to verify both the network state (VIP location) and the application state (filter rule count).

Health Script (/home/matt/dns-health.sh):

Bash
#!/bin/bash
# File: ~/dns-health.sh
VIP="10.0.0.231"
RULE_COUNT=$(curl -s -u admin:pass "http://localhost:8083/control/filtering/status" | grep -oP '"url":' | wc -l)

echo "--- Wardeck DNS Health Check ---"
if ip addr show | grep -q "$VIP"; then
    echo "[INFO] VIP ($VIP) is ACTIVE on this Node (MASTER)."
else
    echo "[INFO] VIP ($VIP) is ACTIVE on Primary VM (BACKUP)."
fi
echo "[INFO] Local AdGuard Filter Rules: $RULE_COUNT" 

๐Ÿ›ก๏ธ Disaster Recovery & Maintenance

To Restart Cluster:sudo systemctl restart keepalived on both nodes.

To Force Sync: /usr/local/bin/adguardhome-sync run --config /etc/adguardhome-sync.yaml

Network Impact: Failover occurs in <3 seconds. Clients experience zero loss of connectivity.