7 months ago
Docker file:
Use Postgres 16 as the base image
FROM postgres:16
Install OpenSSL, sudo, and pglogical extension dependencies
RUN apt-get update && apt-get install -y openssl sudo postgresql-16-pglogical
Allow the postgres user to execute certain commands as root without a password
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown, /usr/bin/openssl" > /etc/sudoers.d/postgres
Add init scripts while setting permissions
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh
Create a configuration script to set wal_level to 'logical'
COPY --chmod=755 config-wal.sh /docker-entrypoint-initdb.d/config-wal.sh
Set environment variables to enable pglogical
ENV POSTGRESINITDBARGS="--wal-level=logical"
Ensure pglogical is loaded and enabled
RUN echo "sharedpreloadlibraries = 'pglogical'" >> /usr/share/postgresql/postgresql.conf.sample
Set executable permissions for the wrapper script
RUN chmod +x /usr/local/bin/wrapper.sh
ENTRYPOINT ["wrapper.sh"]
CMD ["postgres", "--port=5432"]
!/bin/bash
exit as soon as any of these commands fail, this prevents starting a database without certificates
set -e
ls -l /usr/local/bin/wrapper.sh
Make sure there is a PGDATA variable available
if [ -z "$PGDATA" ]; then
echo "Missing PGDATA variable"
exit 1
fi
Set up needed variables
SSLDIR="/var/lib/postgresql/data/certs" INITSSLSCRIPT="/docker-entrypoint-initdb.d/init-ssl.sh" POSTGRESCONF_FILE="$PGDATA/postgresql.conf"
Regenerate if the certificate is not a x509v3 certificate
if [ -f "$SSLDIR/server.crt" ] && ! openssl x509 -noout -text -in "$SSLDIR/server.crt" | grep -q "DNS:localhost"; then
echo "Did not find a x509v3 certificate, regenerating certificates…"
bash "$INITSSLSCRIPT"
fi
Regenerate if the certificate has expired or will expire
2592000 seconds = 30 days
if [ -f "$SSLDIR/server.crt" ] && ! openssl x509 -checkend 2592000 -noout -in "$SSLDIR/server.crt"; then
echo "Certificate has or will expire soon, regenerating certificates…"
bash "$INITSSLSCRIPT"
fi
Generate a certificate if the database was initialized but is missing a certificate
Useful when going from the base postgres image to this ssl image
if [ -f "$POSTGRESCONFFILE" ] && [ ! -f "$SSLDIR/server.crt" ]; then echo "Database initialized without certificate, generating certificates…" bash "$INITSSL_SCRIPT"
fi
unset PGHOST to force psql to use Unix socket path
this is specific to Railway and allows
us to use PGHOST after the init
unset PGHOST
unset PGPORT also specific to Railway
since postgres checks for validity of
the value in PGPORT we unset it in case
it ends up being empty
unset PGPORT
Call the entrypoint script with the
appropriate PGHOST & PGPORT and redirect
the output to stdout if LOGTOSTDOUT is true
if [[ "$LOGTOSTDOUT" == "true" ]]; then
/usr/local/bin/docker-entrypoint.sh "$@" 2>&1
else
/usr/local/bin/docker-entrypoint.sh "$@"
fi
ⓘ Deployment information is only viewable by project members and Railway employees.
2 Replies
7 months ago
init-ssl.sh:
#!/bin/bash
# Log directory and file permissions
ls -ld "$SSL_DIR"
ls -l "$SSL_DIR"
if [ -z "$PGDATA" ]; then
echo "Error: PGDATA is not set."
exit 1
fi
# exit as soon as any of these commands fail, this prevents starting a database without certificates
set -e
# Set up needed variables
SSL_DIR="/var/lib/postgresql/data/certs"
SSL_SERVER_CRT="$SSL_DIR/server.crt"
SSL_SERVER_KEY="$SSL_DIR/server.key"
SSL_SERVER_CSR="$SSL_DIR/server.csr"
SSL_ROOT_KEY="$SSL_DIR/root.key"
SSL_ROOT_CRT="$SSL_DIR/root.crt"
SSL_V3_EXT="$SSL_DIR/v3.ext"
POSTGRES_CONF_FILE="$PGDATA/postgresql.conf"
# Use sudo to create the directory as root
sudo mkdir -p "$SSL_DIR"
# Use sudo to change ownership as root
sudo chown postgres:postgres "$SSL_DIR"
# Generate self-signed 509v3 certificates
# ref: https://www.postgresql.org/docs/16/ssl-tcp.html#SSL-CERTIFICATE-CREATION
openssl req -new -x509 -days "${SSL_CERT_DAYS:-820}" -nodes -text -out "$SSL_ROOT_CRT" -keyout "$SSL_ROOT_KEY" -subj "/CN=root-ca"
chmod og-rwx "$SSL_ROOT_KEY"
openssl req -new -nodes -text -out "$SSL_SERVER_CSR" -keyout "$SSL_SERVER_KEY" -subj "/CN=localhost"
chown postgres:postgres "$SSL_SERVER_KEY"
chmod og-rwx "$SSL_SERVER_KEY"
cat >| "$SSL_V3_EXT" <<EOF
[v3_req]
authorityKeyIdentifier = keyid, issuer
basicConstraints = critical, CA:TRUE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = DNS:localhost
EOF
openssl x509 -req -in "$SSL_SERVER_CSR" -extfile "$SSL_V3_EXT" -extensions v3_req -text -days "${SSL_CERT_DAYS:-820}" -CA "$SSL_ROOT_CRT" -CAkey "$SSL_ROOT_KEY" -CAcreateserial -out "$SSL_SERVER_CRT"
chown postgres:postgres "$SSL_SERVER_CRT"
# PostgreSQL configuration, enable ssl and set paths to certificate files
cat >> "$POSTGRES_CONF_FILE" <<EOF
ssl = on
ssl_cert_file = '$SSL_SERVER_CRT'
ssl_key_file = '$SSL_SERVER_KEY'
ssl_ca_file = '$SSL_ROOT_CRT'
EOF
Nixpacks.toml:
[build]
builder = "dockerfile"
dockerfile = "Dockerfile.16"
[phases.setup]
aptPkgs = ["openssl", "wget", "postgresql"]
[phases.build]
cmds = ["chmod +x init-ssl.sh", "./init-ssl.sh"]
[start]
cmd = "./wrapper.sh"
[variables]
PGDATA = "/var/lib/postgresql/data"
7 months ago
Please provide a minimal reproducible example, in this case, the public repo that you are trying to deploy.
Status changed to Awaiting User Response railway[bot] • 7 months ago