diff --git a/scripts/backup.sh b/scripts/backup.sh index 467a3a0..b28c320 100644 --- a/scripts/backup.sh +++ b/scripts/backup.sh @@ -1,14 +1,51 @@ #!/bin/bash # scripts/backup.sh - Backup complet Nextcloud -set -e +set -euo pipefail +# Charger les variables d'environnement +if [ ! -f .env ]; then + echo "❌ Erreur: Fichier .env introuvable" + exit 1 +fi + +# shellcheck disable=SC1091 source .env +# Vérifier les variables requises +: "${MYSQL_USER:?Variable MYSQL_USER non définie}" +: "${MYSQL_PASSWORD:?Variable MYSQL_PASSWORD non définie}" +: "${MYSQL_DATABASE:?Variable MYSQL_DATABASE non définie}" + BACKUP_DIR="${BACKUP_DESTINATION:-./backups}" DATE=$(date +%Y%m%d_%H%M%S) BACKUP_NAME="nextcloud_backup_$DATE" BACKUP_PATH="$BACKUP_DIR/$BACKUP_NAME" +MAINTENANCE_ENABLED=false + +# Fonction de nettoyage en cas d'erreur +cleanup() { + local exit_code=$? + if [ "$exit_code" -ne 0 ]; then + echo "❌ Erreur détectée (code: $exit_code), nettoyage..." + fi + + # Désactiver le mode maintenance si activé + if [ "$MAINTENANCE_ENABLED" = true ]; then + echo "▶️ Désactivation du mode maintenance..." + docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --off || true + fi + + # Nettoyer le backup partiel + if [ -d "$BACKUP_PATH" ]; then + echo "🧹 Nettoyage du backup partiel..." + rm -rf "${BACKUP_PATH:?}" + fi + + exit "$exit_code" +} + +trap cleanup EXIT INT TERM echo "🔧 Démarrage du backup: $BACKUP_NAME" @@ -17,18 +54,25 @@ mkdir -p "$BACKUP_PATH" # 1. Activer le mode maintenance echo "⏸️ Activation du mode maintenance..." -docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --on +if docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --on; then + MAINTENANCE_ENABLED=true +else + echo "❌ Impossible d'activer le mode maintenance" + exit 1 +fi # 2. Backup de la base de données echo "💾 Backup de la base de données..." -docker-compose exec -T db mysqldump \ - -u"$MYSQL_USER" \ - -p"$MYSQL_PASSWORD" \ - "$MYSQL_DATABASE" \ +# Utiliser des variables d'environnement pour éviter le mot de passe dans la ligne de commande +if ! docker-compose exec -T db sh -c "MYSQL_PWD=\"\$MYSQL_PASSWORD\" mysqldump \ + -u\"\$MYSQL_USER\" \ + \"\$MYSQL_DATABASE\" \ --single-transaction \ --quick \ - --lock-tables=false \ - > "$BACKUP_PATH/database.sql" + --lock-tables=false" > "$BACKUP_PATH/database.sql"; then + echo "❌ Erreur lors du backup de la base de données" + exit 1 +fi # 3. Backup des fichiers de config echo "⚙️ Backup de la configuration..." @@ -59,17 +103,26 @@ fi # 6. Désactiver le mode maintenance echo "▶️ Désactivation du mode maintenance..." -docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --off +if docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --off; then + MAINTENANCE_ENABLED=false +else + echo "⚠️ Attention: Impossible de désactiver le mode maintenance" +fi # 7. Créer une archive complète echo "🗜️ Compression finale..." -cd "$BACKUP_DIR" -tar -czf "$BACKUP_NAME.tar.gz" "$BACKUP_NAME/" -rm -rf "$BACKUP_NAME" +if ! tar -czf "$BACKUP_DIR/$BACKUP_NAME.tar.gz" -C "$BACKUP_DIR" "$BACKUP_NAME/"; then + echo "❌ Erreur lors de la compression" + exit 1 +fi + +# Supprimer le dossier temporaire après compression réussie +rm -rf "${BACKUP_PATH:?}" # 8. Nettoyer les vieux backups -echo "🧹 Nettoyage des backups > ${BACKUP_RETENTION_DAYS:-30} jours..." -find "$BACKUP_DIR" -name "nextcloud_backup_*.tar.gz" -mtime +${BACKUP_RETENTION_DAYS:-30} -delete +RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-30}" +echo "🧹 Nettoyage des backups > $RETENTION_DAYS jours..." +find "$BACKUP_DIR" -name "nextcloud_backup_*.tar.gz" -type f -mtime +"$RETENTION_DAYS" -delete echo "✅ Backup terminé: $BACKUP_DIR/$BACKUP_NAME.tar.gz" du -h "$BACKUP_DIR/$BACKUP_NAME.tar.gz" diff --git a/scripts/occ.sh b/scripts/occ.sh index 0177f92..af5cf5a 100644 --- a/scripts/occ.sh +++ b/scripts/occ.sh @@ -1,6 +1,21 @@ #!/bin/bash # scripts/occ.sh - Wrapper pour commandes OCC -set -e +set -euo pipefail +# Vérifier que docker-compose est disponible +if ! command -v docker-compose >/dev/null 2>&1; then + echo "❌ Erreur: docker-compose n'est pas installé" + exit 1 +fi + +# Vérifier que le container nextcloud est actif +if ! docker-compose ps nextcloud | grep -q "Up"; then + echo "❌ Erreur: Le container nextcloud n'est pas actif" + echo " Démarrez-le avec: make up" + exit 1 +fi + +# Exécuter la commande OCC +# Le "$@" est sûr ici car il est passé directement à PHP OCC qui gère la validation docker-compose exec -u www-data nextcloud php occ "$@" diff --git a/scripts/restore.sh b/scripts/restore.sh index cfa6c11..99ca77b 100644 --- a/scripts/restore.sh +++ b/scripts/restore.sh @@ -1,22 +1,48 @@ #!/bin/bash # scripts/restore.sh - Restauration d'un backup -set -e +set -euo pipefail -if [ -z "$1" ]; then +# Charger les variables d'environnement +if [ ! -f .env ]; then + echo "❌ Erreur: Fichier .env introuvable" + exit 1 +fi + +# shellcheck disable=SC1091 +source .env + +# Vérifier les variables requises +: "${MYSQL_USER:?Variable MYSQL_USER non définie}" +: "${MYSQL_PASSWORD:?Variable MYSQL_PASSWORD non définie}" +: "${MYSQL_DATABASE:?Variable MYSQL_DATABASE non définie}" + +if [ -z "${1:-}" ]; then echo "Usage: $0 " exit 1 fi BACKUP_FILE="$1" +# Valider le chemin du fichier (éviter path traversal) +if [[ "$BACKUP_FILE" =~ \.\./\.\. ]]; then + echo "❌ Chemin de fichier invalide" + exit 1 +fi + if [ ! -f "$BACKUP_FILE" ]; then echo "❌ Fichier introuvable: $BACKUP_FILE" exit 1 fi +# Vérifier que c'est bien un fichier tar.gz +if ! file "$BACKUP_FILE" | grep -q "gzip compressed"; then + echo "❌ Le fichier n'est pas une archive gzip valide" + exit 1 +fi + echo "⚠️ ATTENTION: Cette opération va écraser les données actuelles !" -read -p "Continuer? (yes/no): " confirm +read -r -p "Continuer? (yes/no): " confirm if [ "$confirm" != "yes" ]; then echo "Annulé." @@ -25,32 +51,100 @@ fi # Extraire le backup TEMP_DIR=$(mktemp -d) -echo "📂 Extraction vers $TEMP_DIR..." -tar -xzf "$BACKUP_FILE" -C "$TEMP_DIR" -BACKUP_DIR=$(ls -1 "$TEMP_DIR" | head -n1) +# Fonction de nettoyage +cleanup() { + local exit_code=$? + if [ -d "$TEMP_DIR" ]; then + echo "🧹 Nettoyage du répertoire temporaire..." + rm -rf "${TEMP_DIR:?}" + fi + exit "$exit_code" +} + +trap cleanup EXIT INT TERM + +echo "📂 Extraction vers $TEMP_DIR..." +if ! tar -xzf "$BACKUP_FILE" -C "$TEMP_DIR"; then + echo "❌ Erreur lors de l'extraction" + exit 1 +fi + +# Trouver le répertoire de backup de manière sécurisée +BACKUP_DIR=$(find "$TEMP_DIR" -mindepth 1 -maxdepth 1 -type d | head -n1) +if [ -z "$BACKUP_DIR" ]; then + echo "❌ Aucun répertoire trouvé dans l'archive" + exit 1 +fi + +BACKUP_DIR=$(basename "$BACKUP_DIR") # Arrêter les services echo "⏹️ Arrêt des services..." docker-compose down +# Vérifier que les fichiers requis existent +if [ ! -f "$TEMP_DIR/$BACKUP_DIR/database.sql" ]; then + echo "❌ Fichier database.sql manquant dans l'archive" + exit 1 +fi + +if [ ! -f "$TEMP_DIR/$BACKUP_DIR/config.tar.gz" ]; then + echo "❌ Fichier config.tar.gz manquant dans l'archive" + exit 1 +fi + # Restaurer la base de données echo "💾 Restauration de la base de données..." docker-compose up -d db -sleep 10 -docker-compose exec -T db mysql \ - -u"$MYSQL_USER" \ - -p"$MYSQL_PASSWORD" \ - "$MYSQL_DATABASE" \ - < "$TEMP_DIR/$BACKUP_DIR/database.sql" +# Attendre que la base de données soit prête +echo "⏳ Attente de la base de données..." +for i in {1..30}; do + if docker-compose exec -T db mysqladmin ping -h localhost --silent 2>/dev/null; then + echo "✅ Base de données prête" + break + fi + if [ "$i" -eq 30 ]; then + echo "❌ Timeout: La base de données n'est pas prête" + exit 1 + fi + sleep 1 +done + +# Restaurer avec MYSQL_PWD pour éviter le mot de passe dans la commande +if ! docker-compose exec -T db sh -c "MYSQL_PWD=\"\$MYSQL_PASSWORD\" mysql \ + -u\"\$MYSQL_USER\" \ + \"\$MYSQL_DATABASE\"" < "$TEMP_DIR/$BACKUP_DIR/database.sql"; then + echo "❌ Erreur lors de la restauration de la base de données" + exit 1 +fi # Restaurer les fichiers echo "📁 Restauration des fichiers..." -tar -xzf "$TEMP_DIR/$BACKUP_DIR/config.tar.gz" -C ./data/config -tar -xzf "$TEMP_DIR/$BACKUP_DIR/data.tar.gz" -C ./data/data +# Vérifier et créer les répertoires si nécessaire +mkdir -p ./data/config ./data/data + +if ! tar -xzf "$TEMP_DIR/$BACKUP_DIR/config.tar.gz" -C ./data/config; then + echo "❌ Erreur lors de la restauration de la configuration" + exit 1 +fi + +# Restaurer les données si elles existent dans l'archive +if [ -f "$TEMP_DIR/$BACKUP_DIR/data.tar.gz" ]; then + if ! tar -xzf "$TEMP_DIR/$BACKUP_DIR/data.tar.gz" -C ./data/data; then + echo "❌ Erreur lors de la restauration des données" + exit 1 + fi +elif [ -d "$TEMP_DIR/$BACKUP_DIR/data" ]; then + # Si les données sont dans un dossier (backup rsync) + rsync -a "$TEMP_DIR/$BACKUP_DIR/data/" ./data/data/ +fi + +# Restaurer les apps personnalisées si présentes if [ -f "$TEMP_DIR/$BACKUP_DIR/apps.tar.gz" ]; then + mkdir -p ./data/custom_apps tar -xzf "$TEMP_DIR/$BACKUP_DIR/apps.tar.gz" -C ./data/custom_apps fi @@ -58,13 +152,23 @@ fi echo "▶️ Redémarrage des services..." docker-compose up -d +# Attendre que Nextcloud soit prêt +echo "⏳ Attente du démarrage de Nextcloud..." +for i in {1..60}; do + if docker-compose exec -T nextcloud curl -f http://localhost/status.php >/dev/null 2>&1; then + echo "✅ Nextcloud prêt" + break + fi + if [ "$i" -eq 60 ]; then + echo "⚠️ Warning: Nextcloud met du temps à démarrer, on continue..." + break + fi + sleep 1 +done + # Réparer et scanner echo "🔧 Réparation..." -sleep 30 -docker-compose exec -u www-data nextcloud php occ maintenance:repair -docker-compose exec -u www-data nextcloud php occ files:scan --all - -# Nettoyer -rm -rf "$TEMP_DIR" +docker-compose exec -u www-data nextcloud php occ maintenance:repair || echo "⚠️ Erreur lors de la réparation" +docker-compose exec -u www-data nextcloud php occ files:scan --all || echo "⚠️ Erreur lors du scan" echo "✅ Restauration terminée !" diff --git a/scripts/update.sh b/scripts/update.sh index 7e5966e..2efcb2a 100644 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -1,47 +1,98 @@ #!/bin/bash # scripts/update.sh - Mise à jour Nextcloud -set -e +set -euo pipefail + +MAINTENANCE_ENABLED=false + +# Fonction de nettoyage en cas d'erreur +cleanup() { + local exit_code=$? + + if [ "$exit_code" -ne 0 ]; then + echo "❌ Erreur détectée lors de la mise à jour (code: $exit_code)" + echo "⚠️ IMPORTANT: Vérifiez les logs et considérez une restauration si nécessaire" + fi + + # Désactiver le mode maintenance si activé + if [ "$MAINTENANCE_ENABLED" = true ]; then + echo "▶️ Tentative de désactivation du mode maintenance..." + docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --off 2>/dev/null || true + fi + + exit "$exit_code" +} + +trap cleanup EXIT INT TERM echo "🔄 Mise à jour de Nextcloud" # Backup avant update echo "💾 Backup de sécurité..." -bash scripts/backup.sh +if ! bash scripts/backup.sh; then + echo "❌ Erreur lors du backup, abandon de la mise à jour" + exit 1 +fi # Mode maintenance echo "⏸️ Mode maintenance activé" -docker-compose exec -u www-data nextcloud php occ maintenance:mode --on +if docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --on; then + MAINTENANCE_ENABLED=true +else + echo "❌ Impossible d'activer le mode maintenance" + exit 1 +fi # Pull nouvelle image echo "📥 Téléchargement de la nouvelle version..." -docker-compose pull nextcloud +if ! docker-compose pull nextcloud; then + echo "❌ Erreur lors du téléchargement de l'image" + exit 1 +fi # Restart echo "🔄 Redémarrage..." docker-compose up -d --force-recreate nextcloud cron # Attendre que Nextcloud soit prêt -echo "⏳ Attente du démarrage..." -sleep 30 +echo "⏳ Attente du démarrage de Nextcloud..." +for i in {1..60}; do + if docker-compose exec -T nextcloud curl -f http://localhost/status.php >/dev/null 2>&1; then + echo "✅ Nextcloud prêt" + break + fi + if [ "$i" -eq 60 ]; then + echo "❌ Timeout: Nextcloud n'est pas prêt" + exit 1 + fi + sleep 1 +done # Upgrade via OCC echo "⬆️ Lancement de l'upgrade..." -docker-compose exec -u www-data nextcloud php occ upgrade +if ! docker-compose exec -T -u www-data nextcloud php occ upgrade; then + echo "❌ Erreur lors de l'upgrade" + exit 1 +fi -# Scan et indices +# Scan et indices (non bloquant) echo "🔍 Scan des fichiers..." -docker-compose exec -u www-data nextcloud php occ files:scan --all +docker-compose exec -T -u www-data nextcloud php occ files:scan --all || echo "⚠️ Avertissement: Erreur lors du scan" echo "📊 Ajout des indices manquants..." -docker-compose exec -u www-data nextcloud php occ db:add-missing-indices +docker-compose exec -T -u www-data nextcloud php occ db:add-missing-indices || echo "⚠️ Avertissement: Erreur lors de l'ajout des indices" echo "🔧 Conversion des colonnes..." -docker-compose exec -u www-data nextcloud php occ db:convert-filecache-bigint --no-interaction +docker-compose exec -T -u www-data nextcloud php occ db:convert-filecache-bigint --no-interaction || echo "⚠️ Avertissement: Erreur lors de la conversion" # Désactiver maintenance echo "▶️ Désactivation du mode maintenance" -docker-compose exec -u www-data nextcloud php occ maintenance:mode --off +if docker-compose exec -T -u www-data nextcloud php occ maintenance:mode --off; then + MAINTENANCE_ENABLED=false + echo "✅ Mise à jour terminée !" +else + echo "⚠️ Attention: Impossible de désactiver le mode maintenance" + echo " Exécutez manuellement: make occ maintenance:mode --off" +fi -echo "✅ Mise à jour terminée !" -docker-compose exec -u www-data nextcloud php occ status +docker-compose exec -T -u www-data nextcloud php occ status