Files
orion/scripts/restore.sh
Samir Boulahtit ef7187b508
Some checks failed
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / ruff (push) Successful in 7s
CI / validate (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
feat: add automated backups and Prometheus/Grafana monitoring stack (Steps 17-18)
Backups: pg_dump scripts with daily/weekly rotation and Cloudflare R2 offsite sync.
Monitoring: Prometheus, Grafana, node-exporter, cAdvisor in docker-compose; /metrics
endpoint activated via prometheus_client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 22:40:08 +01:00

153 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# scripts/restore.sh — Database restore helper for Orion and Gitea
#
# Usage:
# bash scripts/restore.sh orion ~/backups/orion/daily/orion_20260214_030000.sql.gz
# bash scripts/restore.sh gitea ~/backups/gitea/daily/gitea_20260214_030000.sql.gz
#
# What it does:
# 1. Stops app containers (keeps DB running)
# 2. Drops and recreates the database
# 3. Restores from the .sql.gz backup
# 4. Runs Alembic migrations (Orion only)
# 5. Restarts all containers
set -euo pipefail
# =============================================================================
# Configuration
# =============================================================================
ORION_APP_DIR="${HOME}/apps/orion"
# =============================================================================
# Functions
# =============================================================================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
usage() {
echo "Usage: $0 <target> <backup-file>"
echo ""
echo " target: 'orion' or 'gitea'"
echo " backup-file: path to .sql.gz file"
echo ""
echo "Examples:"
echo " $0 orion ~/backups/orion/daily/orion_20260214_030000.sql.gz"
echo " $0 gitea ~/backups/gitea/daily/gitea_20260214_030000.sql.gz"
exit 1
}
restore_orion() {
local backup_file="$1"
local container="orion-db-1"
local db_name="orion_db"
local db_user="orion_user"
log "=== Restoring Orion database ==="
# Stop app containers (keep DB running)
log "Stopping Orion app containers..."
cd "${ORION_APP_DIR}"
docker compose --profile full stop api celery-worker celery-beat flower 2>/dev/null || true
# Drop and recreate database
log "Dropping and recreating ${db_name}..."
docker exec "${container}" psql -U "${db_user}" -d postgres -c \
"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${db_name}' AND pid <> pg_backend_pid();" 2>/dev/null || true
docker exec "${container}" dropdb -U "${db_user}" --if-exists "${db_name}"
docker exec "${container}" createdb -U "${db_user}" "${db_name}"
# Restore
log "Restoring from ${backup_file}..."
gunzip -c "${backup_file}" | docker exec -i "${container}" psql -U "${db_user}" -d "${db_name}" --quiet
# Run migrations
log "Running Alembic migrations..."
docker compose --profile full start api 2>/dev/null || \
docker compose --profile full up -d api
sleep 5 # Wait for API container to be ready
docker compose --profile full exec -e PYTHONPATH=/app api python -m alembic upgrade heads
# Restart all
log "Restarting all services..."
docker compose --profile full up -d
log "=== Orion restore complete ==="
}
restore_gitea() {
local backup_file="$1"
local container="gitea-db"
local db_name="gitea"
local db_user="gitea"
local gitea_dir="${HOME}/gitea"
log "=== Restoring Gitea database ==="
# Stop Gitea container (keep DB running)
log "Stopping Gitea..."
cd "${gitea_dir}"
docker compose stop gitea 2>/dev/null || true
# Drop and recreate database
log "Dropping and recreating ${db_name}..."
docker exec "${container}" psql -U "${db_user}" -d postgres -c \
"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${db_name}' AND pid <> pg_backend_pid();" 2>/dev/null || true
docker exec "${container}" dropdb -U "${db_user}" --if-exists "${db_name}"
docker exec "${container}" createdb -U "${db_user}" "${db_name}"
# Restore
log "Restoring from ${backup_file}..."
gunzip -c "${backup_file}" | docker exec -i "${container}" psql -U "${db_user}" -d "${db_name}" --quiet
# Restart Gitea
log "Restarting Gitea..."
docker compose up -d
log "=== Gitea restore complete ==="
}
# =============================================================================
# Main
# =============================================================================
if [ $# -lt 2 ]; then
usage
fi
TARGET="$1"
BACKUP_FILE="$2"
# Validate backup file
if [ ! -f "${BACKUP_FILE}" ]; then
log "ERROR: Backup file not found: ${BACKUP_FILE}"
exit 1
fi
if [[ ! "${BACKUP_FILE}" == *.sql.gz ]]; then
log "ERROR: Expected a .sql.gz file, got: ${BACKUP_FILE}"
exit 1
fi
# Confirm
log "WARNING: This will DROP and RECREATE the ${TARGET} database!"
log "Backup file: ${BACKUP_FILE}"
read -rp "Continue? (y/N) " confirm
if [[ "${confirm}" != [yY] ]]; then
log "Aborted."
exit 0
fi
case "${TARGET}" in
orion)
restore_orion "${BACKUP_FILE}"
;;
gitea)
restore_gitea "${BACKUP_FILE}"
;;
*)
log "ERROR: Unknown target '${TARGET}'. Use 'orion' or 'gitea'."
usage
;;
esac