File size: 5,285 Bytes
23b38fd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | #!/bin/bash
set -e
PG_VERSION=15
PG_BIN=/usr/lib/postgresql/$PG_VERSION/bin
PG_DATA=/data/pgdata
PG_LOG=/data/pgdata/pg.log
: "${POSTGRES_USER:=root}"
: "${POSTGRES_PASSWORD:=123456}"
: "${POSTGRES_DB:=new-api}"
: "${SQL_DSN:=postgresql://root:123456@127.0.0.1:5432/new-api?sslmode=disable}"
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export SQL_DSN
mkdir -p "$PG_DATA"
chown -R postgres:postgres "$PG_DATA"
if [ ! -f "$PG_DATA/PG_VERSION" ]; then
echo "Initializing PostgreSQL data directory..."
su postgres -c "$PG_BIN/initdb -D '$PG_DATA' --locale=en_US.UTF-8"
if [ ! -f "$PG_DATA/postgresql.conf" ]; then
echo "FATAL: initdb did not create postgresql.conf" >&2
exit 1
fi
fi
echo "Writing PostgreSQL configuration..."
cat > "$PG_DATA/pg_hba.conf" << EOF
local all all trust
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
EOF
# Listen only on localhost
if ! grep -q "^listen_addresses" "$PG_DATA/postgresql.conf" 2>/dev/null; then
echo "listen_addresses = '127.0.0.1,::1'" >> "$PG_DATA/postgresql.conf"
fi
# Optimize for Hugging Face Spaces / slow persistent storage
if ! grep -q "^fsync = off" "$PG_DATA/postgresql.conf" 2>/dev/null; then
echo "Applying PostgreSQL storage optimizations..."
cat >> "$PG_DATA/postgresql.conf" << EOF
# Hugging Face Spaces storage optimizations
fsync = off
synchronous_commit = off
full_page_writes = off
EOF
fi
# Remove stale PID file from previous run
if [ -f "$PG_DATA/postmaster.pid" ]; then
OLD_PID=$(head -1 "$PG_DATA/postmaster.pid")
if ! kill -0 "$OLD_PID" 2>/dev/null; then
echo "Removing stale PostgreSQL PID file, old PID: $OLD_PID"
rm -f "$PG_DATA/postmaster.pid"
fi
fi
# Fix permissions on every start
chown -R postgres:postgres "$PG_DATA"
chmod 0700 "$PG_DATA"
# Recreate missing critical directories
# HF persistent storage may sometimes lose empty dirs after restart
for dir in \
base \
global \
pg_commit_ts \
pg_dynshmem \
pg_logical \
pg_logical/snapshots \
pg_logical/mappings \
pg_multixact \
pg_multixact/members \
pg_multixact/offsets \
pg_notify \
pg_replslot \
pg_serial \
pg_snapshots \
pg_stat \
pg_stat_tmp \
pg_subtrans \
pg_tblspc \
pg_twophase \
pg_wal \
pg_wal/archive_status; do
if [ ! -d "$PG_DATA/$dir" ]; then
echo "Recreating missing directory: $dir"
mkdir -p "$PG_DATA/$dir"
fi
done
chown -R postgres:postgres "$PG_DATA"
rm -f "$PG_LOG"
echo "Starting PostgreSQL..."
su postgres -c "$PG_BIN/pg_ctl -D '$PG_DATA' -l '$PG_LOG' start" || {
echo "=== PostgreSQL log ==="
cat "$PG_LOG" 2>/dev/null || echo "(no PostgreSQL log file)"
exit 1
}
echo "Waiting for PostgreSQL to be ready..."
for i in $(seq 1 120); do
if su postgres -c "$PG_BIN/pg_isready -q -h 127.0.0.1 -p 5432"; then
echo "PostgreSQL is ready."
break
fi
if [ "$i" -eq 120 ]; then
echo "PostgreSQL startup timeout."
echo "=== PostgreSQL log ==="
cat "$PG_LOG" 2>/dev/null || echo "(no PostgreSQL log file)"
exit 1
fi
sleep 1
done
echo "Creating or fixing database user and database..."
# Create role if missing
if ! su postgres -c "$PG_BIN/psql -tAc \"SELECT 1 FROM pg_roles WHERE rolname='$POSTGRES_USER'\"" | grep -q 1; then
echo "Creating PostgreSQL user: $POSTGRES_USER"
su postgres -c "$PG_BIN/psql -c \"CREATE USER \\\"$POSTGRES_USER\\\" WITH PASSWORD '$POSTGRES_PASSWORD'\""
fi
# Always reset password
# This is important when /data/pgdata already exists with an old password
echo "Resetting PostgreSQL password for user: $POSTGRES_USER"
su postgres -c "$PG_BIN/psql -c \"ALTER USER \\\"$POSTGRES_USER\\\" WITH PASSWORD '$POSTGRES_PASSWORD'\""
# Create database if missing
if ! su postgres -c "$PG_BIN/psql -tAc \"SELECT 1 FROM pg_database WHERE datname='$POSTGRES_DB'\"" | grep -q 1; then
echo "Creating PostgreSQL database: $POSTGRES_DB"
su postgres -c "$PG_BIN/psql -c \"CREATE DATABASE \\\"$POSTGRES_DB\\\" OWNER \\\"$POSTGRES_USER\\\"\""
fi
# Ensure owner is correct
echo "Fixing database owner..."
su postgres -c "$PG_BIN/psql -c \"ALTER DATABASE \\\"$POSTGRES_DB\\\" OWNER TO \\\"$POSTGRES_USER\\\"\""
echo "Testing PostgreSQL login..."
PGPASSWORD="$POSTGRES_PASSWORD" "$PG_BIN/psql" \
"postgresql://$POSTGRES_USER@127.0.0.1:5432/$POSTGRES_DB?sslmode=disable" \
-c "SELECT current_user, current_database();" || {
echo "FATAL: PostgreSQL login test failed."
echo "=== PostgreSQL log ==="
cat "$PG_LOG" 2>/dev/null || echo "(no PostgreSQL log file)"
exit 1
}
cd /data
echo "Starting NewAPI..."
echo "SQL_DSN=$SQL_DSN"
/new-api &
NEWAPI_PID=$!
cleanup() {
echo "Shutting down..."
if kill -0 "$NEWAPI_PID" 2>/dev/null; then
kill "$NEWAPI_PID" 2>/dev/null || true
wait "$NEWAPI_PID" 2>/dev/null || true
fi
su postgres -c "$PG_BIN/pg_ctl -D '$PG_DATA' stop -m fast" || true
exit 0
}
trap cleanup SIGTERM SIGINT
wait "$NEWAPI_PID"
EXIT_CODE=$?
echo "NewAPI exited with code $EXIT_CODE"
su postgres -c "$PG_BIN/pg_ctl -D '$PG_DATA' stop -m fast" || true
exit "$EXIT_CODE" |