#!/bin/bash # restore.sh — decrypt and restore a backup # Usage: # docker compose exec backend bash scripts/restore.sh # docker compose exec backend bash scripts/restore.sh --list set -euo pipefail BACKUP_DIR="${BACKUP_DIR:-/app/backups}" if [ "${1:-}" = "--list" ]; then echo "[restore] Available backups in ${BACKUP_DIR}:" find "${BACKUP_DIR}" -name "*.sql.gz.gpg" -printf " %f (%s bytes)\n" | sort -r exit 0 fi if [ -z "${1:-}" ]; then echo "Usage: restore.sh " echo " restore.sh --list" exit 1 fi BACKUP_FILE="$1" # Accept bare filename or full path if [ ! -f "${BACKUP_FILE}" ] && [ -f "${BACKUP_DIR}/${BACKUP_FILE}" ]; then BACKUP_FILE="${BACKUP_DIR}/${BACKUP_FILE}" fi if [ ! -f "${BACKUP_FILE}" ]; then echo "[restore] ERROR: File not found: ${BACKUP_FILE}" >&2 exit 1 fi if [ -z "${BACKUP_PASSPHRASE:-}" ]; then echo "[restore] ERROR: BACKUP_PASSPHRASE is not set" >&2 exit 1 fi PG_URL="${DATABASE_URL/postgresql+asyncpg/postgresql}" echo "[restore] WARNING: This will overwrite the current database." echo "[restore] File: ${BACKUP_FILE}" read -r -p "[restore] Type 'yes' to continue: " CONFIRM if [ "${CONFIRM}" != "yes" ]; then echo "[restore] Aborted" exit 1 fi echo "[restore] Decrypting and restoring…" gpg --batch --yes --decrypt \ --passphrase "${BACKUP_PASSPHRASE}" \ "${BACKUP_FILE}" \ | gunzip \ | psql "${PG_URL}" echo "[restore] Done"