Sync Pi-Hole Settings and Blocklists between Instances with Nebula Sync

If you were like me, when you saw the Gravity Sync project was archived and would have no future development, this was a bummer as I have relied on Gravity sync for quite some time now to sync Pi-Hole instances. However, in steps the power of community! Another developer took on the project to carry it forward and also make the project compatible with the newest version of Pi-Hole, Pi-Hole v6. The project is called Nebula Sync and is a great new project that you need to know about if you want to sync Pi-Hole settings and blocklists between multiple Pi-Hole instances.
Table of contents
Brief overview of Pi-Hole
Before we jump in, let’s talk about Pi-Hole just briefly. Pi-Hole is an extremely popular open-source project that functions as a DNS sinkhole solution that blocks unwanted content across all devices it is in front of. So, it performs this role “network-wide”.
It intercepts DNS queries that are destined for advertising domains or malicious domains and sinkholes or drops these. By doing this, it speeds up your network and makes it more secure, even reducing your data usage from unwanted domains that are being connected to in the background. Due to its light nature, it can run on many different hardware platforms, including Raspberry Pi, from which it gets its name.
It has a user-friendly web interface, and now also has an API in v6 that makes things really interesting, and what makes projects like Nebula Sync possible.
Brief overview of Nebula Sync
Now for Nebula-Sync. It is an open-source tool that does what Gravity Sync used to do with v5 and lower. That is to sync pi-hole settings between multiple Pi-Hole instances. Nebula-Sync is compatible with the new v6 and higher instances and now uses the API to perform synchronization tasks. This makes sure all instances are in sync in terms of settings, blocklists, custom configs, etc.
Note the features of Nebula Sync:โ
- Full Synchronization: It uses Pi-Hole’s Teleporter feature for full synchronization
- Selective Synchronization: You can sync specific features or settings.
- Scheduled Synchronization: It has cron scheduling to automate syncs at certain intervals
Using this type of configuration, you can effectively have multiple Pi-Hole instances that can satisfy the design of DNS failover in your home lab network. See my recent blog on this topic here:
Why Have Two Pi-Hole Instances to Sync?
Deploying multiple Pi-Hole instances has several advantages:โ
- Redundancy: It makes sure you have continuous DNS resolution and filtering even if one instance fails or you need to take it down for maintenance
- Load Distribution: While this solution is not a “load balanced” solution per se, you can distribute the DNS query loads across multiple instances if you were to put a load blancer in front of the Pi-Hole instances
If you try to manage settings in a “sneakernet” fashion across your installations, changes are there will be discrepancies. Nebula Sync allows you to automate this whole process and sync pi-hole settings which means it won’t be a manual or tedious process that you have to carry out by hand.
How to Install Nebula Sync (as a Container)
Installing Nebula Sync as a Docker container is what I would call the easiest way to get the solution up and running. With a container image, you have all the dependencies included and this simplifies the deployment. Below are the steps to install Nebula Sync using Docker Compose code:โ
- Prepare a Docker host
- Make sure you have a Docker host in your environment where you have Docker and Docker Compose installed
- Make sure Pi-Hole instances are running and you can connect to them
- Create a Directory for Nebula Sync – I like to create directories for my services in a parent directory like “homelabservices” or something like that. Underneath, create the individual folders for your services:
mkdir nebula-sync
cd nebula-sync
- Create the Docker Compose Configuration: Create a
docker-compose.yml
file with the following content to sync pi-hole settings:
version: '3'
services:
nebula-sync:
image: ghcr.io/lovelaze/nebula-sync:latest
container_name: nebula-sync
environment:
- PRIMARY=https://pihole01.mydomain.com|<password>
- REPLICAS=https://pihole02.mydomain.com|<password>
- FULL_SYNC=false
- RUN_GRAVITY=false
- CRON=*/15 * * * *
# Sync configuration options
- SYNC_CONFIG_DNS=true
- SYNC_CONFIG_DHCP=false
- SYNC_CONFIG_NTP=false
- SYNC_CONFIG_RESOLVER=false
- SYNC_CONFIG_DATABASE=false
- SYNC_CONFIG_MISC=false
- SYNC_CONFIG_DEBUG=false
# Sync gravity options
- SYNC_GRAVITY_DHCP_LEASES=false
- SYNC_GRAVITY_GROUP=false
- SYNC_GRAVITY_AD_LIST=true
- SYNC_GRAVITY_AD_LIST_BY_GROUP=true
- SYNC_GRAVITY_DOMAIN_LIST=true
- SYNC_GRAVITY_DOMAIN_LIST_BY_GROUP=true
- SYNC_GRAVITY_CLIENT=false
- SYNC_GRAVITY_CLIENT_BY_GROUP=false
restart: always
Just as a note about some of the above, these allow to just do a delta sync of specific items with your Pi-Hole instances. You likely don’t want to do a “full sync” since this literally copies everything and from what I have found makes your web interface unresponsive on the target for a time while the sync happens and full gravity config.
In the Docker compose code example above, you will replace the config with your own custom values in your environment.
- Run a docker-compose up command for the Nebula Sync Container:
docker-compose up -d
This command will download the Nebula Sync image and start the container in detached mode.
After you run your docker-compose up -d command, it is a good idea to check your Nebula-sync container logs to make sure you don’t see any errors listed.
If you want to check out other configuration options and environment variables, take a look at the official Nebula Sync GitHub repository.โ
How to Configure Nebula Sync to Sync Pi-Hole
Configuring Nebula Sync involves setting environment variables to define synchronization behavior. Key configurations include:โ
- PRIMARY: Sets the primary Pi-Hole node in the format http://<address>|<password>.โ
- REPLICAS: Sets your replica Pi-Hole instances, separated by commas, each with the format http://<address>|<password>.โ
- FULL_SYNC: When set to true, it performs a full Teleporter import/export synchronization.โ
- CRON: Sets the cron schedule for synchronization (e.g.,
0 * * * *
for hourly syncs).โ - RUN_GRAVITY: When set to true, runs Pi-Hole’s gravity after synchronization to update blocklists
Optional Environment Variables
Name | Default | Example | Description |
---|---|---|---|
CRON | n/a | 0 * * * * | Specifies the cron schedule for synchronization |
RUN_GRAVITY | false | true | Specifies whether to run gravity after syncing |
TZ | n/a | Europe/London | Specifies the timezone for logs and cron |
CLIENT_SKIP_TLS_VERIFICATION | false | true | Skips TLS certificate verification |
CLIENT_RETRY_DELAY_SECONDS | 1 | 5 | Seconds to delay between connection attempts |
CLIENT_TIMEOUT_SECONDS | 20 | 60 | Http client timeout in seconds |
Note: The following optional settings apply only if
FULL_SYNC=false
. They allow for granular control of synchronization if a full sync is not wanted. Note the following other settings below once you set the FULL_SYNC=false
Name | Default | Description |
---|---|---|
SYNC_CONFIG_DNS | false | Synchronize DNS settings |
SYNC_CONFIG_DHCP | false | Synchronize DHCP settings |
SYNC_CONFIG_NTP | false | Synchronize NTP settings |
SYNC_CONFIG_RESOLVER | false | Synchronize resolver settings |
SYNC_CONFIG_DATABASE | false | Synchronize database settings |
SYNC_CONFIG_MISC | false | Synchronize miscellaneous settings |
SYNC_CONFIG_DEBUG | false | Synchronize debug settings |
SYNC_GRAVITY_DHCP_LEASES | false | Synchronize DHCP leases |
SYNC_GRAVITY_GROUP | false | Synchronize groups |
SYNC_GRAVITY_AD_LIST | false | Synchronize ad lists |
SYNC_GRAVITY_AD_LIST_BY_GROUP | false | Synchronize ad lists by group |
SYNC_GRAVITY_DOMAIN_LIST | false | Synchronize domain lists |
SYNC_GRAVITY_DOMAIN_LIST_BY_GROUP | false | Synchronize domain lists by group |
SYNC_GRAVITY_CLIENT | false | Synchronize clients |
SYNC_GRAVITY_CLIENT_BY_GROUP | false | Synchronize clients by group |
These environment variables can be set in the docker-compose.yml file (as you see we have done above) or in an external .env file. Again for a full list of configuration options, look at the Nebula Sync documentation.โ
Pros and cons of Nebula Sync
Note the following pros of the solution:
Pros of Nebula Sync
1. Centralized Management
- You can sync blocklists, settings, and configurations from a primary Pi-hole to one or more replicas
2. Full or Partial Sync Options
- You can do full syncs using Pi-hole’s Teleporter or hand pick settings to sync for specific configurations
3. Docker-Friendly
- It is easy to deploy using Docker or Docker Compose
4. Cron-Based
- You can use cron to automate syncs on your schedule using all the granularity that cron provides
5. Redundancy for High Availability
- It allows you to successfully setup high availability or DNS failover with two Pi-Hole instances
7. Gravity Reload Support
- You can automatically update and run gravity updates after syncing to make sure your blocklists are properly applied
8. No External Dependencies
- It sync using only Pi-Hole’s API so you don’t have any additional components required to make the solution work
Cons of Nebula Sync
1. Passwords are stored in clear text
- Pi-hole passwords are passed in environment variables this can definitely be a security concern to note and you want to handle your compose files accordingly
2. Minimal GUI or Error Feedback
- It doesn’t have a web interface, so when you configure it or do any troubleshooting, this will need to be done using the CLI looking at logs
4. Docker-Only deployment
- Itโs built with Docker deployments in mind, so you will need to have a Docker host, no bare-metal hosts
5. Two-Way sync is not possible at this time
- You can only sync one-way to your replicas
Wrapping Up
This is a great new solution and project for the community that allows having multiple Pi-Hole instances up and running for high-availability and failover in case something happens to your primary Pi-Hole server. I really like how it uses the API with v6 and higher to sync pi-hole settings as this streamlines the solution and reduces complexity. Are you already using Nebula Sync to synchronize your Pi-Hole instances? Let me know in the comments.