Skip to content

Nebula-Sync : synchroniser plusieurs Pi-hole v6 gratuitement (le remplaçant de Gravity Sync)

Brandon Visca
Published date:

Spoiler : c’est le successeur non-officiel de Gravity Sync, et il est compatible avec Pi-hole v6.


Table des matières

Open Table des matières

Pourquoi synchroniser plusieurs Pi-hole ?

Tu te dis peut-être : « Pourquoi avoir plusieurs Pi-hole ? » Bonne question.

Haute disponibilité : Si ton unique Pi-hole plante, tous tes appareils se retrouvent sans résolution DNS. Pas cool quand tu veux juste regarder Netflix un dimanche soir.

Redondance géographique : Un Pi-hole dans ton homelab principal, un autre sur un VPS distant ou chez un pote. Si ton internet coupe, le deuxième prend le relais.

Load balancing : Répartir la charge entre plusieurs serveurs DNS, surtout si tu as 50 devices IoT qui spamment des requêtes DNS toute la journée.

Le problème ? Maintenir la même config sur 2, 3, voire 10 Pi-hole, c’est l’enfer. Tu ajoutes une liste noire sur l’un, tu dois la recopier sur les autres. Avec Nebula-Sync, tu configures un seul Pi-hole primaire, et tous les autres répliques se synchronisent automatiquement.

Nebula-Sync vs Gravity Sync : le match

Si tu connais Gravity Sync, tu sais qu’il était LA solution pour synchroniser des Pi-hole. Problème : Gravity Sync n’est plus maintenu activement et n’est pas compatible avec Pi-hole v6.

Nebula-Sync reprend le concept, mais en mieux :

Bref, si tu upgraes vers Pi-hole v6, Nebula-Sync est ton nouveau meilleur ami.

Installation : toutes les options

Nebula-Sync peut tourner en standalone (binaire Go) ou via Docker. Voyons les deux méthodes.

Option 1 : Installation via binaire (sans Docker)

Télécharge la dernière version depuis les releases GitHub :

# Télécharge le binaire
wget https://github.com/lovelaze/nebula-sync/releases/latest/download/nebula-sync-linux-amd64 -O nebula-sync

# Rends-le exécutable
chmod +x nebula-sync

# Déplace-le dans /usr/local/bin pour l'utiliser partout
sudo mv nebula-sync /usr/local/bin/

go install github.com/lovelaze/nebula-sync@latest

Vérifie que ça fonctionne :

nebula-sync --version

services: nebula-sync: image: ghcr.io/lovelaze/nebula-sync:latest container_name: nebula-sync environment: - PRIMARY=http://192.168.1.10|VotreSuperMotDePasse - REPLICAS=http://192.168.1.11|password1,http://192.168.1.12|password2 - FULL_SYNC=true - RUN_GRAVITY=true - CRON=0 * * * * - TZ=Europe/Paris restart: unless-stopped

Explications :

Lance le conteneur :

docker-compose up -d

docker logs -f nebula-sync

Option 3 : Docker run (pour les minimalistes)

Si tu veux juste tester rapidement sans docker-compose :

docker run --rm \
  --name nebula-sync \
  -e PRIMARY="http://192.168.1.10|password" \
  -e REPLICAS="http://192.168.1.11|password" \
  -e FULL_SYNC=true \
  -e RUN_GRAVITY=true \
  ghcr.io/lovelaze/nebula-sync:latest

sudo nano /etc/pihole/pihole.toml

Trouve la section [webserver.api] et modifie :

[webserver.api]
app_sudo = true  # Change de false à true

sudo systemctl restart pihole-FTL

Répète ça sur chaque réplique. Oublie cette étape, et Nebula-Sync va se plaindre d’erreurs d’authentification.

Configuration avancée : sync sélectif

Si tu ne veux pas tout synchroniser (par exemple, tu veux garder des listes DHCP différentes sur chaque Pi-hole), tu peux désactiver FULL_SYNC et choisir précisément ce que tu synchronises.

Exemple de fichier .env pour un sync ultra-personnalisé :

PRIMARY=http://192.168.1.10|password
REPLICAS=http://192.168.1.11|password,http://192.168.1.12|password
FULL_SYNC=false

# Sync uniquement les paramètres DNS
SYNC_CONFIG_DNS=true

# Sync les listes de blocage
SYNC_GRAVITY_AD_LIST=true
SYNC_GRAVITY_AD_LIST_BY_GROUP=true

# Sync les domaines autorisés/bloqués
SYNC_GRAVITY_DOMAIN_LIST=true
SYNC_GRAVITY_DOMAIN_LIST_BY_GROUP=true

# Ne synchronise PAS les clients ni le DHCP
SYNC_GRAVITY_CLIENT=false
SYNC_CONFIG_DHCP=false

RUN_GRAVITY=true
CRON=0 2 * * *  # Sync tous les jours à 2h du mat
TZ=Europe/Paris

[Unit] Description=Nebula Sync - Pi-hole Synchronization After=network.target

[Service] Type=oneshot ExecStart=/usr/local/bin/nebula-sync run —env-file /etc/nebula-sync/.env User=root

[Install] WantedBy=multi-user.target

Créer un timer systemd (pour exécution périodique) :

[Unit]
Description=Nebula Sync Timer
Requires=nebula-sync.service

[Timer]
OnBootSec=5min
OnUnitActiveSec=30min

[Install]
WantedBy=timers.target

systemctl daemon-reload systemctl enable nebula-sync.timer systemctl enable nebula-sync.service systemctl start nebula-sync.timer

Vérifier

systemctl status nebula-sync.timer systemctl list-timers

Méthode 2 : Docker Compose (recommandée)

Avec le docker-compose.yml donné plus haut, lance simplement :

docker-compose up -d

docker ps | grep nebula-sync

Check les logs en temps réel :

docker logs -f nebula-sync

WEBHOOK_SYNC_SUCCESS_URL=https://hc-ping.com/ton-uuid-ici WEBHOOK_SYNC_FAILURE_URL=https://hc-ping.com/ton-uuid-ici/fail

À chaque sync réussi, Healthchecks.io recevra un ping. Si un sync rate, tu recevras une alerte.

Exemple 2 : ntfy.sh (notification push)

WEBHOOK_SYNC_FAILURE_URL=https://ntfy.sh/monpiholebackup
WEBHOOK_SYNC_FAILURE_BODY=Sync Pi-hole a échoué !

WEBHOOK_SYNC_FAILURE_URL=https://ton-serveur.com/api/alert WEBHOOK_SYNC_FAILURE_METHOD=POST WEBHOOK_SYNC_FAILURE_BODY={“service”:“nebula-sync”,“status”:“failed”} WEBHOOK_SYNC_FAILURE_HEADERS=Content-Type:application/json

Bref, tu peux brancher n’importe quel système de monitoring.

Erreurs fréquentes et comment les résoudre

« Failed to initialize service: permission denied »

Cause : Le conteneur Docker (qui tourne sous l’utilisateur 1001 par défaut) n’a pas les droits de lecture sur tes fichiers secrets.

Solution :

sudo chown 1001:1001 /path/to/secrets/*
sudo chmod 400 /path/to/secrets/*

user: “1000:1000” # Ton propre UID

« Authentication error » sur les répliques

Cause : Tu n’as pas activé webserver.api.app_sudo sur tes Pi-hole répliques.

Solution : Retourne dans la section « Configuration de Pi-hole côté serveur » et active cette option.

Le sync ne se déclenche pas automatiquement

Cause : Le cron n’est pas bien configuré.

Solution : Vérifie que la variable CRON est bien définie. Format : minute heure jour mois jour_de_semaine.

Exemples :

Les listes de blocage ne se synchronisent pas

Cause : Si FULL_SYNC=false, tu dois activer manuellement les options de sync.

Solution : Ajoute :

SYNC_GRAVITY_AD_LIST=true
SYNC_GRAVITY_AD_LIST_BY_GROUP=true

services: nebula-sync: image: ghcr.io/lovelaze/nebula-sync:latest container_name: nebula-sync environment: - PRIMARY=http://192.168.1.10|MotDePassePrimaire - REPLICAS=http://192.168.1.11|password1,http://100.64.0.5|password2 - FULL_SYNC=true - RUN_GRAVITY=true - CRON=0 */2 * * * # Sync toutes les 2 heures - TZ=Europe/Paris - WEBHOOK_SYNC_FAILURE_URL=https://ntfy.sh/monpiholebackup restart: unless-stopped

Résultat : je modifie les listes noires sur mon Pi-hole principal, et dans les 2 heures max, tous mes autres Pi-hole sont à jour. Si un sync plante, je reçois une notif push.

Bonnes pratiques

Fais une sauvegarde Teleporter avant : Avant d’activer Nebula-Sync pour la première fois, exporte ta config via Teleporter sur tous tes Pi-hole. Au cas où.

Teste avec FULL_SYNC=true d’abord : Commence avec une synchro complète pour voir si tout fonctionne. Tu optimiseras avec le sync sélectif plus tard.

Surveille les logs les premiers jours :

docker logs -f nebula-sync
Previous
Pourquoi j'ai quitté Google (et comment tu peux faire pareil en 2025)
Next
Docker pour les débutants : 10 services essentiels à auto-héberger en 2025