Create a Secondary Pi-hole DNS Node and Test Resolver Resilience
Build an independent secondary Pi-hole resolver, align the settings that should match the primary, and test both resolvers before advertising them together to clients.
Expected Outcome
Two Pi-hole DNS resolvers that can each answer independently, with a documented client test proving the secondary remains usable when the primary resolver is unavailable.
Assumptions
A Raspberry Pi 3 or newer running a current Raspberry Pi OS release.
An existing primary Pi-hole resolver that is healthy before this Lab begins.
Console or SSH access with a user that can run `sudo` on both Pi-hole hosts.
A test client whose DNS settings can be changed without affecting the rest of the network.
A maintenance window if you intend to stop the primary Pi-hole service for an outage test.
Bill of Materials
Secondary Raspberry Pi with a reliable power supply and supported storage.
Network access to the official Pi-hole GitHub repository.
A record of the primary resolver's upstream DNS choices, local DNS records, allow/block policy, and DHCP role if Pi-hole provides DHCP.
A workstation with `dig` or an equivalent DNS query tool for direct resolver tests.
Build Steps
- Capture the primary and secondary network baseline
Record the primary resolver address, secondary host address, default gateway, and current upstream DNS policy before installing or changing anything. The secondary must be able to resolve externally without depending on the primary Pi-hole; otherwise a primary outage also removes the secondary's upstream path.
Manual or UI step
hostnamectl
ip -brief address
ip route
Read-only command: verify target and scope
cat /etc/resolv.conf
- Install prerequisites and retrieve the official Pi-hole installer source
Install Git and DNS test utilities, then clone the official Pi-hole repository rather than piping a remote installer directly into a privileged shell. Record the exact Git commit you reviewed so the installation evidence identifies what was executed.
Changes system state: review before running
sudo apt update sudo apt install -y git dnsutils git clone --depth 1 https://github.com/pi-hole/pi-hole.git ~/Pi-hole git -C ~/Pi-hole rev-parse HEAD
Manual or UI step
less "$HOME/Pi-hole/automated install/basic-install.sh"
- Install Pi-hole from the reviewed local script
Run the locally reviewed installer and choose the interface, static address, and upstream resolver deliberately. Configure upstream resolvers that remain reachable when the primary Pi-hole is offline; do not point the secondary exclusively at the primary Pi-hole if resilience is the goal.
Review before running: verify target, scope, and execution context
sudo bash "$HOME/Pi-hole/automated install/basic-install.sh"
Manual or UI step
pihole status
pihole version
- Align policy without copying live Pi-hole state directories
Use Pi-hole's supported configuration and administration surfaces to reproduce only the settings that should match: upstream policy, adlists, allow/block entries, local DNS records, privacy settings, and any other intentional policy. Pi-hole v6 stores configuration in /etc/pihole/pihole.toml, but do not use a generic rsync --delete of /etc/pihole or /etc/dnsmasq.d as a synchronization strategy; those paths can contain node-specific and live service state.
Manual or UI step
pihole status
Read-only command: verify target and scope
sudo ls -l /etc/pihole/pihole.toml
- Prove each resolver independently
Query the primary and secondary explicitly from a test client. Direct queries establish that each resolver works on its own before client configuration introduces resolver-selection behavior.
Read-only command: verify target and scope
dig @<PRIMARY_PI_IP> example.com A +short dig @<SECONDARY_PI_IP> example.com A +short dig @<PRIMARY_PI_IP> pi.hole A +short dig @<SECONDARY_PI_IP> pi.hole A +short
- Test one client with both resolver addresses
Configure only a disposable or low-impact test client to use both Pi-hole addresses. Do not assume clients will always use the first address until it fails; resolver selection and retry behavior vary by operating system and application. Generate several DNS lookups and confirm both Pi-hole dashboards or query logs reflect expected traffic before changing router-wide DHCP settings.
Read-only command: verify target and scope
dig example.com dig cloudflare.com dig github.com
- Run a controlled primary-outage test
If the maintenance window allows it, temporarily stop Pi-hole DNS on the primary, then repeat direct and normal client lookups. The success criterion is not that every client instantly switches in a strict order; it is that the tested client can still resolve through the secondary and that you have observed the actual failover behavior of your client/network combination.
Changes system state: review before running
ssh <PRIMARY_ADMIN>@<PRIMARY_PI_IP> 'sudo systemctl stop pihole-FTL' dig @<SECONDARY_PI_IP> example.com A +short dig example.com
- Restore the primary and decide whether to advertise both resolvers
Restore the primary service first. Only after direct tests and the controlled client test succeed should you update router or DHCP scope options to advertise both resolver addresses. Preserve the prior DHCP/DNS settings so the network-wide change has an immediate backout path.
Changes system state: review before running
ssh <PRIMARY_ADMIN>@<PRIMARY_PI_IP> 'sudo systemctl start pihole-FTL' dig @<PRIMARY_PI_IP> example.com A +short dig @<SECONDARY_PI_IP> example.com A +short
Validation
Confirm both Pi-hole services are healthy and independently answer direct DNS queries.
Read-only command: verify target and scope
dig @<PRIMARY_PI_IP> example.com A +short dig @<SECONDARY_PI_IP> example.com A +short
Confirm the secondary still resolves while the primary service is stopped during the approved outage test.
Read-only command: verify target and scope
dig @<SECONDARY_PI_IP> example.com A +short
After restoring the primary, confirm both resolvers are healthy before ending the maintenance window.
Read-only command: verify target and scope
dig @<PRIMARY_PI_IP> example.com A +short dig @<SECONDARY_PI_IP> example.com A +short
Troubleshooting
If the secondary answers local queries but not internet names, verify its configured upstream resolvers and routing. Do not make the secondary depend exclusively on the primary if the objective is primary-resolver outage resilience.
Manual or UI step
ip route
pihole status
Read-only command: verify target and scope
dig @<SECONDARY_PI_IP> example.com
If a client does not switch as expected, verify the DNS addresses the client actually received and test each resolver explicitly. Client behavior can differ from a simple primary/secondary ordering assumption.
Cleanup or Rollback
Always restore the primary Pi-hole service after an outage test.
Changes system state: review before running
ssh <PRIMARY_ADMIN>@<PRIMARY_PI_IP> 'sudo systemctl start pihole-FTL'
If network-wide testing fails, restore the previous router or DHCP DNS options and remove any temporary DNS override from the test client. Leave the secondary unadvertised until the failure is understood.
Next Improvements
Document how policy changes will be kept aligned across the two Pi-hole nodes using supported administration/configuration methods.
Repeat the outage test from representative Windows, Linux, mobile, or appliance clients if their DNS behavior matters to your environment.
Add monitoring for resolver availability so a failed node is visible before the next maintenance event.
