#!/bin/sh set -eu ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) ENV_FILE="$ROOT/.env" TEST_IMAGE="${TEST_IMAGE:-who-need-help:test}" if [ ! -f "$ENV_FILE" ]; then echo "Missing $ENV_FILE. Copy .env.example to .env first." >&2 exit 1 fi for command in docker openssl perl; do if ! command -v "$command" >/dev/null 2>&1; then echo "Required command is unavailable: $command" >&2 exit 1 fi done set -a # shellcheck source=/dev/null . "$ENV_FILE" set +a : "${POSTGRES_USER:?POSTGRES_USER is missing from .env}" : "${POSTGRES_DB:?POSTGRES_DB is missing from .env}" case "$POSTGRES_USER" in *[!A-Za-z0-9_]* | "") echo "POSTGRES_USER contains unsupported characters." >&2; exit 1 ;; esac case "$POSTGRES_DB" in *[!A-Za-z0-9_]* | "") echo "POSTGRES_DB contains unsupported characters." >&2; exit 1 ;; esac generate_phoenix_secret() { docker run --rm "$TEST_IMAGE" mix phx.gen.secret } new_secret_key_base=$(generate_phoenix_secret) new_handover_secret=$(generate_phoenix_secret) new_release_cookie=$(generate_phoenix_secret) new_postgres_password=$(openssl rand -hex 32) new_database_url="ecto://${POSTGRES_USER}:${new_postgres_password}@db/${POSTGRES_DB}" tmp_env=$(mktemp "${ENV_FILE}.rotate.XXXXXX") trap 'rm -f "$tmp_env"' EXIT HUP INT TERM chmod 600 "$tmp_env" NEW_SECRET_KEY_BASE=$new_secret_key_base \ NEW_HANDOVER_SECRET=$new_handover_secret \ NEW_RELEASE_COOKIE=$new_release_cookie \ NEW_POSTGRES_PASSWORD=$new_postgres_password \ NEW_DATABASE_URL=$new_database_url \ perl -pe ' s/^SECRET_KEY_BASE=.*/SECRET_KEY_BASE=$ENV{NEW_SECRET_KEY_BASE}/; s/^HANDOVER_SECRET=.*/HANDOVER_SECRET=$ENV{NEW_HANDOVER_SECRET}/; s/^RELEASE_COOKIE=.*/RELEASE_COOKIE=$ENV{NEW_RELEASE_COOKIE}/; s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$ENV{NEW_POSTGRES_PASSWORD}/; s/^DATABASE_URL=.*/DATABASE_URL=$ENV{NEW_DATABASE_URL}/; ' "$ENV_FILE" >"$tmp_env" printf "ALTER ROLE \"%s\" WITH PASSWORD '%s';\n" \ "$POSTGRES_USER" "$new_postgres_password" | docker compose --project-directory "$ROOT" exec -T db \ psql --set ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \ >/dev/null mv "$tmp_env" "$ENV_FILE" chmod 600 "$ENV_FILE" trap - EXIT HUP INT TERM echo "Local application and PostgreSQL secrets rotated without printing their values." echo "Run docker compose up -d --wait to apply the new application environment."