114 lines
4.4 KiB
Bash
Executable File
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)."
|