#!/bin/bash # Co-op Cloud entrypoint wrapper for the discourse/postgres image. # # discourse/postgres (https://github.com/discourse/discourse-postgres) is pgvector # plus a management layer that auto-upgrades an older cluster on boot. It does the # heavy lifting (apt-installs the old binaries, runs pg_upgrade, writes the new # cluster to the versioned PGDATA). This wrapper only fills the two gaps it leaves: # # 1. Secrets: the image reads DB_PASSWORD / POSTGRES_PASSWORD from the process # env (no *_FILE support), so inject them from the docker secret. # 2. Install user: the image runs `pg_upgrade --username="$POSTGRES_USER"` and # initdb's the new cluster with $POSTGRES_USER, but never detects the OLD # cluster's real bootstrap superuser (the install user, oid 10). pg_upgrade # aborts unless the new cluster's install-user name matches the old one. Real # deployments differ: some were bootstrapped with `postgres` as the install # user (+ a separate `discourse` app role), others with `discourse` itself. # So detect oid 10 from the old cluster and export POSTGRES_USER to match # before handing off to the image's run-postgres.sh. set -e # --- 1. secret injection ----------------------------------------------------- if [ -f /run/secrets/db_password ]; then pw="$(cat /run/secrets/db_password)" export DB_PASSWORD="$pw" export POSTGRES_PASSWORD="$pw" fi # --- 2. install-user detection (only matters on the upgrade path) ------------ NEW_MAJOR="$(postgres --version | sed -rn 's/^[^0-9]*([0-9]+).*/\1/p')" # Newest existing cluster under the data mount (same search the image uses). PGVER_FILE="$(find /var/lib/postgresql -maxdepth 3 -type f -name PG_VERSION 2>/dev/null \ | xargs -I{} sh -c 'printf "%s " "{}"; cat "{}"' \ | sort -nk2,2 | tail -n1 | awk '{print $1}')" if [ -n "$PGVER_FILE" ]; then OLD_DIR="$(dirname "$PGVER_FILE")" OLD_MAJOR="$(cat "$PGVER_FILE")" if [ "$OLD_MAJOR" != "$NEW_MAJOR" ]; then echo "cc-db-entrypoint: existing pg${OLD_MAJOR} cluster at ${OLD_DIR}, image is pg${NEW_MAJOR} -> detecting install user" OLD_BIN="/usr/lib/postgresql/${OLD_MAJOR}/bin" if [ ! -x "$OLD_BIN/pg_ctl" ]; then echo "cc-db-entrypoint: installing postgresql-${OLD_MAJOR} to read the old cluster" apt-get update apt-get install -y --no-install-recommends "postgresql-${OLD_MAJOR}" >/dev/null fi chown -R postgres "$OLD_DIR" 2>/dev/null || true # Briefly start the old cluster on a local socket only, ask it for oid 10. gosu postgres "$OLD_BIN/pg_ctl" -D "$OLD_DIR" -w \ -o "-c listen_addresses= -c unix_socket_directories=/tmp" start >/dev/null 2>&1 || true detected="" for login_role in discourse postgres; do detected="$(gosu postgres psql -h /tmp -U "$login_role" -d postgres -tAc \ 'select rolname from pg_roles where oid = 10' 2>/dev/null | tr -d '[:space:]')" [ -n "$detected" ] && break done gosu postgres "$OLD_BIN/pg_ctl" -D "$OLD_DIR" -w stop >/dev/null 2>&1 || true if [ -n "$detected" ]; then echo "cc-db-entrypoint: old cluster install user is '$detected' -> POSTGRES_USER=$detected" export POSTGRES_USER="$detected" else echo "cc-db-entrypoint: WARNING could not detect old install user; leaving POSTGRES_USER=${POSTGRES_USER:-}" fi # pg_upgrade refuses to run if the old and new clusters disagree on data # checksums. PostgreSQL 18's initdb enables checksums by default, but the # older clusters in this recipe's lineage (pg13-17) were created without # them, so initdb the new cluster to match. Default to OFF (the lineage # reality) and only enable when the old cluster positively reports them on. csum="" if [ -x "$OLD_BIN/pg_controldata" ]; then csum="$("$OLD_BIN/pg_controldata" "$OLD_DIR" 2>/dev/null \ | awk -F: '/checksum version/{gsub(/[^0-9]/,"",$2); print $2}')" fi if [ "$csum" = "1" ]; then echo "cc-db-entrypoint: old cluster data checksums ON -> initdb new cluster --data-checksums" export POSTGRES_INITDB_ARGS="${POSTGRES_INITDB_ARGS:+$POSTGRES_INITDB_ARGS }--data-checksums" else echo "cc-db-entrypoint: old cluster data checksums OFF (version='${csum:-unknown}') -> initdb new cluster --no-data-checksums" export POSTGRES_INITDB_ARGS="${POSTGRES_INITDB_ARGS:+$POSTGRES_INITDB_ARGS }--no-data-checksums" fi fi fi exec run-postgres.sh postgres