chore(scripts): add local-to-server DB migration script
One-time tool: dumps the local dev Postgres, scp's it to the server, and restores it into the remote postgres container over SSH - drops and recreates the target database, so it prompts for an explicit YES before touching the remote side. Connection details are placeholders (SSH_USER/SSH_HOST/etc.) filled in via env vars or direct edits, never committed with real values.
This commit is contained in:
@@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# One-time migration: dump the local dev Postgres and restore it into the
|
||||||
|
# server's Postgres over SSH, replacing whatever is there.
|
||||||
|
#
|
||||||
|
# DESTRUCTIVE on the target: drops and recreates the remote database.
|
||||||
|
#
|
||||||
|
# Fill in the placeholders below (or export them as env vars before running),
|
||||||
|
# then run from the project root: bash scripts/migrate-local-db-to-server.sh
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# - Local Postgres running: cd infrastructure && docker compose up -d postgres redis
|
||||||
|
# - SSH access to the server
|
||||||
|
# - The remote postgres container's name (find it with `docker ps` on the
|
||||||
|
# server, or check the container list in Portainer for your stack - it'll
|
||||||
|
# be something like <stack-name>-postgres-1)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Fill these in ──────────────────────────────────────────────────────────
|
||||||
|
SSH_USER="${SSH_USER:-dummyuser}"
|
||||||
|
SSH_HOST="${SSH_HOST:-dummy.server.example}"
|
||||||
|
SSH_PORT="${SSH_PORT:-22}"
|
||||||
|
REMOTE_POSTGRES_CONTAINER="${REMOTE_POSTGRES_CONTAINER:-studioflow-postgres-1}"
|
||||||
|
REMOTE_POSTGRES_USER="${REMOTE_POSTGRES_USER:-studioflow}"
|
||||||
|
REMOTE_POSTGRES_DB="${REMOTE_POSTGRES_DB:-studioflow}"
|
||||||
|
# ────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
LOCAL_DB_USER="studioflow"
|
||||||
|
LOCAL_DB_NAME="studioflow"
|
||||||
|
DUMP_FILE="studioflow_migration_$(date +%Y%m%d_%H%M%S).dump"
|
||||||
|
|
||||||
|
echo "==> Finding local Postgres container"
|
||||||
|
LOCAL_PG_CONTAINER=$(docker ps --format '{{.Names}}' | grep -i postgres | head -1)
|
||||||
|
if [ -z "$LOCAL_PG_CONTAINER" ]; then
|
||||||
|
echo "No running local postgres container found. Start it first:"
|
||||||
|
echo " cd infrastructure && docker compose up -d postgres redis"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " Using: $LOCAL_PG_CONTAINER"
|
||||||
|
|
||||||
|
echo "==> Dumping local database ($LOCAL_DB_NAME)"
|
||||||
|
docker exec "$LOCAL_PG_CONTAINER" pg_dump -U "$LOCAL_DB_USER" -d "$LOCAL_DB_NAME" -F c -f "/tmp/$DUMP_FILE"
|
||||||
|
docker cp "${LOCAL_PG_CONTAINER}:/tmp/$DUMP_FILE" "./$DUMP_FILE"
|
||||||
|
docker exec "$LOCAL_PG_CONTAINER" rm "/tmp/$DUMP_FILE"
|
||||||
|
echo " Dump size: $(du -h "./$DUMP_FILE" | cut -f1)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "About to overwrite the database on ${SSH_HOST} (container: ${REMOTE_POSTGRES_CONTAINER})."
|
||||||
|
read -p "Type YES to continue: " CONFIRM
|
||||||
|
if [ "$CONFIRM" != "YES" ]; then
|
||||||
|
echo "Aborted. Local dump kept at ./$DUMP_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Copying dump to server"
|
||||||
|
scp -P "$SSH_PORT" "./$DUMP_FILE" "${SSH_USER}@${SSH_HOST}:/tmp/$DUMP_FILE"
|
||||||
|
|
||||||
|
echo "==> Restoring on server"
|
||||||
|
ssh -p "$SSH_PORT" "${SSH_USER}@${SSH_HOST}" bash -s <<EOF
|
||||||
|
set -euo pipefail
|
||||||
|
echo " Copying dump into container..."
|
||||||
|
docker cp "/tmp/$DUMP_FILE" "${REMOTE_POSTGRES_CONTAINER}:/tmp/$DUMP_FILE"
|
||||||
|
|
||||||
|
echo " Terminating existing connections..."
|
||||||
|
docker exec "$REMOTE_POSTGRES_CONTAINER" psql -U "$REMOTE_POSTGRES_USER" -d postgres -c \
|
||||||
|
"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$REMOTE_POSTGRES_DB';" >/dev/null
|
||||||
|
|
||||||
|
echo " Dropping and recreating database..."
|
||||||
|
docker exec "$REMOTE_POSTGRES_CONTAINER" psql -U "$REMOTE_POSTGRES_USER" -d postgres -c \
|
||||||
|
"DROP DATABASE IF EXISTS $REMOTE_POSTGRES_DB;" >/dev/null
|
||||||
|
docker exec "$REMOTE_POSTGRES_CONTAINER" psql -U "$REMOTE_POSTGRES_USER" -d postgres -c \
|
||||||
|
"CREATE DATABASE $REMOTE_POSTGRES_DB OWNER $REMOTE_POSTGRES_USER;" >/dev/null
|
||||||
|
|
||||||
|
echo " Restoring data..."
|
||||||
|
docker exec "$REMOTE_POSTGRES_CONTAINER" pg_restore -U "$REMOTE_POSTGRES_USER" -d "$REMOTE_POSTGRES_DB" --no-owner --no-privileges "/tmp/$DUMP_FILE"
|
||||||
|
|
||||||
|
docker exec "$REMOTE_POSTGRES_CONTAINER" rm "/tmp/$DUMP_FILE"
|
||||||
|
rm "/tmp/$DUMP_FILE"
|
||||||
|
echo " Done."
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "==> Migration complete."
|
||||||
|
echo " Restart api/worker in Portainer (or they'll self-heal on next DB query)."
|
||||||
|
echo " Local dump kept at ./$DUMP_FILE - delete it once you've confirmed the server looks right."
|
||||||
Reference in New Issue
Block a user