Files
agence66-gitea/scripts/restore.sh
BeauTroll e7d3b6cf16 Fix restore script permissions handling with sudo
Add sudo usage for data directory operations to handle Docker-created files
owned by UID 1000. The restore script now properly cleans and extracts data
with correct permissions, preventing "Permission denied" errors when restoring
backups.

Changes:
- Use sudo rm for cleaning existing data directory
- Use sudo tar for extracting backup data
- Add sudo chown to restore proper file ownership (1000:1000)
- Remove redundant success message from Makefile restore target

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-17 05:56:58 +01:00

300 lines
9.8 KiB
Bash
Executable File

#!/bin/bash
# ============================================
# Script de restauration Gitea
# ============================================
# Ce script restaure une sauvegarde complète de Gitea
# ATTENTION: Cette opération est destructive!
set -euo pipefail # Arrêter en cas d'erreur, variables non définies, erreurs dans pipes
# Couleurs pour l'affichage
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Vérifier qu'un fichier de sauvegarde a été fourni
if [ -z "${1:-}" ]; then
echo -e "${RED}Erreur: Aucun fichier de sauvegarde spécifié${NC}"
echo "Usage: $0 <fichier_sauvegarde.tar.gz>"
echo "Exemple: $0 backups/gitea_backup_20240101_120000.tar.gz"
exit 1
fi
BACKUP_FILE="$1"
# Vérifier que le fichier existe
if [ ! -f "$BACKUP_FILE" ]; then
echo -e "${RED}Erreur: Le fichier $BACKUP_FILE n'existe pas${NC}"
exit 1
fi
# Vérifier que c'est bien un fichier gzip
if ! file "$BACKUP_FILE" | grep -q "gzip compressed"; then
echo -e "${RED}Erreur: Le fichier n'est pas une archive gzip valide${NC}"
exit 1
fi
# Validation du chemin (sécurité contre path traversal)
BACKUP_FILE=$(realpath "$BACKUP_FILE")
BACKUPS_DIR=$(realpath "./backups" 2>/dev/null || echo "")
if [ -n "$BACKUPS_DIR" ] && [[ "$BACKUP_FILE" != "$BACKUPS_DIR"* ]]; then
echo -e "${YELLOW}Avertissement: Le fichier n'est pas dans le répertoire backups${NC}"
read -p "Continuer quand même? (oui/non) " -r
if [[ ! $REPLY =~ ^[Oo][Uu][Ii]$ ]]; then
echo "Restauration annulée."
exit 0
fi
fi
# Vérifier le checksum si disponible
CHECKSUM_FILE="${BACKUP_FILE}.sha256"
if [ -f "$CHECKSUM_FILE" ]; then
echo -e "${BLUE}Vérification du checksum...${NC}"
if cd "$(dirname "$BACKUP_FILE")" && sha256sum -c "$(basename "$CHECKSUM_FILE")" > /dev/null 2>&1; then
echo -e "${GREEN}✓ Checksum valide${NC}"
cd - > /dev/null
else
echo -e "${RED}Erreur: Checksum invalide! Le fichier peut être corrompu.${NC}"
cd - > /dev/null 2>&1 || true
read -p "Continuer quand même? (oui/non) " -r
if [[ ! $REPLY =~ ^[Oo][Uu][Ii]$ ]]; then
echo "Restauration annulée."
exit 0
fi
fi
else
echo -e "${YELLOW}Avertissement: Aucun fichier checksum trouvé${NC}"
fi
# Charger les variables d'environnement de manière sécurisée
if [ -f .env ]; then
set -a
source .env
set +a
else
echo -e "${RED}Erreur: Fichier .env non trouvé${NC}"
exit 1
fi
# Vérifier que les variables nécessaires sont définies
if [ -z "${POSTGRES_DATABASE:-}" ] || [ -z "${POSTGRES_USER:-}" ] || [ -z "${POSTGRES_PASSWORD:-}" ]; then
echo -e "${RED}Erreur: Variables PostgreSQL non définies dans .env${NC}"
exit 1
fi
# Variables
TEMP_DIR=$(mktemp -d)
BACKUP_NAME=$(basename "$BACKUP_FILE" .tar.gz)
LOG_DIR="./logs"
LOG_FILE="${LOG_DIR}/restore_$(date +%Y%m%d_%H%M%S).log"
# Créer le répertoire de logs
mkdir -p "$LOG_DIR"
# Fonction de logging
log() {
echo -e "$@" | tee -a "$LOG_FILE"
}
# Fonction de nettoyage
cleanup() {
local exit_code=$?
if [ -d "$TEMP_DIR" ]; then
log "${YELLOW}Nettoyage des fichiers temporaires...${NC}"
rm -rf "$TEMP_DIR"
fi
if [ $exit_code -ne 0 ]; then
log "${RED}Restauration échouée avec le code: $exit_code${NC}"
log "${YELLOW}Les services peuvent être dans un état incohérent.${NC}"
log "Consultez le log: $LOG_FILE"
fi
}
# Piège pour nettoyer en cas d'erreur ou d'interruption
trap cleanup EXIT INT TERM
log "${RED}=== ATTENTION: Restauration de Gitea ===${NC}"
log "Fichier de sauvegarde: $BACKUP_FILE"
log "${RED}Cette opération va ÉCRASER toutes les données actuelles!${NC}"
echo ""
read -p "Êtes-vous sûr de vouloir continuer? (oui/non) " -r
if [[ ! $REPLY =~ ^[Oo][Uu][Ii]$ ]]; then
log "Restauration annulée par l'utilisateur."
exit 0
fi
# Créer un backup de sécurité de la DB actuelle avant de la dropper
SAFETY_BACKUP_DIR="${TEMP_DIR}/safety_backup"
mkdir -p "$SAFETY_BACKUP_DIR"
log ""
log "${GREEN}=== Début de la restauration ===${NC}"
log "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC}"
log "${YELLOW}[1/6] Extraction de l'archive...${NC}"
if ! tar xzf "$BACKUP_FILE" -C "$TEMP_DIR" 2>> "$LOG_FILE"; then
log "${RED}Erreur: Échec de l'extraction de l'archive${NC}"
exit 1
fi
# Trouver le répertoire de sauvegarde
BACKUP_DIR=$(find "$TEMP_DIR" -maxdepth 1 -type d -name "gitea_backup_*" | head -n 1)
if [ -z "$BACKUP_DIR" ]; then
log "${RED}Erreur: Structure de sauvegarde invalide${NC}"
exit 1
fi
# Vérifier que les fichiers nécessaires existent
if [ ! -f "$BACKUP_DIR/database.dump" ] || [ ! -f "$BACKUP_DIR/gitea_data.tar.gz" ]; then
log "${RED}Erreur: Fichiers de sauvegarde manquants${NC}"
log "Contenu trouvé: $(ls -la "$BACKUP_DIR" 2>&1)"
exit 1
fi
log "${GREEN}✓ Archive extraite et vérifiée${NC}"
log "${YELLOW}[2/6] Arrêt des services...${NC}"
if ! docker compose down 2>> "$LOG_FILE"; then
log "${YELLOW}Avertissement: Erreur lors de l'arrêt des services${NC}"
fi
log "${GREEN}✓ Services arrêtés${NC}"
log "${YELLOW}[3/6] Démarrage de PostgreSQL et backup de sécurité...${NC}"
docker compose up -d db
log "Attente du démarrage de PostgreSQL..."
# Attendre que PostgreSQL soit prêt
MAX_TRIES=30
COUNTER=0
until docker compose exec -T db pg_isready -U "$POSTGRES_USER" > /dev/null 2>&1; do
COUNTER=$((COUNTER + 1))
if [ $COUNTER -gt $MAX_TRIES ]; then
log "${RED}Erreur: PostgreSQL ne démarre pas${NC}"
exit 1
fi
log "En attente de PostgreSQL... ($COUNTER/$MAX_TRIES)"
sleep 2
done
log "${GREEN}✓ PostgreSQL prêt${NC}"
# Créer un backup de sécurité de la DB actuelle
log "${BLUE}Création d'un backup de sécurité de la DB actuelle...${NC}"
if docker compose exec -T -e PGPASSWORD="$POSTGRES_PASSWORD" db pg_dump \
-U "$POSTGRES_USER" \
-d "$POSTGRES_DATABASE" \
--format=custom \
> "$SAFETY_BACKUP_DIR/current_db.dump" 2>> "$LOG_FILE"; then
log "${GREEN}✓ Backup de sécurité créé${NC}"
else
log "${YELLOW}Avertissement: Impossible de créer le backup de sécurité (DB peut ne pas exister)${NC}"
fi
log "${YELLOW}[4/6] Restauration de la base de données...${NC}"
# Supprimer et recréer la base de données
if ! docker compose exec -T -e PGPASSWORD="$POSTGRES_PASSWORD" db psql \
-U "$POSTGRES_USER" -d postgres \
-c "DROP DATABASE IF EXISTS $POSTGRES_DATABASE;" 2>> "$LOG_FILE"; then
log "${RED}Erreur: Échec de la suppression de la base de données${NC}"
exit 1
fi
if ! docker compose exec -T -e PGPASSWORD="$POSTGRES_PASSWORD" db psql \
-U "$POSTGRES_USER" -d postgres \
-c "CREATE DATABASE $POSTGRES_DATABASE OWNER $POSTGRES_USER;" 2>> "$LOG_FILE"; then
log "${RED}Erreur: Échec de la création de la base de données${NC}"
exit 1
fi
# Restaurer le dump
if ! docker compose exec -T -e PGPASSWORD="$POSTGRES_PASSWORD" db pg_restore \
-U "$POSTGRES_USER" \
-d "$POSTGRES_DATABASE" \
--clean \
--if-exists \
--no-owner \
--no-acl \
< "$BACKUP_DIR/database.dump" 2>> "$LOG_FILE"; then
log "${RED}Erreur: Échec de la restauration de la base de données${NC}"
log "${YELLOW}Le backup de sécurité est disponible dans: $SAFETY_BACKUP_DIR/current_db.dump${NC}"
exit 1
fi
log "${GREEN}✓ Base de données restaurée${NC}"
log "${YELLOW}[5/6] Restauration des données Gitea...${NC}"
# Arrêter Gitea s'il tourne
docker compose stop gitea 2>/dev/null || true
# Nettoyer les données existantes de manière sécurisée avec les bonnes permissions
DATA_DIR="./data"
if [ -d "$DATA_DIR" ]; then
log "Suppression des anciennes données avec sudo..."
# Utiliser sudo pour supprimer les fichiers appartenant à l'utilisateur Docker
if ! sudo rm -rf "$DATA_DIR"/* 2>> "$LOG_FILE"; then
log "${YELLOW}Avertissement: Échec du nettoyage${NC}"
log "Vous pouvez exécuter manuellement: sudo rm -rf $DATA_DIR/*"
read -p "Continuer quand même? (oui/non) " -r
if [[ ! $REPLY =~ ^[Oo][Uu][Ii]$ ]]; then
exit 1
fi
fi
fi
# Créer le répertoire de données
mkdir -p "$DATA_DIR"
# Extraire les données depuis l'archive avec sudo pour les permissions
log "Extraction des données Gitea..."
if ! sudo tar xzf "$BACKUP_DIR/gitea_data.tar.gz" -C "$DATA_DIR" 2>> "$LOG_FILE"; then
log "${RED}Erreur: Échec de l'extraction des données Gitea${NC}"
exit 1
fi
# Restaurer les bonnes permissions (UID/GID 1000 pour Gitea)
log "Restauration des permissions..."
if ! sudo chown -R 1000:1000 "$DATA_DIR" 2>> "$LOG_FILE"; then
log "${YELLOW}Avertissement: Impossible de changer les permissions${NC}"
fi
# Vérifier les permissions
log "Vérification des permissions..."
if [ -d "$DATA_DIR/gitea" ]; then
log "${GREEN}✓ Données restaurées${NC}"
else
log "${YELLOW}Avertissement: Structure de données inattendue${NC}"
fi
log "${YELLOW}[6/6] Redémarrage de tous les services...${NC}"
# Démarrer tous les services (db, redis, gitea)
docker compose up -d
# Attendre que les services soient prêts
log "Attente du démarrage complet..."
sleep 10
MAX_TRIES=30
COUNTER=0
until docker compose ps --status running --services | grep -q '^gitea$'; do
COUNTER=$((COUNTER + 1))
if [ $COUNTER -gt $MAX_TRIES ]; then
log "${YELLOW}Avertissement: Gitea met du temps à démarrer${NC}"
break
fi
log "En attente de Gitea... ($COUNTER/$MAX_TRIES)"
sleep 2
done
log ""
log "${GREEN}=== Restauration terminée avec succès ===${NC}"
log "Gitea devrait être accessible sur: http://localhost:3000"
log ""
log "Vérifications recommandées:"
log " - Vérifier l'accès web"
log " - Tester l'authentification"
log " - Vérifier les dépôts"
log " - Consulter les logs: docker compose logs -f gitea"
log ""
log "Log de restauration: $LOG_FILE"
log "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] Restauration terminée${NC}"