PiHole – Add KeepAlive on two Pi’s

PiHole - Add KeepAlive on two Pi's
August 11, 2026

Setting up keepalived for dual Pi-holes requires installing the package on both machines, writing a short configuration file on each, and pointing your network/AD DNS forwarder to the shared Virtual IP (VIP).

Prerequisites & Example Values

Check your network interface name using ip a (usually eth0 for wired or wlan0 for Wi-Fi).

  • Pi-hole A (Primary): 192.168.1.10 (Interface: eth0)

  • Pi-hole B (Secondary): 192.168.1.11 (Interface: eth0)

  • Shared Virtual IP (VIP): 192.168.1.99 (Choose an unused static IP outside your DHCP range)

Step 1: Install keepalived on Both Pi-holes

Run the following commands on both Pi-hole servers:

sudo apt update sudo apt install -y keepalived 

Allow the Linux kernel to bind to non-local IP addresses (needed so Pi-hole can bind to the VIP even when it's not the active master):

echo "net.ipv4.ip_nonlocal_bind=1" | sudo tee -a /etc/sysctl.d/99-keepalived.conf sudo sysctl --system 

Step 2: Configure Pi-hole A (Primary / MASTER)

Create the configuration file on Pi-hole A:

sudo nano /etc/keepalived/keepalived.conf 

Paste the following configuration:

vrrp_script check_pihole { # Verify Pi-hole DNS service is answering queries locally script "dig +short +time=1 +tries=1 @127.0.0.1 google.com > /dev/null 2>&1" interval 2 weight -20 } vrrp_instance VI_PIHOLE { state MASTER interface eth0 # Replace with your interface if different (e.g., wlan0) virtual_router_id 51 # Must be identical on both Pis (1-255) priority 100 # Higher priority = primary holder of VIP advert_int 1 authentication { auth_type PASS auth_pass SecretPass123 # Must match on both Pis (max 8 chars) } virtual_ipaddress { 192.168.1.99/24 # Your shared VIP } track_script { check_pihole } } 

Save and exit (Ctrl+O, Enter, Ctrl+X).

Step 3: Configure Pi-hole B (Secondary / BACKUP)

Create the configuration file on Pi-hole B:

sudo nano /etc/keepalived/keepalived.conf 

Paste the following configuration:

vrrp_script check_pihole { script "dig +short +time=1 +tries=1 @127.0.0.1 google.com > /dev/null 2>&1" interval 2 weight -20 } vrrp_instance VI_PIHOLE { state BACKUP interface eth0 # Replace with your interface if different virtual_router_id 51 # Must match Pi-hole A priority 90 # Lower priority than Master advert_int 1 authentication { auth_type PASS auth_pass SecretPass123 # Must match Pi-hole A } virtual_ipaddress { 192.168.1.99/24 # Same shared VIP } track_script { check_pihole } } 

Save and exit (Ctrl+O, Enter, Ctrl+X).

Step 4: Start and Enable the Services

Run these commands on both Pi-holes:

sudo systemctl enable keepalived sudo systemctl restart keepalived 

Step 5: Verify Failover Operation

  1. Check which Pi holds the VIP: On Pi-hole A, run:

    ip a show eth0 

    You should see inet 192.168.1.99/24 listed as a secondary IP on the interface.

  2. Test Failover:

    • Stop the service on Pi-hole A:

      sudo systemctl stop keepalived 
    • Run ip a show eth0 on Pi-hole B192.168.1.99 will immediately appear on Pi-hole B.

    • Start keepalived back up on Pi-hole A:

      sudo systemctl start keepalived 
    • Pi-hole A will reclaim the VIP because its priority (100) is higher than Pi-hole B's (90).

  3. Update Upstream Settings: Set the DNS forwarder address on your Active Directory DNS server, Synology NAS, or pfSense/DHCP scope to point strictly to the Virtual IP (192.168.1.99).