75 lines
2.9 KiB
Bash
Executable File
75 lines
2.9 KiB
Bash
Executable File
#!/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
|