Featured image of post Sync Multiple Pi-hole Servers with Nebula Sync

Sync Multiple Pi-hole Servers with Nebula Sync

Keep blocklists, local DNS, and settings identical across Pi-hole v6 nodes

You add a blocklist to your first Pi-hole. Easy. Then you remember you’ve got two more Pi-holes scattered around your network. Each one needs the same update. Manually. You tab between admin pages, copying settings, and by the second one you’re asking yourself why you ever thought multiple Pi-holes was a good idea.

Nebula Sync On GitHub fixes this. It keeps multiple Pi-hole servers in sync by automatically copying blocklists, local DNS records, and settings from one primary Pi-hole to all your replicas. Change something once on the primary, and Nebula pushes it everywhere else within a few mins.

If you’re running multiple Pi-holes and you’re tired of manual updates, this guide will get you set up. If you can log into pihole/admin and run Docker, you can do this.

💭 TL;DR
Run multiple Pi-hole servers for redundancy, designate one as primary, and use Nebula Sync to automatically replicate blocklists, local DNS, and settings to all replicas without manual updates.

Quick checklist:

  • 2+ working Pi-hole nodes (same major version, ideally v6)
  • One node chosen as PRIMARY (the only one you edit)
  • A basic understanding of Docker/Compose
  • Router/DHCP hands out both Pi-hole IPs (DNS) for failover

Why Sync Multiple Pi-hole Servers?

Why Run More Than One Pi-hole?

One Pi-hole works great until it doesn’t. Maybe you’re updating it at 2am and something breaks. Maybe the SD card dies. Whatever the reason, when your single DNS server goes down, your entire network loses internet. Your spouse can’t stream. The smart home stops working. You know how this goes.

Multiple Pi-holes solve this:

  • Redundancy: One Pi-hole fails, DNS keeps working.
  • Maintenance without downtime: Update one node while the other handles queries.
  • Better coverage: Every device stays protected during updates or failures.

The problem? Managing them manually is a pain. Every blocklist or whitelist addition, every DNS entry, every setting tweak has to be repeated on each node. That gets old fast.

Two Sync Approaches, One Clear Winner for v6

You’ve got two main options for syncing Pi-holes:

Gravity Sync is the old reliable. It’s a bash script that syncs databases over SSH. Works great for Pi-hole v5.x, but it wasn’t built for v6’s API architecture.

Nebula Sync is newer and designed specifically for Pi-hole v6’s web API. It syncs more than just gravity databases and handles the modern Pi-hole setup better.

We’re using Nebula Sync here because it’s built for v6 and just works cleaner with current Pi-hole versions.

Prerequisites and Lab Layout

What You Need

Before you start, make sure you have:

  • Two or more working Pi-hole servers
  • Each Pi-hole accessible at http://<ip>/admin or https://<host>/admin
  • An admin password set on each Pi-hole
  • Something that can run Docker (often one of the Pi-holes works fine)
RaspberryPi 4GB: Best for: Running Pi-hole servers as described in the post. Why it fits this post: Low-power, affordable, and widely used for Pi-hole deployment…

RaspberryPi 4GB Must have for this build.

  • Best for: Running Pi-hole servers as described in the post.
  • Why: Low-power, affordable, and widely used for Pi-hole deployments; ideal for syncing multiple DNS blockers.
  • Tradeoffs: Limited performance for heavier workloads; not suitable for large-scale DNS or heavy multitasking.

Current Amazon Price: Loading...
Amazon Availability: Checking...

Contains affiliate links. I may earn a commission at no cost to you.

Example Setup

Throughout this guide, I’ll use:

  • pihole1 at 192.168.1.10 (Primary)
  • pihole2 at 192.168.1.11 (Replica)

Swap in your own IPs. You can add more replicas later.

Check Pi-hole Versions (Important)

Log into each pihole/admin dashboard and check the version at the bottom of the page.

Keep all nodes on the same major version, ideally v6.x. Mixing versions causes weird issues. If they don’t match, update each node:

pihole -up

Decide Where Nebula Sync Will Run

Two common options:

  • Option A (simplest): Run Nebula Sync as a Docker container on the primary Pi-hole.
  • Option B: Run it on a separate Docker host that can reach all Pi-hole admin URLs.

For most people, Option A is easiest.

Step 1: Verify Each Pi-hole Works Standalone

Don’t skip this. If a Pi-hole is broken before you sync it, you’ll just spread the brokenness around.

On each Pi-hole:

  1. Open http://<pihole-ip>/admin.
  2. Log in with the admin password.
  3. Confirm the dashboard loads and shows recent queries.
  4. From the terminal, tail logs:
pihole -t
  1. From a client device, temporarily set DNS to only that Pi-hole and browse a few sites.

If DNS queries show up in the log, you’re good. If not, fix networking or service issues before moving on.

Step 2: Gather URLs and Credentials

Nebula Sync talks to Pi-hole via the web API, so you need the exact URLs and passwords.

For each Pi-hole, write down:

  • Full admin URL, including /admin
    • Example: http://192.168.1.10/admin
  • Admin password

Nebula expects this format:

URL|password

Example:

http://192.168.1.10/admin|SuperSecretPassword
💡
Tip: About 80% of sync failures happen because someone forgot /admin at the end of the URL. Don’t be that person.

Step 3: Create a Nebula Sync Docker Compose File

Most people deploy Nebula Sync with Docker Compose or Portainer.

Example compose.yml

services:
  nebula-sync:
    image: ghcr.io/lovelaze/nebula-sync:latest
    container_name: nebula-sync
    environment:
      - PRIMARY=http://192.168.1.10/admin|PRIMARY_PASSWORD
      - REPLICAS=http://192.168.1.11/admin|REPLICA_PASSWORD
      - FULL_SYNC=true
      - RUN_GRAVITY=true
      - SCHEDULE=*/5 * * * *
    restart: unless-stopped

Replace the URLs and passwords with your actual ones.

⚠️
Warning: Putting passwords directly in the compose file works but isn’t great. For better security, use a .env file:

Do this instead from the same directory where your compose.yaml file lives

nano .env

and paste this:

PIHOLE_PRIMARY_URL=http://192.168.1.10/admin
PIHOLE_PRIMARY_PASSWORD=YourSecretPassword

PIHOLE_SECONDARY_URL=http://192.168.1.11/admin
PIHOLE_SECONDARY_PASSWORD=YourSecretPassword

Then reference them in compose like this:

- PRIMARY=${PIHOLE_PRIMARY_URL}|${PIHOLE_PRIMARY_PASSWORD}
- REPLICAS=${PIHOLE_SECONDARY_URL}|${PIHOLE_SECONDARY_PASSWORD}

Now you can share your compose file and not have to worry about removing the password.

Example 2 .env compose.yaml

services:
  nebula-sync:
    image: ghcr.io/lovelaze/nebula-sync:latest
    container_name: nebula-sync
    env_file:
      - .env
    environment:
      - PRIMARY=${PIHOLE_PRIMARY_URL}|${PIHOLE_PRIMARY_PASSWORD}
      - REPLICAS=${PIHOLE_SECONDARY_URL}|${PIHOLE_SECONDARY_PASSWORD}
      - FULL_SYNC=true
      - RUN_GRAVITY=true
      - CRON=*/5 * * * *
    restart: unless-stopped

Key Environment Variables Explained

  • PRIMARY: The Pi-hole you’ll always edit manually. This is your source of truth.
  • REPLICAS: Pi-holes that receive config from the primary. Separate multiple with spaces.
  • FULL_SYNC: Set to true to sync everything Nebula supports.
  • RUN_GRAVITY: Tells Pi-hole to run gravity after syncing.
  • SCHEDULE: Cron-style interval. */5 * * * * means every 5 minutes, a good starting point.

Common mistakes:

  • Missing /admin
  • Wrong http:// vs https://
  • Typos in passwords

Step 4: Deploy Nebula Sync

From the directory containing your compose file:

docker compose up -d

Then check logs:

docker logs -f nebula-sync

What you want to see:

  • Successful connection to primary
  • Sync operations targeting replicas
  • No authentication or connection errors

If you see authentication errors, double-check those URLs and passwords. Connection errors? Verify HTTP vs HTTPS and make sure you can load the admin pages in a browser from the Docker host.

Step 5: First Sync Test with Gravity and Blocklists

Time to confirm real data is syncing.

On the primary Pi-hole:

  1. Go to Group Management > Adlists.
  2. Add a test blocklist or toggle an existing one.
  3. Click Save and Update

Wait for the next Nebula run (or restart the container because who has patience?).

On the replica:

  1. Open /admin.
  2. Navigate to Group Management > Adlists.
  3. Confirm the new list appears and domain counts match closely.

If it’s there, gravity syncing works. Nice.

Step 6: Sync Local DNS and Custom Entries

This is where Nebula Sync really shines compared to older tools. Custom DNS entries sync automatically.

On the primary:

  1. Go to Local DNS > DNS Records.
  2. Add:
    • Hostname: tim.example.com
    • IP: 10.0.0.50
  3. Save.

After the next sync:

On the replica:

  1. Open Local DNS > DNS Records.
  2. Search for tim.example.com.
  3. Confirm it exists and points to the same IP.

Test it:

nslookup tim.example.com 192.168.1.11

You should get 10.0.0.50.

Step 7: Day-to-Day Workflow (Primary/Replica Rules)

Once everything’s working, the rules are simple:

  • Always make changes on the primary Pi-hole.
  • Treat replicas as read-only in the UI.
  • Let Nebula Sync handle propagation.

You can adjust the sync frequency if needed. For most homelabs, every 5 to 15 minutes works well. More frequent syncing means less drift time but more API calls hitting your Pi-holes.

Step 8: Router and Client DNS Configuration

To actually benefit from multiple Pi-holes, clients need to know about them.

Simple Setup: Two DNS IPs

In your router’s DHCP settings:

  • DNS 1: 192.168.1.10
  • DNS 2: 192.168.1.11

Clients automatically fail over if one Pi-hole is unavailable. It’s not instant, but it works.

Advanced Option: Virtual IP

If you’re feeling ambitious, tools like keepalived can give you a single virtual IP that floats between Pi-holes. This is optional and overkill for most people.

Step 9: Testing Failover and Basic Pi-hole Tests

Make sure your redundancy actually works:

  1. Ensure clients receive both DNS IPs from DHCP.
  2. Stop Pi-hole on the primary or reboot the server.
  3. Browse the web from a client.
  4. Check the replica’s Query Log for activity.

Useful commands:

  • pihole -t to watch live queries
  • dig or nslookup against each Pi-hole IP
  • Visit ad-heavy sites and confirm blocks appear

Step 10: Maintenance and Updates

Updating Pi-hole

On each node:

pihole -up

Keep versions aligned to avoid API mismatches.

Updating Nebula Sync

From the compose directory:

docker compose pull
docker compose up -d

Backup Strategy

Before major changes:

  • Export Pi-hole config from the primary
  • Keep a copy offline

If something breaks:

  1. Stop the Nebula container.
  2. Restore the primary from backup.
  3. Restart Nebula Sync.

Troubleshooting Common Problems

Quick Troubleshooting Table

Symptom Likely cause Fix
Authentication errors in Nebula logs Wrong password or URL format Re-check password and make sure the URL includes /admin
Connection errors / timeouts Wrong scheme (HTTP vs HTTPS) or network issues Verify http:// vs https://, check firewalls, make sure the admin UI loads in a browser
Changes not appearing on replicas FULL_SYNC disabled, schedule not running, or edits made on replica Confirm FULL_SYNC=true, check logs for runs, only edit the primary
Nodes drift after updates Mixed major versions Upgrade all nodes; don’t mix v5 and v6
Expecting DHCP to sync Not supported Keep DHCP on router or manage separately

Nebula Sync Fails Authentication

  • Double-check admin passwords.
  • Confirm /admin is included in the URL.
  • Verify HTTP vs HTTPS.

Changes Not Appearing on Replicas

  • Confirm FULL_SYNC=true.
  • Check Nebula logs for recent runs.
  • Make sure changes were made on the primary only.

Mixed Pi-hole Versions

  • Upgrade all nodes to the same major version.
  • Don’t mix v5 and v6.

DHCP Expectations

Nebula Sync does not sync DHCP settings or leases. Keep DHCP on your router or manage it separately.

Beelink SER5 (Ryzen 5 5600H): Best for: Users seeking a quiet, compact upgrade from Raspberry Pi for Pi-hole and light Docker stacks. Why it fits this post: …

Beelink SER5 (Ryzen 5 5600H)
Nice to have, not required.

  • Best for: Users seeking a quiet, compact upgrade from Raspberry Pi for Pi-hole and light Docker stacks.
  • Why: Handles Pi-hole plus additional homelab duties with ease.
  • Tradeoffs: More expensive and power-hungry than a Pi; still limited for heavy virtualization.

Current Amazon Price: Loading...
Amazon Availability: Checking...

Contains affiliate links. I may earn a commission at no cost to you.

FAQs (Nebula Sync + Pi-hole)

➤ Can I sync more than two Pi-hole servers with Nebula Sync?

Yes. Define one primary and add multiple replicas in the REPLICAS variable. Example:

- REPLICAS=http://ph2.example.com|password,http://ph3.example.com|password

or with env:

- REPLICAS=${PIHOLE_SECONDARY_URL}|${PIHOLE_SECONDARY_PASSWORD},${PIHOLE_TERTIARY_URL}|${PIHOLE_TERTIARY_PASSWORD}
➤ Do I have to run Nebula Sync in Docker?
Docker is the most common and easiest approach for updates and isolation.
➤ oes Nebula Sync work with Pi-hole v6?
Yes. It’s designed around Pi-hole v6’s web API and HTTPS admin interface.
➤ Will Nebula Sync keep DHCP settings in sync?
No. DHCP settings and leases are node-specific and don’t sync.
➤ Can I edit settings directly on replicas?
You can, but Nebula will overwrite them on the next run. Save yourself the headache and only edit the primary.
➤ What happens if a replica is offline during sync?
Nebula will fail that run and catch up when the replica comes back online.
➤ Is it safe to mix HTTP and HTTPS?
Yes, as long as each Pi-hole is defined with the correct scheme in Nebula’s config.
➤ How often should I run the sync?
Every 5 to 15 minutes is typical for homelabs.
➤ Do I still need to run `pihole -g` on replicas?
No. Run it on the primary only. Nebula syncs the results.
➤ How do I test that everything works?
Add a test DNS record or blocklist on the primary and confirm it appears and functions on replicas.

Conclusion

Running multiple Pi-hole servers for redundancy is great until you realize you’ve tripled your management overhead. Nebula Sync fixes this by letting you treat one Pi-hole as the source of truth and having the rest automatically mirror it.

If you’re tired of juggling multiple pihole/admin pages and trying to remember which server has the latest config, this setup changes everything. Start with two nodes, get comfortable with the workflow, then add more as you need them.

Next steps:

  • Experiment with sync schedules
  • Add a third replica
  • Explore virtual IP failover if you want true high availability

Once you’ve got this running, you won’t go back to manual Pi-hole updates.

MINISFORUM MS-01 Mini Workstation: Best for: Readers planning to expand beyond Pi-hole to VMs, containers, or more demanding homelab tasks. Why it fits this …

MINISFORUM MS-01 Mini Workstation
Optional upgrade.

  • Best for: Readers planning to expand beyond Pi-hole to VMs, containers, or more demanding homelab tasks.
  • Why: Dual 10G SFP+ and 2.5GbE support advanced networking for syncing multiple servers.
  • Tradeoffs: Not needed for simple Pi-hole sync; higher price and complexity.

Current Amazon Price: Loading...
Amazon Availability: Checking...

Contains affiliate links. I may earn a commission at no cost to you.

© 2024 - 2025 DiyMediaServer

Buy Me a Coffee

Built with Hugo
Using a modified Theme Stack designed by Jimmy