#!/usr/bin/env bash set -Eeuo pipefail umask 077 SCRIPT_DIRECTORY="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" PROJECT_ROOT="$(cd -- "$SCRIPT_DIRECTORY/.." && pwd -P)" FORCE=0 usage() { printf '%s\n' "Usage: $0 [--force] BACKUP.tar.gz" >&2 } if [[ "${1:-}" == "--force" ]]; then FORCE=1 shift fi [[ $# -eq 1 ]] || { usage; exit 2; } archive_argument="$1" archive_directory="$(cd -- "$(dirname -- "$archive_argument")" && pwd -P)" archive_path="$archive_directory/$(basename -- "$archive_argument")" [[ -f "$archive_path" ]] || { printf '%s\n' "The backup archive does not exist." >&2; exit 1; } command -v tar >/dev/null 2>&1 || { printf '%s\n' "tar is required to restore a backup." >&2; exit 1; } if ((FORCE == 0)); then read -r -p "Restore will overwrite the current .env and runtime secrets. Continue? [y/N] " restore_answer case "${restore_answer,,}" in y|yes) ;; *) printf '%s\n' "Restore cancelled." >&2; exit 1 ;; esac fi while IFS= read -r archive_entry; do normalized_entry="${archive_entry%/}" case "$normalized_entry" in config|config/environment.env|secrets|secrets/calendar_ical_urls.json|secrets/organizer_access_token.txt|manifest.txt) ;; *) printf '%s\n' "The archive contains an unexpected path and will not be restored." >&2; exit 1 ;; esac done < <(tar -tzf "$archive_path") staging_path="$(mktemp -d "$PROJECT_ROOT/.restore-staging-XXXXXXXX")" cleanup_staging() { [[ -n "${staging_path:-}" && -d "$staging_path" ]] && rm -rf -- "$staging_path" } trap cleanup_staging EXIT HUP INT TERM tar -xzf "$archive_path" -C "$staging_path" for required_file in \ "$staging_path/config/environment.env" \ "$staging_path/secrets/calendar_ical_urls.json" \ "$staging_path/secrets/organizer_access_token.txt"; do [[ -f "$required_file" && ! -L "$required_file" ]] || { printf '%s\n' "The archive is missing a required regular file." >&2 exit 1 } done mkdir -p -- "$PROJECT_ROOT/secrets" cp -- "$staging_path/config/environment.env" "$PROJECT_ROOT/.env" cp -- "$staging_path/secrets/calendar_ical_urls.json" "$PROJECT_ROOT/secrets/calendar_ical_urls.json" cp -- "$staging_path/secrets/organizer_access_token.txt" "$PROJECT_ROOT/secrets/organizer_access_token.txt" chmod 600 -- "$PROJECT_ROOT/.env" "$PROJECT_ROOT/secrets/calendar_ical_urls.json" "$PROJECT_ROOT/secrets/organizer_access_token.txt" rm -rf -- "$staging_path" staging_path="" trap - EXIT HUP INT TERM printf '%s\n' "Configuration restored. Restart with: docker compose up -d --build"