#!/usr/bin/env bash set -euo pipefail CONFIG_FILE="/opt/appfactory/config/appfactory.env" if [ ! -f "$CONFIG_FILE" ]; then echo "Missing config file: $CONFIG_FILE" exit 1 fi source "$CONFIG_FILE" FORCE="false" BACKUP_FILE="" if [ "${1:-}" = "--force" ]; then FORCE="true" BACKUP_FILE="${2:-}" else BACKUP_FILE="${1:-}" fi if [ "$FORCE" != "true" ]; then echo "REFUSING TO RUN RESTORE." echo "" echo "Restore overwrites:" echo "- $APPFACTORY_DIR" echo "- $WORKSPACE_DIR" echo "- Gitea data" echo "- Registry data" echo "- deployed apps" echo "- catalog" echo "- gateway config" echo "" echo "Usage:" echo " sudo ./restore-appfactory.sh --force /path/to/backup.tar.gz" exit 1 fi if [ -z "$BACKUP_FILE" ]; then echo "Missing backup file." echo "Usage:" echo " sudo ./restore-appfactory.sh --force /path/to/backup.tar.gz" exit 1 fi if [ ! -f "$BACKUP_FILE" ]; then echo "Backup file not found:" echo "$BACKUP_FILE" exit 1 fi echo "======================================================" echo "DANGEROUS OPERATION: APPFACTORY RESTORE" echo "======================================================" echo "" echo "Backup file:" echo " $BACKUP_FILE" echo "" echo "This will overwrite:" echo " $APPFACTORY_DIR" echo " $WORKSPACE_DIR" echo "" echo "Before restore, an emergency backup will be created." echo "" read -r -p "Type RESTORE to continue: " CONFIRM if [ "$CONFIRM" != "RESTORE" ]; then echo "Cancelled." exit 1 fi TIMESTAMP="$(date +%Y%m%d-%H%M%S)" EMERGENCY_BACKUP_DIR="${BACKUP_DIR:-/opt/appfactory/backups}" EMERGENCY_BACKUP_FILE="$EMERGENCY_BACKUP_DIR/emergency-before-restore-$TIMESTAMP.tar.gz" mkdir -p "$EMERGENCY_BACKUP_DIR" echo "" echo "Creating emergency backup:" echo "$EMERGENCY_BACKUP_FILE" tar -czf "$EMERGENCY_BACKUP_FILE" \ "$APPFACTORY_DIR" \ "$WORKSPACE_DIR" \ 2>/tmp/appfactory-emergency-backup-errors.log || { echo "Emergency backup failed." echo "Errors:" cat /tmp/appfactory-emergency-backup-errors.log exit 1 } echo "" echo "Emergency backup created." echo "" echo "Stopping AppFactory containers..." if [ -d "$APPFACTORY_DIR/deploy" ]; then cd "$APPFACTORY_DIR/deploy" docker compose -f docker-compose.yml -f apps-compose.yml down || true fi echo "" echo "Restoring files from backup..." tar -xzf "$BACKUP_FILE" -C / echo "" echo "Fixing ownership..." chown -R "$APP_USER:$APP_GROUP" "$APPFACTORY_DIR" chown -R "$APP_USER:$APP_GROUP" "$WORKSPACE_DIR" if [ -f "$APPFACTORY_DIR/config/appfactory.env" ]; then chmod 600 "$APPFACTORY_DIR/config/appfactory.env" fi echo "" echo "Starting core services..." cd "$APPFACTORY_DIR/deploy" docker compose -f docker-compose.yml up -d echo "" echo "Regenerating generated files..." TOOLS_DIR="$WORKSPACE_DIR/appfactory-tools" if [ ! -d "$TOOLS_DIR" ]; then echo "Missing tools directory:" echo "$TOOLS_DIR" echo "" echo "Core services started, but app rebuild skipped." exit 0 fi cd "$TOOLS_DIR" if [ -x "./scripts/generate-apps-compose.sh" ]; then ./scripts/generate-apps-compose.sh fi if [ -x "./scripts/generate-caddyfile.sh" ]; then ./scripts/generate-caddyfile.sh fi if [ -x "./scripts/generate-apps-page.sh" ]; then ./scripts/generate-apps-page.sh fi echo "" echo "Rebuilding apps from workspace..." for app_dir in "$WORKSPACE_DIR"/*; do if [ -f "$app_dir/app.yml" ]; then app_id="$(basename "$app_dir")" echo "" echo "Rebuilding app: $app_id" if [ -x "$TOOLS_DIR/scripts/deploy-app.sh" ]; then "$TOOLS_DIR/scripts/deploy-app.sh" "$app_id" || { echo "WARNING: failed to rebuild app: $app_id" } fi fi done echo "" echo "Final compose up..." cd "$APPFACTORY_DIR/deploy" docker compose -f docker-compose.yml -f apps-compose.yml up -d echo "" echo "DONE" echo "" echo "Emergency backup:" echo "$EMERGENCY_BACKUP_FILE" echo "" echo "Check:" echo " docker ps" echo " curl http://localhost/health"