#!/bin/sh set -eu # ============================================================================ # E-COSPLAY - Script de sauvegarde pour migration vers un autre serveur # ---------------------------------------------------------------------------- # N'UTILISE PAS DOCKER. S'appuie sur les binaires installés sur l'hôte # (pg_dump, psql, tar, gzip) et lit DATABASE_URL depuis .env.local. # # Sauvegarde : # - Base PostgreSQL distante via DATABASE_URL (pg_dump logique) # - Fichiers uploadés (public/storage) # - Fichiers d'environnement et credentials (.env.local, google.json, ...) # # Le tout est empaqueté dans une archive tar.gz horodatée. # ============================================================================ RED='\033[0;31m' ORANGE='\033[0;33m' GREEN='\033[0;32m' CYAN='\033[0;36m' RESET='\033[0m' PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$PROJECT_DIR" TIMESTAMP="$(date +%Y%m%d_%H%M%S)" BACKUP_DIR="${BACKUP_DIR:-$PROJECT_DIR/var/backups}" WORK_DIR="$BACKUP_DIR/tmp_$TIMESTAMP" ARCHIVE="$BACKUP_DIR/e-cosplay_backup_$TIMESTAMP.tar.gz" STORAGE_DIR="${STORAGE_DIR:-public/storage}" echo "${CYAN}############################${RESET}" echo "${CYAN}# E-COSPLAY BACKUP START #${RESET}" echo "${CYAN}############################${RESET}" echo "${CYAN}Destination : ${ARCHIVE}${RESET}" mkdir -p "$WORK_DIR" # --------------------------------------------------------------------------- # 1) Vérifications # --------------------------------------------------------------------------- for bin in pg_dump tar gzip; do if ! command -v "$bin" >/dev/null 2>&1; then echo "${RED}Binaire introuvable : $bin${RESET}" >&2 exit 1 fi done # --------------------------------------------------------------------------- # 2) Récupération de DATABASE_URL # Priorité : variable d'env existante > .env.local > .env.prod.local > .env # --------------------------------------------------------------------------- get_database_url() { if [ -n "${DATABASE_URL:-}" ]; then echo "$DATABASE_URL" return 0 fi for f in .env.local .env.prod.local .env.prod .env; do if [ -f "$PROJECT_DIR/$f" ]; then url="$(grep -E '^DATABASE_URL=' "$PROJECT_DIR/$f" | tail -n1 | sed -E 's/^DATABASE_URL=//; s/^"(.*)"$/\1/; s/^'"'"'(.*)'"'"'$/\1/')" if [ -n "$url" ]; then echo "$url" return 0 fi fi done return 1 } DATABASE_URL_RAW="$(get_database_url || true)" if [ -z "$DATABASE_URL_RAW" ]; then echo "${RED}DATABASE_URL introuvable (ni en env, ni dans .env.local/.env)${RESET}" >&2 exit 1 fi # Strip des paramètres Doctrine (serverVersion, charset, ...) que libpq ignore DATABASE_URL_CLEAN="$(echo "$DATABASE_URL_RAW" | sed -E 's/\?.*$//')" # Affiche une URL masquée (cache le mot de passe) DATABASE_URL_MASKED="$(echo "$DATABASE_URL_CLEAN" | sed -E 's#(://[^:]+:)[^@]+(@)#\1***\2#')" echo "${CYAN}> DATABASE_URL : ${DATABASE_URL_MASKED}${RESET}" # --------------------------------------------------------------------------- # 3) Dump PostgreSQL # --------------------------------------------------------------------------- echo "${CYAN}> Dump PostgreSQL...${RESET}" pg_dump "$DATABASE_URL_CLEAN" \ --clean --if-exists --no-owner --no-privileges \ | gzip -9 > "$WORK_DIR/database.sql.gz" echo "${GREEN} ✓ database.sql.gz ($(du -h "$WORK_DIR/database.sql.gz" | cut -f1))${RESET}" # --------------------------------------------------------------------------- # 4) Fichiers uploadés # --------------------------------------------------------------------------- if [ -d "$PROJECT_DIR/$STORAGE_DIR" ]; then echo "${CYAN}> Sauvegarde de ${STORAGE_DIR}...${RESET}" tar -C "$PROJECT_DIR" -czf "$WORK_DIR/storage.tar.gz" "$STORAGE_DIR" echo "${GREEN} ✓ storage.tar.gz ($(du -h "$WORK_DIR/storage.tar.gz" | cut -f1))${RESET}" else echo "${ORANGE} ! ${STORAGE_DIR} introuvable, étape ignorée${RESET}" fi # --------------------------------------------------------------------------- # 5) Fichiers d'environnement et credentials # --------------------------------------------------------------------------- echo "${CYAN}> Copie des fichiers d'environnement et credentials...${RESET}" mkdir -p "$WORK_DIR/env" for f in .env .env.local .env.prod .env.prod.local google.json account.json; do if [ -f "$PROJECT_DIR/$f" ]; then cp -a "$PROJECT_DIR/$f" "$WORK_DIR/env/$f" echo "${GREEN} ✓ $f${RESET}" fi done # --------------------------------------------------------------------------- # 6) Métadonnées # --------------------------------------------------------------------------- { echo "timestamp=$TIMESTAMP" echo "hostname=$(hostname)" echo "git_commit=$(git -C "$PROJECT_DIR" rev-parse HEAD 2>/dev/null || echo unknown)" echo "git_branch=$(git -C "$PROJECT_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)" echo "database_url=$DATABASE_URL_MASKED" echo "storage_dir=$STORAGE_DIR" } > "$WORK_DIR/manifest.txt" # --------------------------------------------------------------------------- # 7) Empaquetage final # --------------------------------------------------------------------------- echo "${CYAN}> Empaquetage de l'archive finale...${RESET}" tar -C "$BACKUP_DIR" -czf "$ARCHIVE" "tmp_$TIMESTAMP" rm -rf "$WORK_DIR" echo "${GREEN}############################${RESET}" echo "${GREEN}# BACKUP TERMINÉ #${RESET}" echo "${GREEN}############################${RESET}" echo "${GREEN}Archive : ${ARCHIVE}${RESET}" echo "${GREEN}Taille : $(du -h "$ARCHIVE" | cut -f1)${RESET}" echo echo "${CYAN}Pour transférer vers le nouveau serveur :${RESET}" echo " scp \"$ARCHIVE\" user@nouveau-serveur:/chemin/vers/e-cosplay/var/backups/" echo " ssh user@nouveau-serveur 'cd /chemin/vers/e-cosplay && ./restore.sh \"var/backups/$(basename "$ARCHIVE")\"'"