Skip to content

Commit 3c16de2

Browse files
committed
Add Dokku restore helper
1 parent 282ce61 commit 3c16de2

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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

Comments
 (0)