ce-infra/scripts/restore.sh

114 lines
4.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# restore.sh — Restore Cloud Elves services from a backup
#
# Usage: ./scripts/restore.sh <backup_file>
#
# Prerequisites:
# - Target server already bootstrapped: ansible-playbook playbooks/bootstrap.yml
# - Services already deployed: ansible-playbook playbooks/deploy.yml
# - This script stops services, replaces data, and restarts
#
# Run from the ce-infra repo root directory.
# Requires SSH access to box.cloud-elves.eu as root.
set -euo pipefail
if [ $# -eq 0 ]; then
echo "Usage: $0 <backup_file>"
echo "Example: $0 ./backups/ce-backup-20260317-180000.tar"
exit 1
fi
BACKUP_FILE="$1"
HOST="root@box.cloud-elves.eu"
SSH_KEY="${SSH_KEY:-$HOME/.ssh/id_ed25519_ce}"
SSH="ssh -i $SSH_KEY $HOST"
SCP="scp -i $SSH_KEY"
REMOTE_TMP="/tmp/ce-restore"
if [ ! -f "${BACKUP_FILE}" ]; then
echo "Error: Backup file not found: ${BACKUP_FILE}"
exit 1
fi
echo "=== Cloud Elves Restore ==="
echo "Backup: ${BACKUP_FILE}"
echo ""
echo "Contents:"
tar tf "${BACKUP_FILE}" | sed 's/^/ /'
echo ""
echo "WARNING: This will stop all services and replace their data."
echo "Press Enter to continue, Ctrl+C to abort."
read -r
# Upload backup
echo "[1/7] Uploading backup to server..."
$SSH "mkdir -p ${REMOTE_TMP}"
$SCP "${BACKUP_FILE}" "${HOST}:${REMOTE_TMP}/backup.tar"
$SSH "cd ${REMOTE_TMP} && tar xf backup.tar && rm backup.tar"
# Stop all services
echo "[2/7] Stopping all services..."
$SSH "cd /opt/services && docker compose down"
# Restore LLDAP volume
echo "[3/7] Restoring LLDAP (user directory)..."
$SSH "docker volume rm services_lldap-data 2>/dev/null || true && docker volume create services_lldap-data"
$SSH "docker run --rm -v services_lldap-data:/data -v ${REMOTE_TMP}:/backup alpine tar xzf /backup/lldap-data.tar.gz -C /data"
# Restore Dex volume
echo "[4/7] Restoring Dex (auth database)..."
$SSH "docker volume rm services_dex-data 2>/dev/null || true && docker volume create services_dex-data"
$SSH "docker run --rm -v services_dex-data:/dex -v ${REMOTE_TMP}:/backup alpine tar xzf /backup/dex-data.tar.gz -C /dex"
# Restore Gitea data volume
echo "[5/7] Restoring Gitea (data + database)..."
$SSH "docker volume rm services_gitea-data 2>/dev/null || true && docker volume create services_gitea-data"
$SSH "docker run --rm -v services_gitea-data:/data -v ${REMOTE_TMP}:/backup alpine tar xzf /backup/gitea-data.tar.gz -C /data"
# Start databases only so we can restore into them
$SSH "cd /opt/services && docker compose up -d gitea-db outline-db"
echo " Waiting for databases to start..."
sleep 5
# Restore Gitea database
$SSH "cd /opt/services && docker compose exec -T gitea-db dropdb -U gitea --if-exists gitea"
$SSH "cd /opt/services && docker compose exec -T gitea-db createdb -U gitea gitea"
$SSH "gunzip -c ${REMOTE_TMP}/gitea-db.sql.gz | docker compose -f /opt/services/docker-compose.yml exec -T gitea-db psql -U gitea gitea"
# Restore Outline data volume
echo "[6/7] Restoring Outline (uploads + database)..."
$SSH "docker volume rm services_outline-data 2>/dev/null || true && docker volume create services_outline-data"
$SSH "docker run --rm -v services_outline-data:/data -v ${REMOTE_TMP}:/backup alpine tar xzf /backup/outline-data.tar.gz -C /data"
# Restore Outline database
$SSH "cd /opt/services && docker compose exec -T outline-db dropdb -U outline --if-exists outline"
$SSH "cd /opt/services && docker compose exec -T outline-db createdb -U outline outline"
$SSH "gunzip -c ${REMOTE_TMP}/outline-db.sql.gz | docker compose -f /opt/services/docker-compose.yml exec -T outline-db psql -U outline outline"
# Start everything
echo "[7/7] Starting all services..."
$SSH "cd /opt/services && docker compose up -d"
# Wait for Gitea and regenerate hooks
echo " Waiting for services to start..."
sleep 10
echo " Regenerating Gitea hooks..."
$SSH "cd /opt/services && docker compose exec -T -u git gitea gitea admin regenerate hooks" || echo " (no repos to regenerate hooks for)"
# Clean up
$SSH "rm -rf ${REMOTE_TMP}"
echo ""
echo "=== Restore complete ==="
echo ""
echo "Please verify:"
echo " - https://ldap.cloud-elves.eu — LLDAP (users should be there)"
echo " - https://auth.cloud-elves.eu — Dex (SSO should work)"
echo " - https://git.cloud-elves.eu — Gitea (repos, users)"
echo " - https://docs.cloud-elves.eu — Outline (documents)"
echo " - https://cloud-elves.eu — Static site (deploy via rsync separately)"
echo ""
echo "Note: Users will need to log in again (SSO sessions were reset)."