#!/bin/bash # ============================================================================= # setup.sh — Installation complète des scripts Docker # ============================================================================= # Usage : # bash setup.sh → Installation interactive complète # bash setup.sh --force → Installation sans confirmation # bash setup.sh --update → Mise à jour des scripts (git pull) # bash setup.sh --dry-run → Affiche ce qui serait fait # # Ce script : # 1. Clone ou met à jour les scripts depuis Git # 2. Vérifie que tous les prérequis sont installés # 3. Rend les scripts exécutables # 4. Crée les dossiers de logs # 5. Installe les entrées cron # 6. Configure la rotation des logs (logrotate) # 7. Propose un premier backup # ============================================================================= set -euo pipefail # ─── Charger la configuration du template (si présent dans le même dossier) ──── SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" if [[ -f "$SCRIPT_DIR/docker-scripts.conf" ]]; then # shellcheck source=/dev/null source "$SCRIPT_DIR/docker-scripts.conf" fi # ─── Configuration (fallbacks après chargement du template) ────────────────── GIT_REPO="${GIT_REPO:-https://git.dracodev.net/Outils/docker-stack-template.git}" SCRIPTS_DIR="${SCRIPTS_DIR:-/opt/docker-scripts}" BRANCH="${GIT_BRANCH:-main}" DOCKER_APP_NAME="${DOCKER_APP_NAME:-gitea}" # ─── Couleurs ─────────────────────────────────────────────────────────────── RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; BLUE='\033[0;34m'; NC='\033[0m' ok() { echo -e " ${GREEN}✅${NC} $1"; } warn() { echo -e " ${YELLOW}⚠️${NC} $1"; } err() { echo -e " ${RED}❌${NC} $1"; } info() { echo -e " ${CYAN}📋${NC} $1"; } step() { echo -e "\n${BLUE}════════════════════════════════════════════════════════${NC}"; echo -e "${BLUE}🔧 $1${NC}"; echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"; } # ─── Usage ────────────────────────────────────────────────────────────────── usage() { cat << EOF Usage: $0 [OPTIONS] Options : --check Vérifier les prérequis uniquement (sans installer) --force Installation sans confirmation --update Mettre à jour les scripts existants (git pull) --dry-run Affiche ce qui serait fait sans rien installer --help Cette aide Variables d'environnement : GIT_REPO URL du dépôt Git (défaut: $GIT_REPO) SCRIPTS_DIR Dossier d'installation (défaut: /opt/docker-scripts) BRANCH Branche Git à utiliser (défaut: main) CMD_DEPEND Liste des prérequis (défaut: git,docker,curl,tar,gzip,crontab) EOF exit 0 } # ─── Vérification des prérequis système ───────────────────────────────────── check_system_prerequisites() { step "Vérification des prérequis système" local missing=0 # Lire la liste depuis la configuration (défaut: git,docker,curl,tar,gzip,crontab) CMD_DEPEND="${CMD_DEPEND:-git,docker,curl,tar,gzip,crontab}" IFS=',' read -ra CMDS <<< "$CMD_DEPEND" info "Vérification des commandes requises (CMD_DEPEND=$CMD_DEPEND)..." for cmd in "${CMDS[@]}"; do # Trim whitespace cmd="$(echo "$cmd" | xargs)" if command -v "$cmd" &>/dev/null; then local version="" case "$cmd" in git) version=$(git --version 2>/dev/null | head -1) ;; docker) version=$(docker --version 2>/dev/null | head -1) ;; curl) version=$(curl --version 2>/dev/null | head -1) ;; esac ok "$cmd ${version:+($version)}" else err "$cmd : NON INSTALLÉ" missing=1 fi done # Vérifier docker compose (toujours pertinent, pas dans CMD_DEPEND) if docker compose version &>/dev/null; then ok "docker compose (plugin)" elif command -v docker-compose &>/dev/null; then ok "docker-compose (standalone)" else err "docker compose : NON INSTALLÉ" missing=1 fi # Vérifier le daemon Docker if docker info &>/dev/null; then ok "Docker daemon : actif" else warn "Docker daemon : injoignable (vérifier que Docker tourne)" fi if [[ $missing -gt 0 ]]; then echo "" err "$missing prérequis manquants. Installez-les avant de continuer." return 1 fi return 0 } # ─── Cloner ou mettre à jour les scripts ──────────────────────────────────── install_scripts() { step "Étape 2/6 : Installation des scripts" if [[ -d "$SCRIPTS_DIR/.git" ]]; then info "Dépôt existant trouvé dans $SCRIPTS_DIR" cd "$SCRIPTS_DIR" local current_remote current_remote=$(git remote get-url origin 2>/dev/null || echo "") if [[ "$current_remote" == "$GIT_REPO" ]]; then info "Mise à jour depuis $GIT_REPO (branche: $BRANCH)..." git fetch origin "$BRANCH" 2>&1 || { warn "Impossible de fetch — on continue avec la version actuelle" } if git diff --quiet "origin/$BRANCH" 2>/dev/null; then ok "Scripts déjà à jour" else git pull origin "$BRANCH" 2>&1 || { warn "Impossible de pull — on continue avec la version actuelle" } ok "Scripts mis à jour" fi else warn "Remote différent ($current_remote != $GIT_REPO) — pas de mise à jour automatique" fi else info "Clonage de $GIT_REPO vers $SCRIPTS_DIR..." if [[ -d "$SCRIPTS_DIR" ]]; then warn "$SCRIPTS_DIR existe déjà mais n'est pas un dépôt Git" info "Sauvegarde dans ${SCRIPTS_DIR}.bak..." mv "$SCRIPTS_DIR" "${SCRIPTS_DIR}.bak.$(date +%s)" 2>/dev/null || true fi git clone --branch "$BRANCH" "$GIT_REPO" "$SCRIPTS_DIR" 2>&1 || { err "Échec du clone de $GIT_REPO" exit 1 } ok "Scripts clonés dans $SCRIPTS_DIR" fi # Vérifier que les scripts principaux existent local scripts_ok=true for script in "docker-backup.sh" "docker-auto-update.sh" "install_cron.sh" "restore.sh" "docker-scripts.conf"; do if [[ -f "$SCRIPTS_DIR/$script" ]]; then ok "$script présent" else warn "$script : absent" scripts_ok=false fi done if [[ "$scripts_ok" != "true" ]]; then warn "Certains scripts sont absents — le dépôt peut être incomplet" fi return 0 } # ─── Rendre les scripts exécutables ───────────────────────────────────────── make_executable() { step "Étape 3/6 : Permissions des scripts" for script in "docker-backup.sh" "docker-auto-update.sh" "install_cron.sh" "restore.sh" "setup.sh"; do if [[ -f "$SCRIPTS_DIR/$script" ]]; then chmod +x "$SCRIPTS_DIR/$script" ok "$script → exécutable" fi done return 0 } # ─── Créer les dossiers de logs ───────────────────────────────────────────── setup_logs() { step "Étape 4/6 : Configuration des logs" # LOG_DIR, BACKUP_CRON_LOG, UPDATE_CRON_LOG déjà chargés depuis docker-scripts.conf LOG_DIR="${LOG_DIR:-/var/log}" BACKUP_CRON_LOG="${BACKUP_CRON_LOG:-$LOG_DIR/${DOCKER_APP_NAME}-backup-cron.log}" UPDATE_CRON_LOG="${UPDATE_CRON_LOG:-$LOG_DIR/${DOCKER_APP_NAME}-update-cron.log}" if [[ -d "$LOG_DIR" ]] && [[ -w "$LOG_DIR" ]]; then ok "Dossier de logs $LOG_DIR accessible" elif [[ -d "$LOG_DIR" ]]; then warn "Pas de droit d'écriture sur $LOG_DIR" info "Les logs seront écrits dans $HOME/" LOG_DIR="$HOME" BACKUP_CRON_LOG="$HOME/${DOCKER_APP_NAME}-backup-cron.log" UPDATE_CRON_LOG="$HOME/${DOCKER_APP_NAME}-update-cron.log" else if mkdir -p "$LOG_DIR" 2>/dev/null; then ok "Dossier de logs $LOG_DIR créé" else warn "Impossible de créer $LOG_DIR — logs dans $HOME/" LOG_DIR="$HOME" BACKUP_CRON_LOG="$HOME/${DOCKER_APP_NAME}-backup-cron.log" UPDATE_CRON_LOG="$HOME/${DOCKER_APP_NAME}-update-cron.log" fi fi # Créer les fichiers de log s'ils n'existent pas touch "$BACKUP_CRON_LOG" "$UPDATE_CRON_LOG" 2>/dev/null || true return 0 } # ─── Configurer logrotate ─────────────────────────────────────────────────── setup_logrotate() { step "Étape 5/6 : Rotation des logs" local logrotate_conf="/etc/logrotate.d/docker-scripts" local need_sudo=false if [[ -f "$logrotate_conf" ]]; then ok "logrotate déjà configuré : $logrotate_conf" return 0 fi if [[ ! -w "/etc/logrotate.d" ]]; then need_sudo=true fi local log_files="$BACKUP_CRON_LOG $UPDATE_CRON_LOG /var/log/${DOCKER_APP_NAME}-backup.log /var/log/${DOCKER_APP_NAME}-update.log" cat << LOGROTATE # Rotation des logs Docker scripts $log_files { weekly rotate 12 compress delaycompress missingok notifempty copytruncate create 0644 $USER $USER } LOGROTATE echo "" if [[ "$need_sudo" == "true" ]]; then warn "Droits sudo requis pour créer $logrotate_conf" info "Voici la commande à exécuter :" echo "" echo " sudo tee $logrotate_conf << 'EOF'" cat << LOGROTATE # Rotation des logs Docker scripts $log_files { weekly rotate 12 compress delaycompress missingok notifempty copytruncate create 0644 $USER $USER } LOGROTATE echo "EOF" echo "" read -p "Exécuter cette commande maintenant ? [O/n] " -r REPLY if [[ "$REPLY" =~ ^[OoYy]?$ ]]; then sudo tee "$logrotate_conf" > /dev/null << LOGROTATE_EOF # Rotation des logs Docker scripts $log_files { weekly rotate 12 compress delaycompress missingok notifempty copytruncate create 0644 $USER $USER } LOGROTATE_EOF ok "logrotate configuré" else info "Vous pourrez configurer logrotate plus tard avec la commande ci-dessus" fi else cat > "$logrotate_conf" << LOGROTATE_EOF # Rotation des logs Docker scripts $log_files { weekly rotate 12 compress delaycompress missingok notifempty copytruncate create 0644 $USER $USER } LOGROTATE_EOF ok "logrotate configuré : $logrotate_conf" fi return 0 } # ─── Installer les crons ──────────────────────────────────────────────────── setup_cron() { step "Étape 6/6 : Installation des crons" if [[ -f "$SCRIPTS_DIR/install_cron.sh" ]]; then if [[ "$FORCE" == "true" ]]; then bash "$SCRIPTS_DIR/install_cron.sh" --force else bash "$SCRIPTS_DIR/install_cron.sh" fi else err "install_cron.sh introuvable" return 1 fi return 0 } # ─── Mise à jour (git pull) ───────────────────────────────────────────────── do_update() { step "Mise à jour des scripts Docker" if [[ ! -d "$SCRIPTS_DIR/.git" ]]; then err "$SCRIPTS_DIR n'est pas un dépôt Git — impossible de mettre à jour" exit 1 fi cd "$SCRIPTS_DIR" info "Fetch des dernières modifications..." git fetch origin "$BRANCH" 2>&1 if git diff --quiet "origin/$BRANCH" 2>/dev/null; then ok "Scripts déjà à jour" else info "Mise à jour disponible — application..." git pull origin "$BRANCH" 2>&1 ok "Scripts mis à jour" # Rendre exécutables à nouveau (au cas où) for script in *.sh; do [[ -f "$script" ]] && chmod +x "$script" done echo "" info "Scripts mis à jour : $(git log --oneline -3)" fi exit 0 } # ═════════════════════════════════════════════════════════════════════════════ # MAIN # ═════════════════════════════════════════════════════════════════════════════ FORCE=false DRY_RUN=false UPDATE=false CHECK=false for arg in "$@"; do case "$arg" in --check) CHECK=true ;; --force) FORCE=true ;; --dry-run) DRY_RUN=true ;; --update) UPDATE=true ;; --help|-h) usage ;; *) echo "Option inconnue : $arg"; usage ;; esac done echo "" echo "╔══════════════════════════════════════════════════════╗" echo "║ 🛠️ SCRIPTS DOCKER — INSTALLATEUR ║" echo "╚══════════════════════════════════════════════════════╝" echo "" info "Dossier scripts : $SCRIPTS_DIR" info "Dépôt Git : $GIT_REPO" info "Branche : $BRANCH" echo "" # ─── Mode vérification (--check) ──────────────────────────────────────────── if [[ "$CHECK" == "true" ]]; then echo "" echo "🔍 VÉRIFICATION DES PRÉREQUIS" echo "" if check_system_prerequisites; then echo "" ok "Tous les prérequis sont satisfaits. Vous pouvez lancer l'installation :" echo "" echo " bash $0" echo " bash $0 --force (sans confirmation)" echo "" exit 0 else echo "" err "Corrigez les prérequis manquants avant de lancer l'installation." exit 1 fi fi # ─── Mode mise à jour ────────────────────────────────────────────────────── if [[ "$UPDATE" == "true" ]]; then do_update fi # ─── Mode dry-run ─────────────────────────────────────────────────────────── if [[ "$DRY_RUN" == "true" ]]; then echo "🔍 DRY RUN — aucune action ne sera effectuée" echo "" echo "Actions qui seraient exécutées :" echo "" echo " 1. Vérifier les prérequis (CMD_DEPEND=${CMD_DEPEND:-git,docker,curl,tar,gzip,crontab})" echo " 2. Cloner/MàJ $GIT_REPO → $SCRIPTS_DIR" echo " 3. Rendre les scripts exécutables" echo " 4. Créer les dossiers de logs" echo " 5. Configurer logrotate" echo " 6. Installer les crons (backup + auto-update)" echo "" exit 0 fi # ─── Confirmation interactive ─────────────────────────────────────────────── if [[ "$FORCE" != "true" ]]; then echo "Ce script va installer complètement les scripts de maintenance Docker :" echo "" echo " 1. Vérifier les prérequis système" echo " 2. Cloner/MàJ les scripts depuis Git" echo " 3. Rendre les scripts exécutables" echo " 4. Créer les dossiers de logs" echo " 5. Configurer la rotation des logs" echo " 6. Installer les tâches cron (backup + auto-update)" echo "" read -p "Continuer l'installation ? [O/n] " -r REPLY if [[ ! "$REPLY" =~ ^[OoYy]?$ ]]; then echo "Installation annulée." exit 0 fi fi # ─── Exécution des étapes ─────────────────────────────────────────────────── check_system_prerequisites install_scripts make_executable setup_logs setup_logrotate setup_cron # ═════════════════════════════════════════════════════════════════════════════ # RÉSUMÉ FINAL # ═════════════════════════════════════════════════════════════════════════════ echo "" echo "╔══════════════════════════════════════════════════════╗" echo "║ ✅ INSTALLATION TERMINÉE ! ║" echo "╚══════════════════════════════════════════════════════╝" echo "" echo "📂 Scripts installés dans : $SCRIPTS_DIR" echo "" echo "📋 Commandes utiles :" echo "" echo " 🔍 Vérifier l'état : bash $SCRIPTS_DIR/install_cron.sh --status" echo " 💾 Backup manuel : bash $SCRIPTS_DIR/docker-backup.sh" echo " 🔄 Restaurer : bash $SCRIPTS_DIR/restore.sh " echo " ⬆️ Mise à jour : bash $SCRIPTS_DIR/setup.sh --update" echo " 🗑️ Désinstaller : bash $SCRIPTS_DIR/install_cron.sh --uninstall" echo "" echo "⚙️ Configuration : $SCRIPTS_DIR/docker-scripts.conf" echo "" echo "📊 Logs :" echo " Backup : ${LOG_DIR:-/var/log}/${DOCKER_APP_NAME}-backup.log" echo " Update : ${LOG_DIR:-/var/log}/${DOCKER_APP_NAME}-update.log" echo " Cron backup : ${BACKUP_CRON_LOG:-$HOME/${DOCKER_APP_NAME}-backup-cron.log}" echo " Cron update : ${UPDATE_CRON_LOG:-$HOME/${DOCKER_APP_NAME}-update-cron.log}" echo "" echo "🕐 Tâches cron :" echo " Backup : $(grep "$SCRIPTS_DIR/docker-backup.sh" <(crontab -l 2>/dev/null) | awk '{print $1" "$2" "$3" "$4" "$5}')" echo " Update : $(grep "$SCRIPTS_DIR/docker-auto-update.sh" <(crontab -l 2>/dev/null) | awk '{print $1" "$2" "$3" "$4" "$5}')" echo "" # Proposer un premier backup if [[ "$FORCE" != "true" ]]; then read -p "💾 Lancer un premier backup maintenant ? [O/n] " -r REPLY if [[ "$REPLY" =~ ^[OoYy]?$ ]]; then echo "" bash "$SCRIPTS_DIR/docker-backup.sh" fi fi echo "" echo "🎉 Prêt ! Les scripts tourneront automatiquement selon le planning cron." echo "" exit 0