From ffdbddf5e399281ca61ab7097ce7800a12203261 Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 14 Aug 2025 04:25:45 +0000 Subject: [PATCH] Ajouter backups_traefik.sh --- backups_traefik.sh | 561 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 561 insertions(+) create mode 100644 backups_traefik.sh diff --git a/backups_traefik.sh b/backups_traefik.sh new file mode 100644 index 0000000..dea96d8 --- /dev/null +++ b/backups_traefik.sh @@ -0,0 +1,561 @@ +#!/bin/bash +# Script de sauvegarde Traefik vers partage Samba via rsync +# Auteur: Script généré par Claude +# Date: $(date +%Y-%m-%d) + +set -euo pipefail + +# ============================================================================= +# CONFIGURATION +# ============================================================================= + +# Configuration Traefik +TRAEFIK_CONFIG_DIR="/etc/traefik" +TRAEFIK_DATA_DIR="/var/lib/traefik" +TRAEFIK_DYNAMIC_CONFIG_DIR="/etc/traefik/dynamic" +TRAEFIK_ACME_DIR="/var/lib/traefik/acme" +TRAEFIK_LOGS_DIR="/var/log/traefik" +TRAEFIK_SERVICE="traefik" +TRAEFIK_USER="traefik" + +# Chemins alternatifs pour installation Docker +DOCKER_TRAEFIK_VOLUME="traefik-data" +DOCKER_COMPOSE_DIR="/opt/traefik" +DOCKER_TRAEFIK_CONFIG="/opt/traefik/config" + +# Configuration du partage Samba +SAMBA_SERVER="192.168.77.230" +SAMBA_SHARE="/srv/samba/partage/Backups" +SAMBA_USER="root" # À adapter selon votre configuration + +# Configuration SSH +SSH_KEY_PATH="$HOME/.ssh/traefik_backup_ed25519" +SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR" + +# Configuration de sauvegarde +BACKUP_BASE_DIR="/tmp/traefik_backup_$(date +%Y%m%d_%H%M%S)" +REMOTE_BACKUP_DIR="traefik_backups" +LOG_FILE="/var/log/traefik_backup.log" +RETENTION_DAYS=30 + +# Options de sauvegarde +BACKUP_CONFIG=true # Sauvegarder la configuration +BACKUP_CERTIFICATES=true # Sauvegarder les certificats SSL/TLS +BACKUP_LOGS=true # Sauvegarder les logs (optionnel) +BACKUP_DYNAMIC_CONFIG=true # Sauvegarder la configuration dynamique +COMPRESS_LOGS=true # Compresser les logs pour économiser l'espace + +# ============================================================================= +# FONCTIONS UTILITAIRES +# ============================================================================= + +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +error_exit() { + log "ERREUR: $1" + exit 1 +} + +check_root() { + if [[ $EUID -ne 0 ]]; then + error_exit "Ce script doit être exécuté en tant que root" + fi +} + +check_command() { + if ! command -v "$1" &> /dev/null; then + return 1 + fi + return 0 +} + +# ============================================================================= +# INSTALLATION DES DÉPENDANCES +# ============================================================================= + +install_dependencies() { + log "Vérification et installation des dépendances..." + + # Détecter la distribution + if [[ -f /etc/debian_version ]]; then + DISTRO="debian" + PKG_MANAGER="apt-get" + PACKAGES="rsync samba-client cifs-utils openssh-client docker.io docker-compose jq gzip tar" + elif [[ -f /etc/redhat-release ]]; then + DISTRO="redhat" + PKG_MANAGER="yum" + PACKAGES="rsync cifs-utils openssh-clients docker docker-compose jq gzip tar" + else + error_exit "Distribution non supportée" + fi + + log "Distribution détectée: $DISTRO" + + # Mise à jour du cache des paquets + if [[ "$DISTRO" == "debian" ]]; then + apt-get update -qq + fi + + # Installation des paquets manquants + for package in $PACKAGES; do + if [[ "$DISTRO" == "debian" ]]; then + if ! dpkg -l | grep -q "^ii $package "; then + log "Installation de $package..." + apt-get install -y -qq "$package" || log "Impossible d'installer $package (peut-être optionnel)" + else + log "$package est déjà installé" + fi + elif [[ "$DISTRO" == "redhat" ]]; then + if ! rpm -q "$package" >/dev/null 2>&1; then + log "Installation de $package..." + yum install -y "$package" || log "Impossible d'installer $package (peut-être optionnel)" + else + log "$package est déjà installé" + fi + fi + done +} + +# ============================================================================= +# GESTION DES CERTIFICATS SSH +# ============================================================================= + +setup_ssh_key() { + log "Configuration de la clé SSH ED25519..." + + if [[ ! -f "$SSH_KEY_PATH" ]]; then + log "Création de la clé SSH ED25519..." + ssh-keygen -t ed25519 -f "$SSH_KEY_PATH" -N "" -C "traefik-backup-$(hostname)" + chmod 600 "$SSH_KEY_PATH" + chmod 644 "${SSH_KEY_PATH}.pub" + + log "Clé SSH créée: $SSH_KEY_PATH" + log "Clé publique: ${SSH_KEY_PATH}.pub" + echo + log "IMPORTANT: Vous devez copier cette clé publique sur le serveur distant:" + log "==========================================" + cat "${SSH_KEY_PATH}.pub" + log "==========================================" + echo + log "Commande pour copier la clé sur le serveur distant:" + log "ssh-copy-id -i $SSH_KEY_PATH ${SAMBA_USER}@${SAMBA_SERVER}" + echo + read -p "Appuyez sur Entrée une fois la clé configurée sur le serveur distant..." + else + log "Clé SSH existante trouvée: $SSH_KEY_PATH" + fi +} + +test_ssh_connection() { + log "Test de la connexion SSH..." + if ssh -i "$SSH_KEY_PATH" $SSH_OPTIONS "${SAMBA_USER}@${SAMBA_SERVER}" "echo 'Connexion SSH réussie'" 2>/dev/null; then + log "Connexion SSH: OK" + else + error_exit "Impossible de se connecter via SSH. Vérifiez la configuration de la clé." + fi +} + +# ============================================================================= +# DÉTECTION DE L'ENVIRONNEMENT +# ============================================================================= + +detect_environment() { + log "Détection de l'environnement Traefik..." + + # Détection de Traefik + TRAEFIK_INSTALL_TYPE="none" + if systemctl is-enabled "$TRAEFIK_SERVICE" >/dev/null 2>&1; then + TRAEFIK_INSTALL_TYPE="systemd" + log "Traefik détecté: installation systemd" + elif check_command traefik; then + TRAEFIK_INSTALL_TYPE="binary" + log "Traefik détecté: installation binaire" + elif docker ps --format "table {{.Names}}" | grep -q traefik; then + TRAEFIK_INSTALL_TYPE="docker" + log "Traefik détecté: conteneur Docker" + elif [[ -d "$DOCKER_COMPOSE_DIR" && -f "$DOCKER_COMPOSE_DIR/docker-compose.yml" ]]; then + TRAEFIK_INSTALL_TYPE="docker-compose" + log "Traefik détecté: Docker Compose" + else + log "ATTENTION: Traefik non détecté" + fi + + # Adaptation des chemins selon l'environnement + if [[ "$TRAEFIK_INSTALL_TYPE" == "docker" ]]; then + TRAEFIK_DATA_DIR="/var/lib/docker/volumes/${DOCKER_TRAEFIK_VOLUME}/_data" + TRAEFIK_CONFIG_DIR="$DOCKER_TRAEFIK_CONFIG" + TRAEFIK_ACME_DIR="$TRAEFIK_DATA_DIR" + fi + + # Vérification des répertoires existants + if [[ ! -d "$TRAEFIK_CONFIG_DIR" ]]; then + log "ATTENTION: Répertoire de configuration non trouvé: $TRAEFIK_CONFIG_DIR" + fi +} + +# ============================================================================= +# GESTION DES SERVICES +# ============================================================================= + +stop_services() { + log "Arrêt des services..." + + TRAEFIK_WAS_RUNNING=false + + # Arrêt de Traefik + case "$TRAEFIK_INSTALL_TYPE" in + "systemd") + if systemctl is-active --quiet "$TRAEFIK_SERVICE"; then + systemctl stop "$TRAEFIK_SERVICE" + TRAEFIK_WAS_RUNNING=true + log "Service Traefik arrêté" + fi + ;; + "docker") + if docker ps -q -f name=traefik | grep -q .; then + docker stop traefik >/dev/null 2>&1 + TRAEFIK_WAS_RUNNING=true + log "Conteneur Traefik arrêté" + fi + ;; + "docker-compose") + if [[ -f "$DOCKER_COMPOSE_DIR/docker-compose.yml" ]]; then + cd "$DOCKER_COMPOSE_DIR" + docker-compose stop >/dev/null 2>&1 + TRAEFIK_WAS_RUNNING=true + log "Services Docker Compose arrêtés" + fi + ;; + esac + + # Attendre un peu pour que les fichiers soient libérés + sleep 2 +} + +start_services() { + log "Redémarrage des services..." + + # Redémarrage de Traefik + if [[ "$TRAEFIK_WAS_RUNNING" == "true" ]]; then + case "$TRAEFIK_INSTALL_TYPE" in + "systemd") + systemctl start "$TRAEFIK_SERVICE" + log "Service Traefik redémarré" + ;; + "docker") + docker start traefik >/dev/null 2>&1 + log "Conteneur Traefik redémarré" + ;; + "docker-compose") + if [[ -f "$DOCKER_COMPOSE_DIR/docker-compose.yml" ]]; then + cd "$DOCKER_COMPOSE_DIR" + docker-compose start >/dev/null 2>&1 + log "Services Docker Compose redémarrés" + fi + ;; + esac + fi +} + +# ============================================================================= +# FONCTIONS DE SAUVEGARDE +# ============================================================================= + +create_backup_structure() { + log "Création de la structure de sauvegarde: $BACKUP_BASE_DIR" + mkdir -p "$BACKUP_BASE_DIR"/{config,data,certificates,logs,metadata} +} + +backup_traefik_config() { + log "Sauvegarde de la configuration Traefik..." + + # Sauvegarde de la configuration principale + if [[ -d "$TRAEFIK_CONFIG_DIR" && "$BACKUP_CONFIG" == "true" ]]; then + log "Sauvegarde de la configuration principale..." + rsync -av --progress "$TRAEFIK_CONFIG_DIR/" "$BACKUP_BASE_DIR/config/" \ + --exclude="*.log" --exclude="*.pid" + fi + + # Sauvegarde de la configuration dynamique + if [[ -d "$TRAEFIK_DYNAMIC_CONFIG_DIR" && "$BACKUP_DYNAMIC_CONFIG" == "true" ]]; then + log "Sauvegarde de la configuration dynamique..." + rsync -av --progress "$TRAEFIK_DYNAMIC_CONFIG_DIR/" "$BACKUP_BASE_DIR/config/dynamic/" + fi + + # Sauvegarde des fichiers Docker Compose si applicable + if [[ "$TRAEFIK_INSTALL_TYPE" == "docker-compose" && -d "$DOCKER_COMPOSE_DIR" ]]; then + log "Sauvegarde de la configuration Docker Compose..." + rsync -av --progress "$DOCKER_COMPOSE_DIR/" "$BACKUP_BASE_DIR/config/docker-compose/" \ + --include="*.yml" --include="*.yaml" --include="*.env" --include="*.toml" --exclude="*" + fi +} + +backup_traefik_data() { + log "Sauvegarde des données Traefik..." + + # Sauvegarde du répertoire de données + if [[ -d "$TRAEFIK_DATA_DIR" ]]; then + log "Sauvegarde des données Traefik..." + rsync -av --progress "$TRAEFIK_DATA_DIR/" "$BACKUP_BASE_DIR/data/" \ + --exclude="*.log" --exclude="*.pid" --exclude="access.log" + fi +} + +backup_certificates() { + log "Sauvegarde des certificats..." + + if [[ "$BACKUP_CERTIFICATES" == "true" ]]; then + # Sauvegarde des certificats ACME/Let's Encrypt + if [[ -d "$TRAEFIK_ACME_DIR" ]]; then + log "Sauvegarde des certificats ACME..." + find "$TRAEFIK_ACME_DIR" -name "*.json" -o -name "acme.json" -o -name "*.crt" -o -name "*.key" | \ + while read -r cert_file; do + if [[ -f "$cert_file" ]]; then + rel_path="${cert_file#$TRAEFIK_ACME_DIR/}" + mkdir -p "$BACKUP_BASE_DIR/certificates/$(dirname "$rel_path")" + cp "$cert_file" "$BACKUP_BASE_DIR/certificates/$rel_path" + log "Certificat sauvegardé: $rel_path" + fi + done + fi + + # Recherche de certificats dans d'autres emplacements courants + for cert_dir in "/etc/ssl/traefik" "/opt/traefik/certs" "/var/lib/traefik/certificates"; do + if [[ -d "$cert_dir" ]]; then + log "Sauvegarde des certificats depuis: $cert_dir" + rsync -av --progress "$cert_dir/" "$BACKUP_BASE_DIR/certificates/additional/" \ + --include="*.crt" --include="*.key" --include="*.pem" --include="*.json" --exclude="*" + fi + done + fi +} + +backup_logs() { + log "Sauvegarde des logs..." + + if [[ "$BACKUP_LOGS" == "true" && -d "$TRAEFIK_LOGS_DIR" ]]; then + log "Sauvegarde des logs Traefik..." + + if [[ "$COMPRESS_LOGS" == "true" ]]; then + log "Compression des logs en cours..." + tar -czf "$BACKUP_BASE_DIR/logs/traefik_logs.tar.gz" -C "$(dirname "$TRAEFIK_LOGS_DIR")" "$(basename "$TRAEFIK_LOGS_DIR")" + else + rsync -av --progress "$TRAEFIK_LOGS_DIR/" "$BACKUP_BASE_DIR/logs/" \ + --include="*.log" --exclude="*.pid" + fi + fi + + # Sauvegarde des logs systemd si applicable + if [[ "$TRAEFIK_INSTALL_TYPE" == "systemd" ]]; then + log "Export des logs systemd..." + journalctl -u "$TRAEFIK_SERVICE" --since "7 days ago" > "$BACKUP_BASE_DIR/logs/systemd.log" 2>/dev/null || true + fi +} + +create_metadata() { + log "Création des métadonnées de sauvegarde..." + + # Informations système + cat > "$BACKUP_BASE_DIR/metadata/system_info.txt" << EOF +Sauvegarde Traefik +================== +Date: $(date) +Serveur: $(hostname) +Version script: 1.0 +Utilisateur: $(whoami) + +Environnement détecté: +- Type d'installation: $TRAEFIK_INSTALL_TYPE +- Répertoire de configuration: $TRAEFIK_CONFIG_DIR +- Répertoire de données: $TRAEFIK_DATA_DIR +- Répertoire ACME: $TRAEFIK_ACME_DIR +- Répertoire des logs: $TRAEFIK_LOGS_DIR + +Options de sauvegarde: +- Configuration: $BACKUP_CONFIG +- Configuration dynamique: $BACKUP_DYNAMIC_CONFIG +- Certificats: $BACKUP_CERTIFICATES +- Logs: $BACKUP_LOGS +- Compression des logs: $COMPRESS_LOGS +EOF + + # Version de Traefik si accessible + if check_command traefik; then + log "Récupération de la version Traefik..." + traefik version > "$BACKUP_BASE_DIR/metadata/traefik_version.txt" 2>/dev/null || \ + echo "Version Traefik non disponible" > "$BACKUP_BASE_DIR/metadata/traefik_version.txt" + fi + + # Informations sur les conteneurs Docker si applicable + if check_command docker; then + log "Sauvegarde des informations Docker..." + docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" > "$BACKUP_BASE_DIR/metadata/docker_containers.txt" 2>/dev/null || true + docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep -i traefik > "$BACKUP_BASE_DIR/metadata/docker_images.txt" 2>/dev/null || true + fi + + # Liste des certificats sauvegardés + if [[ -d "$BACKUP_BASE_DIR/certificates" ]]; then + find "$BACKUP_BASE_DIR/certificates" -type f -name "*.json" -o -name "*.crt" -o -name "*.key" -o -name "*.pem" | \ + sed "s|$BACKUP_BASE_DIR/certificates/||" > "$BACKUP_BASE_DIR/metadata/certificates_list.txt" + fi + + # Taille de la sauvegarde + BACKUP_SIZE=$(du -sh "$BACKUP_BASE_DIR" | cut -f1) + echo "Taille totale de la sauvegarde: $BACKUP_SIZE" >> "$BACKUP_BASE_DIR/metadata/system_info.txt" + + log "Sauvegarde locale créée dans: $BACKUP_BASE_DIR (Taille: $BACKUP_SIZE)" +} + +sync_to_remote() { + log "Synchronisation vers le serveur distant..." + + # Création du répertoire distant si nécessaire + ssh -i "$SSH_KEY_PATH" $SSH_OPTIONS "${SAMBA_USER}@${SAMBA_SERVER}" \ + "mkdir -p ${SAMBA_SHARE}/${REMOTE_BACKUP_DIR}/$(date +%Y/%m)" + + # Synchronisation des fichiers + REMOTE_PATH="${SAMBA_USER}@${SAMBA_SERVER}:${SAMBA_SHARE}/${REMOTE_BACKUP_DIR}/$(date +%Y/%m)/traefik_backup_$(date +%Y%m%d_%H%M%S)/" + + log "Envoi vers: $REMOTE_PATH" + rsync -avz --progress --delete \ + -e "ssh -i $SSH_KEY_PATH $SSH_OPTIONS" \ + "$BACKUP_BASE_DIR/" \ + "$REMOTE_PATH" + + log "Synchronisation terminée" +} + +cleanup_local() { + log "Nettoyage des fichiers temporaires..." + if [[ -d "$BACKUP_BASE_DIR" ]]; then + rm -rf "$BACKUP_BASE_DIR" + log "Répertoire temporaire supprimé: $BACKUP_BASE_DIR" + fi +} + +cleanup_remote() { + log "Nettoyage des anciennes sauvegardes (plus de $RETENTION_DAYS jours)..." + + ssh -i "$SSH_KEY_PATH" $SSH_OPTIONS "${SAMBA_USER}@${SAMBA_SERVER}" \ + "find ${SAMBA_SHARE}/${REMOTE_BACKUP_DIR} -type d -name 'traefik_backup_*' -mtime +${RETENTION_DAYS} -exec rm -rf {} + 2>/dev/null || true" + + log "Nettoyage des anciennes sauvegardes terminé" +} + +# ============================================================================= +# FONCTION PRINCIPALE +# ============================================================================= + +main() { + log "=== DÉBUT DE LA SAUVEGARDE TRAEFIK ===" + + # Vérifications préliminaires + check_root + + # Installation des dépendances + install_dependencies + + # Configuration SSH + setup_ssh_key + test_ssh_connection + + # Détection de l'environnement + detect_environment + + # Variables pour suivre l'état des services + TRAEFIK_WAS_RUNNING=false + + # Gestion des erreurs avec nettoyage + trap 'cleanup_local; start_services' EXIT ERR + + # Arrêt des services pour une sauvegarde cohérente + stop_services + + # Création de la structure de sauvegarde + create_backup_structure + + # Sauvegarde de la configuration + backup_traefik_config + + # Sauvegarde des données + backup_traefik_data + + # Sauvegarde des certificats + backup_certificates + + # Sauvegarde des logs + backup_logs + + # Création des métadonnées + create_metadata + + # Redémarrage des services dès que possible + start_services + + # Synchronisation vers le serveur distant + sync_to_remote + + # Nettoyage + cleanup_remote + cleanup_local + + log "=== SAUVEGARDE TRAEFIK TERMINÉE AVEC SUCCÈS ===" +} + +# ============================================================================= +# POINT D'ENTRÉE +# ============================================================================= + +# Vérification des arguments pour les options avancées +while [[ $# -gt 0 ]]; do + case $1 in + --no-config) + BACKUP_CONFIG=false + log "Option: Sauvegarde de la configuration désactivée" + shift + ;; + --no-certificates) + BACKUP_CERTIFICATES=false + log "Option: Sauvegarde des certificats désactivée" + shift + ;; + --no-logs) + BACKUP_LOGS=false + log "Option: Sauvegarde des logs désactivée" + shift + ;; + --no-dynamic-config) + BACKUP_DYNAMIC_CONFIG=false + log "Option: Sauvegarde de la configuration dynamique désactivée" + shift + ;; + --no-compression) + COMPRESS_LOGS=false + log "Option: Compression des logs désactivée" + shift + ;; + --help) + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " --no-config Ne pas sauvegarder la configuration" + echo " --no-certificates Ne pas sauvegarder les certificats" + echo " --no-logs Ne pas sauvegarder les logs" + echo " --no-dynamic-config Ne pas sauvegarder la configuration dynamique" + echo " --no-compression Ne pas compresser les logs" + echo " --help Afficher cette aide" + exit 0 + ;; + *) + error_exit "Option inconnue: $1" + ;; + esac +done + +# Création du fichier de log si nécessaire +mkdir -p "$(dirname "$LOG_FILE")" +touch "$LOG_FILE" + +# Lancement du script principal +main "$@" \ No newline at end of file