#!/usr/bin/env bash # Fix B: set the Postgres role password to match POSTGRES_PASSWORD in .env (no volume wipe). # # Works when `psql` inside the container can connect to the server over the Unix socket # without a password (common for the official postgres image’s local/trust rules). The app # role (POSTGRES_USER) can change its own password, or you can set POSTGRES_SUPERUSER to # connect as a different superuser (e.g. postgres) when that role still exists. # # Usage (repo root, stack can be up): # ./scripts/sync-postgres-app-password.sh # # Optional .env entries: # POSTGRES_SUPERUSER=postgres # DB role to connect as (default: same as POSTGRES_USER) # set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" COMPOSE=(docker compose --env-file "${ROOT}/.env" -f "${ROOT}/docker-compose.prod.yml") cd "$ROOT" ENV_FILE="${ENV_FILE:-$ROOT/.env}" if [[ ! -f "$ENV_FILE" ]]; then printf 'Missing %s\n' "$ENV_FILE" >&2 exit 1 fi while IFS= read -r line || [[ -n "$line" ]]; do line="${line%$'\r'}" [[ "$line" =~ ^[[:space:]]*# ]] && continue [[ "$line" =~ ^[[:space:]]*$ ]] && continue if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then key="${BASH_REMATCH[1]}" val="${BASH_REMATCH[2]}" val="${val#"${val%%[![:space:]]*}"}" val="${val%"${val##*[![:space:]]}"}" export "${key}=${val}" fi done <"$ENV_FILE" if [[ -z "${POSTGRES_USER:-}" || -z "${POSTGRES_PASSWORD:-}" ]]; then printf 'POSTGRES_USER and POSTGRES_PASSWORD must be set in %s\n' "$ENV_FILE" >&2 exit 1 fi # SQL string literal: escape single quotes per PostgreSQL rules (' -> '') sql_escape_literal() { printf '%s' "$1" | sed "s/'/''/g" } # Double-quoted identifier: " -> " sql_escape_ident() { printf '%s' "$1" | sed 's/"/""/g' } conn_role="${POSTGRES_SUPERUSER:-$POSTGRES_USER}" pass_esc="$(sql_escape_literal "$POSTGRES_PASSWORD")" user_ident="$(sql_escape_ident "$POSTGRES_USER")" sql="ALTER ROLE \"${user_ident}\" WITH PASSWORD '${pass_esc}';" printf '→ Connecting as Postgres role %q (inside container), updating password for role %q…\n' "$conn_role" "$POSTGRES_USER" if "${COMPOSE[@]}" exec -T postgres psql -U "$conn_role" -d postgres -v ON_ERROR_STOP=1 -c "$sql"; then printf 'OK — role %q password now matches POSTGRES_PASSWORD in .env.\nRestart be0 if it was crash-looping:\n %s restart be0\n' "$POSTGRES_USER" "${COMPOSE[*]}" exit 0 fi printf '\nThat failed. Common causes:\n' >&2 printf ' • This cluster has no local "trust" for psql — supply the current password and run manually:\n' >&2 printf ' PGPASSWORD="(old)" docker compose --env-file .env -f docker-compose.prod.yml exec -T postgres \\\n' >&2 printf ' psql -U %q -d postgres -c "ALTER ROLE ..."\n' "$POSTGRES_USER" >&2 printf ' • Role %q is not a superuser and you connected as the wrong POSTGRES_SUPERUSER — set POSTGRES_SUPERUSER in .env to a superuser that exists.\n' "$POSTGRES_USER" >&2 printf ' • See docs/deploy-production-docker.md §3\n' >&2 exit 1