#!/bin/sh # Ripristino di un backup creato da backup.sh. Sostituisce COMPLETAMENTE i due database e i file caricati. # Prima fermare chi usa i database: # docker compose -f docker-compose.prod.yml stop api medusa public # docker compose -f docker-compose.prod.yml run --rm restore # docker compose -f docker-compose.prod.yml up -d --wait set -eu ID="${1:-}" if [ -z "$ID" ]; then echo "Uso: restore . Backup disponibili:" >&2 ls -1 /backups | grep -E '^[0-9]+T[0-9]+Z$' >&2 || echo " (nessuno)" >&2 exit 2 fi if [ "$ID" = "latest" ]; then ID="$(ls -1 /backups | grep -E '^[0-9]+T[0-9]+Z$' | sort | tail -n 1)" [ -n "$ID" ] || { echo "Nessun backup in /backups" >&2; exit 1; } fi SRC="/backups/$ID" [ -d "$SRC" ] || { echo "Backup $SRC inesistente" >&2; exit 1; } log() { echo "[restore $(date -u +%H:%M:%S)] $*"; } log "verifica checksum di $ID" (cd "$SRC" && sha256sum -c SHA256SUMS) # Nessuna connessione degli utenti applicativi: API e Medusa devono essere ferme ACTIVE="$(psql -d postgres -tA -v ON_ERROR_STOP=1 \ -c "SELECT count(*) FROM pg_stat_activity WHERE usename IN ('$APP_DB_USER', '$MEDUSA_DB_USER')")" if [ "$ACTIVE" != "0" ]; then echo "Ci sono $ACTIVE connessioni di $APP_DB_USER/$MEDUSA_DB_USER: fermare prima api, medusa e public" >&2 exit 1 fi restore_db() { db="$1"; owner="$2"; dump="$3" log "ricreo il database $db (proprietario $owner)" psql -d postgres -v ON_ERROR_STOP=1 -q \ -c "DROP DATABASE IF EXISTS \"$db\" WITH (FORCE)" \ -c "CREATE DATABASE \"$db\" OWNER \"$owner\" ENCODING 'UTF8' TEMPLATE template0" \ -c "REVOKE ALL ON DATABASE \"$db\" FROM PUBLIC" # Da superuser: ricrea anche le estensioni (postgis, vector, …) e mantiene i proprietari originali log "pg_restore $dump → $db" pg_restore --exit-on-error --dbname="$db" "$SRC/$dump" } restore_db "$APP_DB_NAME" "$APP_DB_USER" app.dump restore_db "$MEDUSA_DB_NAME" "$MEDUSA_DB_USER" medusa.dump restore_files() { dir="$1"; archive="$2" log "ripristino $dir da $archive" # Svuota il contenuto ma NON le cartelle di primo livello (public/, private/): Caddy monta uploads/public # con un subpath, e una cartella ricreata non sarebbe più quella montata (file serviti come 404) find "$dir" -mindepth 1 -maxdepth 1 ! -type d -delete find "$dir" -mindepth 2 -delete tar -C "$dir" -xzpf "$SRC/$archive" } restore_files /data/uploads uploads.tar.gz restore_files /data/medusa-files medusa-files.tar.gz log "ripristino di $ID completato: riavviare i servizi (docker compose -f docker-compose.prod.yml up -d --wait)"