Files
carmanagement/production/scripts/docker-prod-restore.sh
root 7ff2dbb139
Build & Deploy / Build & Push Docker Image (push) Successful in 2m55s
Test / Type Check (all packages) (push) Successful in 54s
Build & Deploy / Deploy to VPS (push) Successful in 4s
Test / API Unit Tests (push) Failing after 48s
Test / Homepage Unit Tests (push) Successful in 43s
Test / Storefront Unit Tests (push) Failing after 40s
Test / Admin Unit Tests (push) Successful in 40s
Test / Dashboard Unit Tests (push) Failing after 42s
Test / API Integration Tests (push) Successful in 1m0s
chore: wire Carplace into dev and production stacks
2026-07-02 18:15:42 -04:00

115 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
BACKUP_DIR="${1:-}"
CONFIRM_FLAG="${2:-}"
if [[ -z "${BACKUP_DIR}" ]]; then
echo "Usage: bash scripts/docker-prod-restore.sh <backup-dir> --yes" >&2
exit 1
fi
if [[ "${CONFIRM_FLAG}" != "--yes" ]]; then
echo "Restore is destructive and will overwrite the production database and uploaded files." >&2
echo "Re-run with: bash scripts/docker-prod-restore.sh ${BACKUP_DIR} --yes" >&2
exit 1
fi
if [[ ! -d "${BACKUP_DIR}" ]]; then
echo "Backup directory not found: ${BACKUP_DIR}" >&2
exit 1
fi
if [[ ! -f "${BACKUP_DIR}/postgres.dump" ]]; then
echo "Missing database backup: ${BACKUP_DIR}/postgres.dump" >&2
exit 1
fi
if [[ ! -f "${BACKUP_DIR}/api-uploads.tar.gz" ]]; then
echo "Missing uploads backup: ${BACKUP_DIR}/api-uploads.tar.gz" >&2
exit 1
fi
ensure_env_file
ensure_traefik_network
RAW_VOLUME_DIR="${BACKUP_DIR}/volumes"
SKIP_RAW_RESTORE_VOLUMES=(
"${PROJECT_NAME}_api_uploads"
"${PROJECT_NAME}_postgres_prod_data"
)
echo "Stopping application services before restore..."
prod_compose stop api homepage carplace dashboard admin pgmanage >/dev/null || true
prod_compose stop redis >/dev/null || true
stop_traefik
echo "Ensuring PostgreSQL is running..."
prod_compose up -d postgres >/dev/null
echo "Waiting for PostgreSQL..."
until prod_compose exec -T postgres sh -lc 'pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"' >/dev/null 2>&1; do
sleep 2
done
echo "Restoring PostgreSQL database..."
cat "${BACKUP_DIR}/postgres.dump" | prod_compose exec -T postgres sh -lc '
pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists --no-owner --no-privileges
'
echo "Restoring uploaded files..."
cat "${BACKUP_DIR}/api-uploads.tar.gz" | prod_compose run --rm --no-deps api bash -lc '
mkdir -p /var/lib/rentaldrivego/storage
find /var/lib/rentaldrivego/storage -mindepth 1 -delete
tar -xzf - -C /var/lib/rentaldrivego/storage
'
if [[ -f "${BACKUP_DIR}/traefik-letsencrypt.tar.gz" ]]; then
echo "Restoring Traefik certificates..."
cat "${BACKUP_DIR}/traefik-letsencrypt.tar.gz" | traefik_compose run --rm traefik sh -lc '
mkdir -p /letsencrypt
find /letsencrypt -mindepth 1 -delete
tar -xzf - -C /letsencrypt
chmod 600 /letsencrypt/acme.json 2>/dev/null || true
'
fi
if [[ -d "${RAW_VOLUME_DIR}" ]]; then
echo "Restoring raw Docker volume archives..."
for archive_path in "${RAW_VOLUME_DIR}"/*.tar.gz; do
[[ -e "${archive_path}" ]] || continue
volume_name="$(basename "${archive_path}" .tar.gz)"
skip_volume=false
for managed_volume in "${SKIP_RAW_RESTORE_VOLUMES[@]}"; do
if [[ "${volume_name}" == "${managed_volume}" ]]; then
skip_volume=true
break
fi
done
if [[ "${skip_volume}" == true ]]; then
echo "Skipping raw restore for ${volume_name}; handled by service-aware restore."
continue
fi
if ! docker_volume_exists "${volume_name}"; then
echo "Creating missing volume ${volume_name}"
docker volume create "${volume_name}" >/dev/null
fi
echo " - ${volume_name}"
restore_named_volume "${volume_name}" "${archive_path}"
done
fi
echo "Starting production services..."
start_traefik
start_prod_services
echo "Restore complete from ${BACKUP_DIR}"