Files
youtube-studio-flow/scripts/migrate-local-db-to-server.sh
T
devil 0ac1ca3b08 fix(scripts): disable MSYS path translation in migrate-local-db-to-server.sh
pg_dump inside the container failed with "could not open output file
C:/Users/.../Temp/studioflow_migration_....dump" - Git Bash/MSYS was
rewriting the /tmp/... argument into a Windows path before handing it
to docker.exe, even though it's meant to be interpreted inside the
Linux container. MSYS_NO_PATHCONV=1 stops that translation.
2026-08-11 17:08:09 +02:00

91 lines
4.1 KiB
Bash

#!/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
# Git Bash/MSYS auto-translates POSIX-looking path args (e.g. /tmp/foo) into
# Windows paths before handing them to docker.exe - but these paths are meant
# to be interpreted inside the Linux container, not on the Windows host.
export MSYS_NO_PATHCONV=1
# ── 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."