|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +# Uploads a local db_imports/*.dump file to a Dokku host and restores it into the |
| 5 | +# specified Dokku Postgres service (production). |
| 6 | +# |
| 7 | +# Required environment variables: |
| 8 | +# PRODUCTION_SSH_HOST - e.g. root@example.com |
| 9 | +# DOKKU_POSTGRES_SERVICE - Dokku Postgres service name to restore (e.g., pwb-database) |
| 10 | +# LOCAL_DUMP_FILE - Path to local dump file (default: latest in db_imports/) |
| 11 | +# |
| 12 | +# Optional environment variables: |
| 13 | +# SSH_COMMAND - command used for ssh/scp (default: ssh) |
| 14 | +# RSYNC_RSH - overrides ssh command just for rsync/scp (default: SSH_COMMAND) |
| 15 | +# REMOTE_DUMP_PATH - path on remote server (default: /tmp/<service>.restore.dump) |
| 16 | +# BACKUP_DIR - directory containing dumps (default: db_imports) |
| 17 | +# |
| 18 | +# Usage: |
| 19 | +# ./scripts/restore_production_from_local.sh |
| 20 | +# LOCAL_DUMP_FILE=db_imports/20260106-120000-pwb-2025-db.dump ./scripts/restore_production_from_local.sh |
| 21 | +# |
| 22 | +# WARNING: This will overwrite the Dokku Postgres database. |
| 23 | + |
| 24 | +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" |
| 25 | +cd "$ROOT_DIR" |
| 26 | + |
| 27 | +: "${PRODUCTION_SSH_HOST:?Set PRODUCTION_SSH_HOST (e.g. root@example.com)}" |
| 28 | +: "${DOKKU_POSTGRES_SERVICE:?Set DOKKU_POSTGRES_SERVICE (dokku postgres service name)}" |
| 29 | + |
| 30 | +SSH_COMMAND="${SSH_COMMAND:-ssh}" |
| 31 | +RSYNC_RSH="${RSYNC_RSH:-$SSH_COMMAND}" |
| 32 | +BACKUP_DIR="${BACKUP_DIR:-$ROOT_DIR/db_imports}" |
| 33 | +REMOTE_DUMP_PATH="${REMOTE_DUMP_PATH:-/tmp/${DOKKU_POSTGRES_SERVICE}.restore.dump}" |
| 34 | + |
| 35 | +log() { |
| 36 | + printf '[%s] %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$*" |
| 37 | +} |
| 38 | + |
| 39 | +if [[ ! -d "$BACKUP_DIR" ]]; then |
| 40 | + log "Backup directory not found: $BACKUP_DIR" |
| 41 | + exit 1 |
| 42 | +fi |
| 43 | + |
| 44 | +LOCAL_DUMP_FILE="${LOCAL_DUMP_FILE:-}" |
| 45 | +if [[ -z "$LOCAL_DUMP_FILE" ]]; then |
| 46 | + LOCAL_DUMP_FILE="$(ls -1t "$BACKUP_DIR"/*.dump 2>/dev/null | head -n 1 || true)" |
| 47 | +fi |
| 48 | + |
| 49 | +if [[ -z "$LOCAL_DUMP_FILE" || ! -f "$LOCAL_DUMP_FILE" ]]; then |
| 50 | + log "No dump file found. Set LOCAL_DUMP_FILE or add dumps to $BACKUP_DIR" |
| 51 | + exit 1 |
| 52 | +fi |
| 53 | + |
| 54 | +echo "⚠️ WARNING: This will overwrite the production database on $PRODUCTION_SSH_HOST" |
| 55 | +echo " Service : $DOKKU_POSTGRES_SERVICE" |
| 56 | +echo " Dump : $LOCAL_DUMP_FILE" |
| 57 | +echo " Remote : $REMOTE_DUMP_PATH" |
| 58 | +read -p "Type RESTORE to continue: " -r CONFIRM_ONE |
| 59 | +if [[ "$CONFIRM_ONE" != "RESTORE" ]]; then |
| 60 | + log "Confirmation failed. Aborting." |
| 61 | + exit 1 |
| 62 | +fi |
| 63 | + |
| 64 | +read -p "This is destructive. Type the service name ($DOKKU_POSTGRES_SERVICE) to confirm: " -r CONFIRM_TWO |
| 65 | +if [[ "$CONFIRM_TWO" != "$DOKKU_POSTGRES_SERVICE" ]]; then |
| 66 | + log "Service confirmation mismatch. Aborting." |
| 67 | + exit 1 |
| 68 | +fi |
| 69 | + |
| 70 | +read -p "Proceed with uploading and restoring? (yes/no): " -r CONFIRM_THREE |
| 71 | +if [[ "$CONFIRM_THREE" != "yes" ]]; then |
| 72 | + log "User cancelled operation." |
| 73 | + exit 1 |
| 74 | +fi |
| 75 | + |
| 76 | +log "Uploading $LOCAL_DUMP_FILE to $PRODUCTION_SSH_HOST:$REMOTE_DUMP_PATH" |
| 77 | +RSYNC_CMD=(rsync -az) |
| 78 | +if [[ -n "${RSYNC_RSH:-}" ]]; then |
| 79 | + RSYNC_CMD+=("-e" "$RSYNC_RSH") |
| 80 | +fi |
| 81 | +"${RSYNC_CMD[@]}" "$LOCAL_DUMP_FILE" "$PRODUCTION_SSH_HOST:$REMOTE_DUMP_PATH" |
| 82 | + |
| 83 | +log "Restoring dump into dokku postgres service: $DOKKU_POSTGRES_SERVICE" |
| 84 | +$SSH_COMMAND "$PRODUCTION_SSH_HOST" "dokku postgres:import $DOKKU_POSTGRES_SERVICE < $REMOTE_DUMP_PATH" |
| 85 | + |
| 86 | +log "Cleaning up remote dump" |
| 87 | +$SSH_COMMAND "$PRODUCTION_SSH_HOST" "rm -f $REMOTE_DUMP_PATH" |
| 88 | + |
| 89 | +log "Production database restore complete" |
0 commit comments