#!/usr/bin/env bash set -Eeo pipefail file_env() { local var="$1" local fileVar="${var}_FILE" local def="${2:-}" if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then printf >&2 'error: both %s and %s are set (but are exclusive)\n' "$var" "$fileVar" exit 1 fi local val="$def" if [ "${!var:-}" ]; then val="${!var}" elif [ "${!fileVar:-}" ]; then val="$(< "${!fileVar}")" fi export "$var"="$val" unset "$fileVar" } docker_setup_env() { file_env 'POSTGRES_PASSWORD' } docker_create_db_directories() { local user; user="$(id -u)" mkdir -p "$PGDATA" chmod 00700 "$PGDATA" || : mkdir -p /var/run/postgresql || : chmod 03775 /var/run/postgresql || : if [ "$user" = '0' ]; then find "$PGDATA" \! -user postgres -exec chown postgres '{}' + find /var/run/postgresql \! -user postgres -exec chown postgres '{}' + fi } docker_init_database_dir() { local uid; uid="$(id -u)" if ! getent passwd "$uid" &> /dev/null; then local wrapper for wrapper in {/usr,}/lib{/*,}/libnss_wrapper.so; do if [ -s "$wrapper" ]; then NSS_WRAPPER_PASSWD="$(mktemp)" NSS_WRAPPER_GROUP="$(mktemp)" export LD_PRELOAD="$wrapper" NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP local gid; gid="$(id -g)" printf 'postgres:x:%s:%s:PostgreSQL:%s:/bin/false\n' "$uid" "$gid" "$PGDATA" > "$NSS_WRAPPER_PASSWD" printf 'postgres:x:%s:\n' "$gid" > "$NSS_WRAPPER_GROUP" break fi done fi eval 'initdb --username=postgres --pwfile=<(printf "%s\n" "$POSTGRES_PASSWORD") '"$POSTGRES_INITDB_ARGS"' "$@"' if [[ "${LD_PRELOAD:-}" == */libnss_wrapper.so ]]; then rm -f "$NSS_WRAPPER_PASSWD" "$NSS_WRAPPER_GROUP" unset LD_PRELOAD NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP fi } docker_temp_server_start() { NOTIFY_SOCKET= \ PGUSER="${PGUSER:-postgres}" \ pg_ctl -D "$PGDATA" \ -o "-c listen_addresses='*' -p 5432" \ -w start } docker_temp_server_stop() { PGUSER="${PGUSER:-postgres}" \ pg_ctl -D "$PGDATA" -m fast -w stop } pg_setup_conf() { { printf "\n" printf "archive_command = '/bin/true'\n" printf "archive_mode = on\n" printf "hot_standby = on\n" printf "max_wal_senders = 10\n" printf "max_replication_slots = 10\n" printf "shared_preload_libraries = 'repmgr'\n" if [[ -n $POSTGRES_MAX_CONNECTIONS ]]; then printf "\nmax_connections = '%s'\n" "$POSTGRES_MAX_CONNECTIONS" fi } >> "$PGDATA/postgresql.conf" } pg_setup_hba_conf() { { printf '\n' printf 'local all all trust\n' printf 'local replication repmgr trust\n' printf 'local repmgr repmgr trust\n' printf '\n' printf 'host replication repmgr 127.0.0.1/32 trust\n' printf 'host repmgr repmgr 127.0.0.1/32 trust\n' printf '\n' printf 'host replication repmgr %s trust\n' "${POSTGRES_NETWORK:-100.64.0.0/10}" printf 'host repmgr repmgr %s trust\n' "${POSTGRES_NETWORK:-100.64.0.0/10}" printf '\n' printf 'host all all all scram-sha-256' } >> "$PGDATA/pg_hba.conf" } repmgr_setup_conf() { { printf "node_id = %s\n" "$REPMGR_NODE_ID" printf "node_name = %s\n" "$REPMGR_NODE_NAME" printf "conninfo = 'host=%s dbname=repmgr user=repmgr connect_timeout=2'\n" "$REPMGR_NODE_NAME" printf "\n" printf "data_directory = '/var/lib/postgresql/data'\n" printf "use_replication_slots = on\n" printf "pg_bindir = '/usr/lib/postgresql/15/bin/'\n" printf "\n" printf "failover = automatic\n" printf "promote_command = '/usr/bin/repmgr standby promote -f /etc/repmgr.conf --log-to-file'\n" printf "follow_command = '/usr/bin/repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'\n" printf "reconnect_attempts = 3\n" printf "reconnect_interval = 5\n" } > /etc/repmgr/repmgr.conf } sudo service ssh start docker_setup_env docker_create_db_directories if [ "$(id -u)" = '0' ]; then exec gosu postgres "$BASH_SOURCE" fi if [[ ! -s "$PGDATA/PG_VERSION" ]]; then repmgr_setup_conf if [[ -z $REPMGR_UPSTREAM ]]; then docker_init_database_dir pg_setup_conf pg_setup_hba_conf export PGPASSWORD="$POSTGRES_PASSWORD" docker_temp_server_start psql -c "CREATE USER repmgr WITH SUPERUSER ENCRYPTED PASSWORD '${REPMGR_PASSWORD}';" psql -c "CREATE DATABASE repmgr WITH OWNER repmgr;" psql -c 'ALTER USER repmgr SET search_path TO repmgr, "$user", public;' if [[ -n $PGPOOL_PASSWORD ]]; then psql -c "CREATE USER pgpool WITH ENCRYPTED PASSWORD '${PGPOOL_PASSWORD}';" fi unset PGPASSWORD /usr/lib/postgresql/15/bin/repmgr -f /etc/repmgr.conf primary register else until /usr/lib/postgresql/15/bin/repmgr -h $REPMGR_UPSTREAM -U repmgr -f /etc/repmgr.conf standby clone --dry-run &> /dev/null do echo "Upstream host not ready. Waiting for 5 minutes..." sleep 300 done echo "Upstream host found..." /usr/lib/postgresql/15/bin/repmgr -h $REPMGR_UPSTREAM -U repmgr -f /etc/repmgr.conf standby clone docker_temp_server_start /usr/lib/postgresql/15/bin/repmgr -f /etc/repmgr.conf standby register --force fi docker_temp_server_stop fi set -m postgres & sleep 10 repmgrd -f /etc/repmgr.conf --pid-file /tmp/repmgrd.pid while true do echo "$(date)" sleep 3600 done