Outils pour utilisateurs

Outils du site


synchronisation_d_un_serveur_sur_deux_autres

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
synchronisation_d_un_serveur_sur_deux_autres [2025/02/03 23:53] inc002synchronisation_d_un_serveur_sur_deux_autres [2025/02/04 00:02] (Version actuelle) inc002
Ligne 1: Ligne 1:
-= Script de synchronisation PiHole =+=== Script de synchronisation PiHole ====
  
 == Vue d'ensemble == == Vue d'ensemble ==
Ligne 6: Ligne 6:
 == Architecture == == Architecture ==
 === Serveurs === === Serveurs ===
-* '''Source de vérité''' : Mikrotik (192.168.2.1) +  * '''Source de vérité''' : Mikrotik (192.168.2.1) 
-** Stockage : <code>/usb1/etc/pihole/</code> et <code>/usb1/etc/dnsmasq.d/</code> +  ** Stockage : <code>/usb1/etc/pihole/</code> et <code>/usb1/etc/dnsmasq.d/</code> 
-** Utilisateur : piholesync +  ** Utilisateur : piholesync 
-* '''Serveurs cibles''' : Ubuntu (192.168.2.8 et 192.168.2.9) +  * '''Serveurs cibles''' : Ubuntu (192.168.2.8 et 192.168.2.9) 
-** Stockage : <code>/etc/pihole/</code> et <code>/etc/dnsmasq.d/</code> +  ** Stockage : <code>/etc/pihole/</code> et <code>/etc/dnsmasq.d/</code> 
-** Utilisateur : piholesync avec droits sudo+  ** Utilisateur : piholesync avec droits sudo
  
 === Fichiers synchronisés === === Fichiers synchronisés ===
Ligne 124: Ligne 124:
 * Test de recovery complet * Test de recovery complet
  
 +<code "bash">
 +#!/bin/bash
 +# Variables de configuration
 +MIKROTIK_MASTER="piholesync@192.168.2.1"
 +LOCAL_HOST="192.168.2.8"
 +OTHER_UBUNTU="piholesync@192.168.2.9"
 +DRY_RUN=0
 +DEBUG=0
 +
 +# SSH Options
 +SSH_OPTS="-o BatchMode=yes -o StrictHostKeyChecking=no"
 +SUDO_OPTS=" sudo -n -u piholesync "
 +
 +# Chemins sur le Mikrotik (master)
 +MIKROTIK_PIHOLE_PATH="/usb1/etc"
 +MIKROTIK_DNSMASQ_PATH="/usb1/etc-dnsmasq.d"
 +
 +# Chemins de logs et backups
 +LOG_DIR="/var/log/pihole-sync"
 +LOG_FILE="$LOG_DIR/sync.log"
 +BACKUP_DIR="/var/backup/pihole-sync"
 +MAX_LOGS=7
 +
 +# Liste des fichiers à exclure
 +EXCLUDE_LIST=(
 +   "pihole-FTL-old.db"
 +   "gravity_old.db"
 +   "*.log"
 +   "dhcp.leases"
 +   "setupVars.conf.update.bak"
 +   "pihole-FTL.conf"
 +   "install.log"
 +)
 +
 +# Fonction pour construire les options rsync
 +build_rsync_opts() {
 +    local target="$1"  # Paramètre pour identifier la cible
 +    local opts="-avz"
 +
 +    # Ajouter les exclusions
 +    for item in "${EXCLUDE_LIST[@]}"; do
 +        opts+=" --exclude=$item"
 +    done
 +
 +    # Ajouter --dry-run si nécessaire
 +    [ $DRY_RUN -eq 1 ] && opts+=" --dry-run"
 +
 +    # Option spéciale pour Mikrotik
 +    if [[ $target == *"192.168.2.1"* ]]; then
 +        opts+=" --rsh='ssh $SSH_OPTS' --rsync-path=/usr/bin/rsync"
 +    fi
 +
 +    echo "$opts"
 +}
 +
 +# Fonction de debug
 +debug() {
 +   if [ $DEBUG -eq 1 ]; then
 +       echo "DEBUG: $1"
 +   fi
 +}
 +
 +# Fonction de logging
 +log() {
 +   local message="$1"
 +   local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
 +   echo "[$timestamp] $message"
 +   if [ -w "$LOG_DIR" ]; then
 +       echo "[$timestamp] $message" >> "$LOG_FILE"
 +   fi
 +}
 +
 +# Fonction de rotation des logs
 +rotate_logs() {
 +   if [ -f "$LOG_FILE" ]; then
 +       mv "$LOG_FILE" "$LOG_FILE.$(date '+%Y%m%d')"
 +       find "$LOG_DIR" -name "sync.log.*" -mtime +$MAX_LOGS -delete
 +   fi
 +}
 +
 +# Fonction de vérification des droits sudo
 +check_sudo() {
 +    local host="$1"
 +    log "Vérification des droits sudo sur $host..."
 +
 +    if [[ $host == "localhost" ]]; then
 +        # Test local
 +        log "Test des permissions rsync..."
 +        if $SUDO_OPTS rsync --version >/dev/null 2>&1; then
 +            log "✓ Droits sudo OK pour rsync"
 +        else
 +            log "✗ Droits sudo manquants pour rsync"
 +            return 1
 +        fi
 +
 +        log "Test des permissions pihole..."
 +        if $SUDO_OPTS pihole -v >/dev/null 2>&1; then
 +            log "✓ Droits sudo OK pour pihole"
 +        else
 +            log "✗ Droits sudo manquants pour pihole"
 +            return 1
 +        fi
 +    else
 +        # Test distant avec sudo -u piholesync
 +        log "Test des permissions rsync sur $host..."
 +        if sudo -u piholesync ssh $SSH_OPTS "$host" "$SUDO_OPTS rsync --version" >/dev/null 2>&1; then
 +            log "✓ Droits sudo OK pour rsync sur $host"
 +        else
 +            log "✗ Droits sudo manquants pour rsync sur $host"
 +            return 1
 +        fi
 +
 +        log "Test des permissions pihole sur $host..."
 +        if sudo -u piholesync ssh $SSH_OPTS "$host" "$SUDO_OPTS pihole -v" >/dev/null 2>&1; then
 +            log "✓ Droits sudo OK pour pihole sur $host"
 +        else
 +            log "✗ Droits sudo manquants pour pihole sur $host"
 +            return 1
 +        fi
 +    fi
 +
 +    log "✓ Tous les droits sudo sont corrects"
 +    return 0
 +}
 +
 +# Fonction de backup modifiée
 +backup_pihole() {
 +    local host="$1"
 +    local backup_date=$(date '+%Y%m%d_%H%M%S')
 +    local backup_path="$BACKUP_DIR/$host/$backup_date"
 +    local rsync_opts=$(build_rsync_opts "$host")
 +
 +    log "Création d'une sauvegarde pour $host"
 +
 +    # Création des répertoires avec les bonnes permissions
 +    if ! sudo mkdir -p "$backup_path/pihole" "$backup_path/dnsmasq.d"; then
 +        log "Erreur : Impossible de créer les répertoires de backup"
 +        return 1
 +    fi
 +
 +    # Attribution des permissions à piholesync
 +    if ! sudo chown -R piholesync:piholesync "$backup_path"; then
 +        log "Erreur : Impossible de modifier les permissions des répertoires de backup"
 +        return 1
 +    fi
 +
 +    if [[ $host == "localhost" ]]; then
 +        if ! sudo -u piholesync rsync $rsync_opts /etc/pihole/ "$backup_path/pihole/"; then
 +            log "Erreur : Échec de la sauvegarde des fichiers pihole locaux"
 +            return 1
 +        fi
 +        if ! sudo -u piholesync rsync $rsync_opts /etc/dnsmasq.d/ "$backup_path/dnsmasq.d/"; then
 +            log "Erreur : Échec de la sauvegarde des fichiers dnsmasq locaux"
 +            return 1
 +        fi
 +    else
 +        if ! sudo -u piholesync rsync $rsync_opts -e "ssh $SSH_OPTS" "$host:/etc/pihole/" "$backup_path/pihole/"; then
 +            log "Erreur : Échec de la sauvegarde des fichiers pihole distants"
 +            return 1
 +        fi
 +        if ! sudo -u piholesync rsync $rsync_opts -e "ssh $SSH_OPTS" "$host:/etc/dnsmasq.d/" "$backup_path/dnsmasq.d/"; then
 +            log "Erreur : Échec de la sauvegarde des fichiers dnsmasq distants"
 +            return 1
 +        fi
 +    fi
 +
 +    log "Sauvegarde terminée pour $host dans $backup_path"
 +    return 0
 +}
 +# Fonction pour vérifier l'existence d'un fichier distant via SSH
 +# Fonction pour vérifier l'existence d'un fichier distant via SSH
 +check_remote_file() {
 +    local host="$1"
 +    local file="$2"
 +    local description="$3"
 +
 +    log "Vérification de $description sur $host..."
 +    if [[ $host == *"192.168.2.1"* ]]; then
 +        # Cas spécial pour Mikrotik
 +        local mikrotik_path=${file#/}
 +        local cmd="/file print where name=\"$mikrotik_path\""
 +
 +        debug "Chemin original: $file"
 +        debug "Chemin Mikrotik: $mikrotik_path"
 +        debug "Commande exécutée: $cmd"
 +
 +        local output=$(sudo -u piholesync ssh $SSH_OPTS "$host" "$cmd")
 +        debug "Sortie de la commande:"
 +        debug "$output"
 +
 +        if echo "$output" | grep -q "$mikrotik_path"; then
 +            log "✓ $description trouvé"
 +            return 0
 +        else
 +            log "✗ $description non trouvé ($mikrotik_path)"
 +            return 1
 +        fi
 +    else
 +        # Cas standard pour les serveurs Ubuntu
 +        if sudo -u piholesync ssh $SSH_OPTS "$host" "$SUDO_OPTS [ -f $file ]"; then
 +            log "✓ $description trouvé"
 +            return 0
 +        else
 +            log "✗ $description non trouvé à $file"
 +            return 1
 +        fi
 +    fi
 +}
 +
 +# Fonction pour copier depuis le Mikrotik
 +# Fonction pour copier depuis le Mikrotik
 +copy_from_mikrotik() {
 +    local source="$1"
 +    local dest="$2"
 +    local description="$3"
 +
 +    log "Copie de $description depuis Mikrotik..."
 +    if [ $DRY_RUN -eq 1 ]; then
 +        log "[DRY RUN] Copie de $source vers $dest"
 +        return 0
 +    fi
 +
 +    # Création d'un répertoire temporaire
 +    local temp_dir=$(mktemp -d)
 +    chown piholesync "$temp_dir"  # Ajout de cette ligne !
 +
 +    local temp_file="$temp_dir/$(basename "$dest")"
 +
 +    debug "Tentative de copie avec SFTP..."
 +
 +    # Exécution de la commande SFTP
 +    if ! sudo -u piholesync sftp "$MIKROTIK_MASTER" <<< "get $source $temp_file"; then
 +        log "✗ Erreur lors de la copie de $description via SFTP"
 +        rm -rf "$temp_dir"
 +        return 1
 +    fi
 +
 +    # Vérification de la taille du fichier
 +    local file_size=$(stat -c%s "$temp_file" 2>/dev/null || stat -f%z "$temp_file")
 +    debug "Taille du fichier temporaire: $file_size octets"
 +
 +    # Vérification SQLite pour gravity.db
 +    if [[ "$source" == *"gravity.db"* ]]; then
 +        if ! sqlite3 "$temp_file" "SELECT name FROM sqlite_master LIMIT 1" > /dev/null 2>&1; then
 +            log "✗ Le fichier temporaire $description n'est pas une base SQLite valide"
 +            rm -rf "$temp_dir"
 +            return 1
 +        fi
 +        debug "Vérification SQLite réussie"
 +    fi
 +
 +    # Déplacement du fichier vers sa destination finale
 +    if ! mv "$temp_file" "$dest"; then
 +        log "✗ Erreur lors du déplacement de $description vers sa destination finale"
 +        rm -rf "$temp_dir"
 +        return 1
 +    fi
 +
 +    # Nettoyage
 +    rm -rf "$temp_dir"
 +
 +    # Vérification finale
 +    if [ ! -s "$dest" ]; then
 +        log "✗ Le fichier $description est vide après copie"
 +        return 1
 +    fi
 +
 +    log "✓ Copie de $description réussie (taille: $file_size octets)"
 +    return 0
 +}
 +
 +
 +
 +# Fonction pour vérifier la taille d'un fichier sur le Mikrotik
 +check_mikrotik_file_size() {
 +    local file="$1"
 +    local min_size="$2"
 +
 +    log "Vérification de la taille de $file..."
 +
 +    # Obtenir les informations du fichier via ssh
 +    local file_info=$(sudo -u piholesync ssh $SSH_OPTS "$MIKROTIK_MASTER" "du -b \"$file\" 2>/dev/null || echo '0'")
 +
 +    # Extraire la taille (premier champ de la sortie du)
 +    local size=$(echo "$file_info" | awk '{print $1}')
 +
 +    if [ -z "$size" ] || [ "$size" -lt "$min_size" ]; then
 +        log "✗ Le fichier $file sur le Mikrotik est trop petit ou inexistant (${size:-0} octets < ${min_size} octets attendus)"
 +        return 1
 +    fi
 +
 +    log "✓ Taille du fichier $file sur le Mikrotik: ${size} octets"
 +    return 0
 +}
 +
 +# Fonction pour arrêter/démarrer/reconstruire Pi-hole
 +manage_pihole_service() {
 +    local host="$1"
 +    local action="$2"
 +    local description="$3"
 +
 +    log "$description sur $host..."
 +    if [[ $host == "localhost" ]]; then
 +        case $action in
 +            "stop")
 +                sudo pihole -f stop
 +                ;;
 +            "start")
 +                sudo pihole -f start
 +                ;;
 +            "rebuild")
 +                sudo pihole -g
 +                ;;
 +        esac
 +    else
 +        case $action in
 +            "stop")
 +                sudo -u piholesync ssh -t "$host" "$SUDO_OPTS pihole -f stop"
 +                ;;
 +            "start")
 +                sudo -u piholesync ssh -t "$host" "$SUDO_OPTS pihole -f start"
 +                ;;
 +            "rebuild")
 +                sudo -u piholesync ssh -t "$host" "$SUDO_OPTS pihole -g"
 +                ;;
 +        esac
 +    fi
 +}
 +
 +sync_to_ubuntu() {
 +    local src="$1"
 +    local dest="$2"
 +    local host="$3"
 +    local description="$4"
 +
 +    log "Synchronisation de $description vers $host..."
 +    if [ $DRY_RUN -eq 1 ]; then
 +        log "[DRY RUN] Synchronisation vers $host"
 +        return 0
 +    fi
 +
 +    if [[ $host == "localhost" ]]; then
 +        # Vérification et création du répertoire
 +        if [ ! -d "$dest" ]; then
 +            sudo mkdir -p "$dest"
 +        fi
 +
 +        # Exécution de rsync en sudo pour éviter les problèmes de permissions
 +        sudo rsync -avz --no-perms --no-owner --no-times "$src" "$dest" || true
 +
 +        # Correction des permissions pour gravity.db
 +        if [[ -f "$dest/gravity.db" && "$EUID" -eq 0 ]]; then
 +            sudo chown pihole:pihole "$dest/gravity.db"
 +            sudo chmod 664 "$dest/gravity.db"
 +        fi
 +    else
 +        # Synchronisation distante avec rsync
 +        sudo -u piholesync rsync -avz --no-perms --no-owner --no-times "$src" "$host:$dest/" || true
 +
 +        # Correction des permissions sur le serveur distant
 +        if [[ "$dest" == *"pihole"* ]]; then
 +            if [[ -n "$SUDO_OPTS" ]]; then
 +                sudo -u piholesync ssh $SSH_OPTS "$host" "$SUDO_OPTS chown pihole:pihole $dest/gravity.db"
 +                sudo -u piholesync ssh $SSH_OPTS "$host" "$SUDO_OPTS chmod 664 $dest/gravity.db"
 +            else
 +                log "⚠️ Impossible de changer les permissions sur $host, SUDO_OPTS est vide."
 +            fi
 +        fi
 +    fi
 +}
 +
 +
 +sync_dnsmasq_cname() {
 +    local cname_file="05-pihole-custom-cname.conf"
 +    local src_path="usb1/etc/dnsmasq.d/$cname_file"  # Correction du chemin ici
 +
 +    log "Vérification du fichier CNAME ($cname_file)..."
 +
 +    # Vérifie si le fichier existe sur le Mikrotik en utilisant /file get
 +    local check_output
 +    check_output=$(sudo -u piholesync ssh $SSH_OPTS "$MIKROTIK_MASTER" ":put [/file/get \"$src_path\" contents]" 2>/dev/null)
 +    debug "Résultat de la vérification: '$check_output'"
 +
 +    if [ -n "$check_output" ] && [[ ! "$check_output" =~ "no such item" ]]; then
 +        log "✓ Fichier CNAME trouvé sur le Mikrotik, synchronisation..."
 +
 +        if [ $DRY_RUN -eq 0 ]; then
 +            # Crée le répertoire temporaire s'il n'existe pas
 +            mkdir -p "$TEMP_DIR/dnsmasq.d"
 +
 +            # Écrit le contenu directement dans le fichier temporaire
 +            echo "$check_output" > "$TEMP_DIR/dnsmasq.d/$cname_file"
 +
 +            # Synchronise vers les deux serveurs Ubuntu
 +            sync_to_ubuntu "$TEMP_DIR/dnsmasq.d/$cname_file" "/etc/dnsmasq.d/" "localhost" "fichier CNAME local"
 +            sync_to_ubuntu "$TEMP_DIR/dnsmasq.d/$cname_file" "/etc/dnsmasq.d/" "$OTHER_UBUNTU" "fichier CNAME distant"
 +        else
 +            log "[DRY RUN] Le fichier CNAME serait synchronisé"
 +        fi
 +    else
 +        log "! Fichier CNAME non trouvé sur le Mikrotik, suppression sur les serveurs Ubuntu..."
 +
 +        if [ $DRY_RUN -eq 0 ]; then
 +            # Supprime le fichier sur les deux serveurs Ubuntu s'il existe
 +            sudo rm -f "/etc/dnsmasq.d/$cname_file"
 +            sudo -u piholesync ssh $SSH_OPTS "$OTHER_UBUNTU" "$SUDO_OPTS rm -f /etc/dnsmasq.d/$cname_file"
 +        else
 +            log "[DRY RUN] Le fichier CNAME serait supprimé des serveurs Ubuntu"
 +        fi
 +    fi
 +}
 +
 +# Fonction de rotation des logs
 +rotate_logs() {
 +   if [ -f "$LOG_FILE" ]; then
 +       mv "$LOG_FILE" "$LOG_FILE.$(date '+%Y%m%d')"
 +       find "$LOG_DIR" -name "sync.log.*" -mtime +$MAX_LOGS -delete
 +   fi
 +}
 +
 +# Fonction pour effectuer les backups
 +perform_backups() {
 +   if [ $DRY_RUN -eq 0 ]; then
 +       log "Démarrage des sauvegardes..."
 +       backup_pihole "localhost"
 +       backup_pihole "$OTHER_UBUNTU"
 +   else
 +       log "[DRY RUN] Les sauvegardes seraient effectuées ici"
 +   fi
 +}
 +
 +# Traitement des arguments
 +while [[ $# -gt 0 ]]; do
 +   case $1 in
 +       --dry-run)
 +           DRY_RUN=1
 +           shift
 +           ;;
 +       --debug)
 +           DEBUG=1
 +           shift
 +           ;;
 +       --help)
 +           echo "Usage: $0 [--dry-run] [--debug]"
 +           echo "Options:"
 +           echo "  --dry-run    Simuler la synchronisation sans l'exécuter"
 +           echo "  --debug      Afficher les messages de debug"
 +           exit 0
 +           ;;
 +       *)
 +           echo "Option invalide: $1"
 +           echo "Utilisez --help pour voir les options disponibles"
 +           exit 1
 +           ;;
 +   esac
 +done
 +
 +log "Mode: $([ $DRY_RUN -eq 1 ] && echo 'DRY RUN' || echo 'PRODUCTION')$([ $DEBUG -eq 1 ] && echo ' (DEBUG activé)')"
 +
 +# Rotation des logs au démarrage
 +rotate_logs
 +
 +# Vérification des prérequis
 +log "Vérification des prérequis..."
 +check_remote_file "$MIKROTIK_MASTER" "$MIKROTIK_PIHOLE_PATH/pihole/gravity.db" "gravity.db" || exit 1
 +check_remote_file "$MIKROTIK_MASTER" "$MIKROTIK_PIHOLE_PATH/pihole/custom.list" "custom.list" || exit 1
 +check_remote_file "$MIKROTIK_MASTER" "$MIKROTIK_PIHOLE_PATH/pihole/local.list" "local.list" || exit 1
 +
 +# Vérification des droits sudo
 +log "Vérification des droits sudo..."
 +check_sudo "localhost" || exit 1
 +check_sudo "$OTHER_UBUNTU" || exit 1
 +
 +# Effectuer les backups avant synchronisation
 +perform_backups
 +
 +# Création du dossier temporaire
 +TEMP_DIR="/tmp/pihole-sync"
 +mkdir -p "$TEMP_DIR/pihole"
 +mkdir -p "$TEMP_DIR/dnsmasq.d"
 +
 +# Synchronisation depuis le Mikrotik
 +log "Synchronisation depuis $MIKROTIK_MASTER..."
 +
 +# Copie des fichiers depuis le Mikrotik
 +mkdir -p "$TEMP_DIR/pihole" "$TEMP_DIR/dnsmasq.d"
 +
 +copy_from_mikrotik "usb1/etc/pihole/gravity.db" "$TEMP_DIR/pihole/gravity.db" "gravity.db" || exit 1
 +copy_from_mikrotik "usb1/etc/pihole/custom.list" "$TEMP_DIR/pihole/custom.list" "custom.list" || exit 1
 +copy_from_mikrotik "usb1/etc/pihole/local.list" "$TEMP_DIR/pihole/local.list" "local.list" || exit 1
 +
 +# Pour le dossier dnsmasq.d
 +log "Gestion du fichier CNAME..."
 +if [ $DRY_RUN -eq 1 ]; then
 +    log "[DRY RUN] Vérification et synchronisation du fichier CNAME"
 +else
 +    sync_dnsmasq_cname || exit 1
 +fi
 +
 +# Dans la partie synchronisation :
 +if [ $DRY_RUN -eq 0 ]; then
 +    # Arrêt des services sur les deux serveurs
 +    manage_pihole_service "localhost" "stop" "Arrêt du service Pi-hole"
 +    manage_pihole_service "$OTHER_UBUNTU" "stop" "Arrêt du service Pi-hole distant"
 +
 +    log "Synchronisation vers les serveurs Ubuntu..."
 +
 +    # Synchronisation locale
 +    sync_to_ubuntu "$TEMP_DIR/pihole/" "/etc/pihole/" "localhost" "fichiers pihole locaux" || exit 1
 +    sync_to_ubuntu "$TEMP_DIR/dnsmasq.d/" "/etc/dnsmasq.d/" "localhost" "dossier dnsmasq.d local" || exit 1
 +
 +    # Synchronisation vers le serveur distant
 +    sync_to_ubuntu "$TEMP_DIR/pihole/" "/etc/pihole" "$OTHER_UBUNTU" "fichiers pihole vers $OTHER_UBUNTU" || exit 1
 +    sync_to_ubuntu "$TEMP_DIR/dnsmasq.d/" "/etc/dnsmasq.d" "$OTHER_UBUNTU" "dossier dnsmasq.d vers $OTHER_UBUNTU" || exit 1
 +
 +    # Reconstruction de la base gravity sur les deux serveurs
 +    manage_pihole_service "localhost" "rebuild" "Reconstruction de la base gravity"
 +    manage_pihole_service "$OTHER_UBUNTU" "rebuild" "Reconstruction de la base gravity distante"
 +
 +    # Démarrage des services
 +    manage_pihole_service "localhost" "start" "Démarrage du service Pi-hole"
 +    manage_pihole_service "$OTHER_UBUNTU" "start" "Démarrage du service Pi-hole distant"
 +fi
 +
 +
 +# Nettoyage
 +rm -rf "$TEMP_DIR"
 +log "Script terminé avec succès!"
 +</code>
 [[Category:Documentation]] [[Category:Documentation]]
 [[Category:PiHole]] [[Category:PiHole]]
 [[Category:Scripts]] [[Category:Scripts]]
synchronisation_d_un_serveur_sur_deux_autres.1738626798.txt.gz · Dernière modification : de inc002