diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..f30ed50 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,63 @@ +name: Docker Build and Push + +on: + schedule: + - cron: '43 0 * * *' + push: + branches: [ "main" ] + tags: [ 'v*.*.*' ] + pull_request: + branches: [ "main" ] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + pgbouncer: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata for pgbouncer + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-pgbouncer + + - name: Build and push Docker image for pgbouncer + id: build-and-push + uses: docker/build-push-action@v6 + with: + context: docker/pgbouncer + file: docker/pgbouncer/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha,scope=pgbouncer + cache-to: type=gha,scope=pgbouncer,mode=max + + - name: Sign the published Docker image for pgbouncer + env: + TAGS: ${{ steps.meta.outputs.tags }} + DIGEST: ${{ steps.build-and-push.outputs.digest }} + run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} diff --git a/docker-compose.yml b/docker-compose.yml index b7cb6c4..fbaf1c0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,8 +11,6 @@ services: - ./certs/psql-server.crt:/var/lib/postgresql/server.crt:ro - ./certs/psql-server.key:/var/lib/postgresql/server.key:ro - postgres_data:/var/lib/postgresql/data - ports: - - '5432:5432' command: > postgres -c ssl=on @@ -24,7 +22,7 @@ services: timeout: 5s retries: 5 networks: - - backend + - services valkey: image: valkey/valkey:8-alpine @@ -51,12 +49,41 @@ services: timeout: 5s retries: 5 networks: - - backend + - services + + pgbouncer: + image: ghcr.io/ahmadk953/poixpixel-discord-bot-pgbouncer + container_name: pgbouncer + environment: + DB_USER: ${POSTGRES_USER} + DB_PASSWORD: ${POSTGRES_PASSWORD} + DB_HOST: postgres + # DB_NAME: ${POSTGRES_DB} + AUTH_TYPE: scram-sha-256 + POOL_MODE: transaction + ADMIN_USERS: ${POSTGRES_USER} + CLIENT_TLS_SSLMODE: require + CLIENT_TLS_CERT_FILE: /certs/server.crt + CLIENT_TLS_KEY_FILE: /certs/server.key + CLIENT_TLS_CA_FILE: /certs/ca.crt + SERVER_TLS_SSLMODE: require + ports: + - "5432:5432" + depends_on: + - postgres + volumes: + - ./certs/pgbouncer-server.crt:/certs/server.crt:ro + - ./certs/pgbouncer-server.key:/certs/server.key:ro + - ./certs/pgbouncer-ca.crt:/certs/ca.crt:ro + healthcheck: + test: ['CMD', 'pg_isready', '-h', 'localhost'] + networks: + - services volumes: postgres_data: valkey_data: networks: - backend: + services: driver: bridge diff --git a/docker/pgbouncer/Dockerfile b/docker/pgbouncer/Dockerfile new file mode 100644 index 0000000..7887f3e --- /dev/null +++ b/docker/pgbouncer/Dockerfile @@ -0,0 +1,42 @@ +# Based on https://raw.githubusercontent.com/edoburu/docker-pgbouncer/master/Dockerfile + +FROM alpine:3.22 AS build + +LABEL org.opencontainers.image.source=https://github.com/ahmadk953/poixpixel-discord-bot/tree/main/docker/pgbouncer +LABEL org.opencontainers.image.description="Docker image for pgbouncer with c-ares support" +LABEL org.opencontainers.image.licenses=Apache-2.0 + +ARG PGBOUNCER_VERSION=1.24.1 +ARG C_ARES_VERSION=1.34.5 + +RUN apk add --no-cache autoconf autoconf-doc automake curl gcc git libc-dev libevent-dev libtool make openssl-dev pandoc pkgconfig + +RUN curl -Lo /c-ares.tar.gz https://github.com/c-ares/c-ares/releases/download/v${C_ARES_VERSION}/c-ares-${C_ARES_VERSION}.tar.gz && \ + tar -xzf /c-ares.tar.gz && mv /c-ares-${C_ARES_VERSION} /c-ares + +RUN curl -Lo /pgbouncer.tar.gz https://pgbouncer.github.io/downloads/files/${PGBOUNCER_VERSION}/pgbouncer-${PGBOUNCER_VERSION}.tar.gz && \ + tar -xzf /pgbouncer.tar.gz && mv /pgbouncer-${PGBOUNCER_VERSION} /pgbouncer + +RUN cd /c-ares && ./configure && make && make install +RUN cd /pgbouncer && ./configure --with-cares && make && make install + +FROM alpine:3.22 + +COPY entrypoint.sh /entrypoint.sh + +RUN apk add --no-cache busybox libevent postgresql-client \ + && mkdir -p /etc/pgbouncer /var/log/pgbouncer /var/run/pgbouncer \ + && touch /etc/pgbouncer/userlist.txt \ + && addgroup -S -g 1100 pgbouncer \ + && adduser -S -u 1100 -G pgbouncer pgbouncer \ + && chown -R pgbouncer:pgbouncer /etc/pgbouncer /var/log/pgbouncer /var/run/pgbouncer /entrypoint.sh \ + && chmod +x /entrypoint.sh + +COPY --from=build /usr/local/bin /usr/local/bin +COPY --from=build /usr/local/lib /usr/local/lib +COPY --from=build /pgbouncer/etc/pgbouncer.ini /etc/pgbouncer/pgbouncer.ini.example +COPY --from=build /pgbouncer/etc/userlist.txt /etc/pgbouncer/userlist.txt.example +EXPOSE 5432 +USER pgbouncer +ENTRYPOINT ["/entrypoint.sh"] +CMD ["/usr/local/bin/pgbouncer", "/etc/pgbouncer/pgbouncer.ini"] \ No newline at end of file diff --git a/docker/pgbouncer/README.md b/docker/pgbouncer/README.md new file mode 100644 index 0000000..a899cc5 --- /dev/null +++ b/docker/pgbouncer/README.md @@ -0,0 +1,76 @@ +# Pgbouncer + +Pgbouncer is a lightweight connection pooler for PostgreSQL that helps optimize database connections by reusing established sessions. + +## Overview + +This directory contains all the necessary files to build and run Pgbouncer as part of the Poixpixel Discord Bot project. It is based on Alpine Linux and includes support for c-ares. + +## Contents + +- **Dockerfile**: Builds the Pgbouncer image with c-ares support. +- **entrypoint.sh**: Generates and configures the Pgbouncer configuration file at container startup. + +## Building the Docker Image + +To build the Pgbouncer Docker image, run: + +```sh +docker build -t my-pgbouncer ./docker/pgbouncer +``` + +## Running the Container + +Run the container with your desired environment variables. For example: + +```sh +docker run --rm \ + -e DATABASE_URL="postgres://user:pass@postgres-host/database" \ + -p 5432:5432 \ + my-pgbouncer +``` + +Or, if you would like to use separate environment variables: + +```sh +docker run --rm \ + -e DB_USER=user \ + -e DB_PASSWORD=pass \ + -e DB_HOST=postgres-host \ + -e DB_NAME=database \ + -p 5432:5432 \ + my-pgbouncer +``` + +You can also use the prebuilt image. For example: + +```sh +docker run --rm \ + -e DB_USER=user \ + -e DB_PASSWORD=pass \ + -e DB_HOST=postgres-host \ + -e DB_NAME=database \ + -p 5432:5432 \ + ghcr.io/ahmadk953/poixpixel-discord-bot-pgbouncer +``` + +## Customizing Your Setup + +- **Dockerfile**: Modify build arguments or dependencies as needed. +- **entrypoint.sh**: Adjust how the configuration file is generated and updated. +- **Environment Variables**: Almost all settings found in the `pgbouncer.ini` file can be set as environment variables with the exception of a few, system-specific configuration options. For an example, check out [the example Docker compose file](../../docker-compose.yml). For all configuration options, check the [pgbouncer configuration documentation](https://www.pgbouncer.org/config.html). +- **Configuration File**: You can specify your own `pgbouncer.ini` file by mounting it as a volume like so: +```sh +docker run --rm \ + -e DB_USER=user \ + -e DB_PASSWORD=pass \ + -e DB_HOST=postgres-host \ + -e DB_NAME=database \ + -v pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro + -p 5432:5432 + ghcr.io/ahmadk953/poixpixel-discord-bot-pgbouncer +``` + +## License + +See the [LICENSE](../../LICENSE) file in the root of the project for licensing details. diff --git a/docker/pgbouncer/entrypoint.sh b/docker/pgbouncer/entrypoint.sh new file mode 100644 index 0000000..64df010 --- /dev/null +++ b/docker/pgbouncer/entrypoint.sh @@ -0,0 +1,203 @@ +#!/bin/sh +# Based on https://raw.githubusercontent.com/brainsam/pgbouncer/master/entrypoint.sh +# and https://raw.githubusercontent.com/edoburu/docker-pgbouncer/master/entrypoint.sh + +set -e + +# Here are some parameters. See all on +# https://pgbouncer.github.io/config.html + +PG_CONFIG_DIR=/etc/pgbouncer +PG_CONFIG_FILE="${PG_CONFIG_DIR}/pgbouncer.ini" +_AUTH_FILE="${AUTH_FILE:-$PG_CONFIG_DIR/userlist.txt}" + +# Workaround userlist.txt missing issue +# https://github.com/edoburu/docker-pgbouncer/issues/33 +if [ ! -e "${_AUTH_FILE}" ]; then + touch "${_AUTH_FILE}" +fi + +# Extract all info from a given URL. Sets variables because shell functions can't return multiple values. +# +# Parameters: +# - The url we should parse +# Returns (sets variables): DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_NAME +function parse_url() { + # Thanks to https://stackoverflow.com/a/17287984/146289 + + # Allow to pass values like dj-database-url / django-environ accept + proto="$(echo $1 | grep :// | sed -e's,^\(.*://\).*,\1,g')" + url="$(echo $1 | sed -e s,$proto,,g)" + + # extract the user and password (if any) + userpass="$(echo $url | grep @ | sed -r 's/^(.*)@([^@]*)$/\1/')" + DB_PASSWORD="$(echo $userpass | grep : | cut -d: -f2)" + if [ -n "${DB_PASSWORD}" ]; then + DB_USER="$(echo $userpass | grep : | cut -d: -f1)" + else + DB_USER="${userpass}" + fi + + # extract the host -- updated + hostport=`echo $url | sed -e s,$userpass@,,g | cut -d/ -f1` + port=`echo $hostport | grep : | cut -d: -f2` + if [ -n "$port" ]; then + DB_HOST=`echo $hostport | grep : | cut -d: -f1` + DB_PORT="${port}" + else + DB_HOST="${hostport}" + fi + + DB_NAME="$(echo $url | grep / | cut -d/ -f2-)" +} + +# Grabs variables set by `parse_url` and adds them to the userlist if not already set in there. +function generate_userlist_if_needed() { + if [ -n "${DB_USER}" -a -n "${DB_PASSWORD}" -a -e "${_AUTH_FILE}" ] && ! grep -q "^\"${DB_USER}\"" "${_AUTH_FILE}"; then + if [ "${AUTH_TYPE}" == "plain" ] || [ "${AUTH_TYPE}" == "scram-sha-256" ]; then + pass="${DB_PASSWORD}" + else + pass="md5$(echo -n "${DB_PASSWORD}${DB_USER}" | md5sum | cut -f 1 -d ' ')" + fi + echo "\"${DB_USER}\" \"${pass}\"" >> "${_AUTH_FILE}" + echo "Wrote authentication credentials for '${DB_USER}' to ${_AUTH_FILE}" + fi +} + +# Grabs variables set by `parse_url` and adds them to the PG config file as a database entry. +function generate_config_db_entry() { + printf "\ +${DB_NAME:-*} = host=${DB_HOST:?"Setup pgbouncer config error! You must set DB_HOST env"} \ +port=${DB_PORT:-5432} auth_user=${DB_USER:-postgres} +${CLIENT_ENCODING:+client_encoding = ${CLIENT_ENCODING}\n}\ +" >> "${PG_CONFIG_FILE}" +} + +# Write the password with MD5 encryption, to avoid printing it during startup. +# Notice that `docker inspect` will show unencrypted env variables. +if [ -n "${DATABASE_URLS}" ]; then + echo "${DATABASE_URLS}" | tr , '\n' | while read url; do + parse_url "$url" + generate_userlist_if_needed + done +else + if [ -n "${DATABASE_URL}" ]; then + parse_url "${DATABASE_URL}" + fi + generate_userlist_if_needed +fi + +if [ ! -f "${PG_CONFIG_FILE}" ]; then + echo "Creating pgbouncer config in ${PG_CONFIG_DIR}" + + # Config file is in "ini" format. Section names are between "[" and "]". + # Lines starting with ";" or "#" are taken as comments and ignored. + # The characters ";" and "#" are not recognized when they appear later in the line. + printf "\ +################## Auto generated ################## +[databases] +" > "${PG_CONFIG_FILE}" + + if [ -n "$DATABASE_URLS" ]; then + echo "$DATABASE_URLS" | tr , '\n' | while read url; do + parse_url "$url" + generate_config_db_entry + done + else + if [ -n "$DATABASE_URL" ]; then + parse_url "$DATABASE_URL" + fi + generate_config_db_entry + fi + + printf "\ +[pgbouncer] +listen_addr = ${LISTEN_ADDR:-0.0.0.0} +listen_port = ${LISTEN_PORT:-5432} +unix_socket_dir = ${UNIX_SOCKET_DIR} +user = pgbouncer +auth_file = ${_AUTH_FILE} +${AUTH_HBA_FILE:+auth_hba_file = ${AUTH_HBA_FILE}\n}\ +auth_type = ${AUTH_TYPE:-md5} +${AUTH_USER:+auth_user = ${AUTH_USER}\n}\ +${AUTH_QUERY:+auth_query = ${AUTH_QUERY}\n}\ +${AUTH_DBNAME:+auth_dbname = ${AUTH_DBNAME}\n}\ +${POOL_MODE:+pool_mode = ${POOL_MODE}\n}\ +${MAX_CLIENT_CONN:+max_client_conn = ${MAX_CLIENT_CONN}\n}\ +${POOL_SIZE:+pool_size = ${POOL_SIZE}\n}\ +${DEFAULT_POOL_SIZE:+default_pool_size = ${DEFAULT_POOL_SIZE}\n}\ +${MIN_POOL_SIZE:+min_pool_size = ${MIN_POOL_SIZE}\n}\ +${RESERVE_POOL_SIZE:+reserve_pool_size = ${RESERVE_POOL_SIZE}\n}\ +${RESERVE_POOL_TIMEOUT:+reserve_pool_timeout = ${RESERVE_POOL_TIMEOUT}\n}\ +${MAX_DB_CONNECTIONS:+max_db_connections = ${MAX_DB_CONNECTIONS}\n}\ +${MAX_USER_CONNECTIONS:+max_user_connections = ${MAX_USER_CONNECTIONS}\n}\ +${SERVER_ROUND_ROBIN:+server_round_robin = ${SERVER_ROUND_ROBIN}\n}\ +ignore_startup_parameters = ${IGNORE_STARTUP_PARAMETERS:-extra_float_digits} +${DISABLE_PQEXEC:+disable_pqexec = ${DISABLE_PQEXEC}\n}\ +${APPLICATION_NAME_ADD_HOST:+application_name_add_host = ${APPLICATION_NAME_ADD_HOST}\n}\ +${TIMEZONE:+timezone = ${TIMEZONE}\n}\ +${MAX_PREPARED_STATEMENTS:+max_prepared_statements = ${MAX_PREPARED_STATEMENTS}\n}\ + +# Log settings +${LOG_CONNECTIONS:+log_connections = ${LOG_CONNECTIONS}\n}\ +${LOG_DISCONNECTIONS:+log_disconnections = ${LOG_DISCONNECTIONS}\n}\ +${LOG_POOLER_ERRORS:+log_pooler_errors = ${LOG_POOLER_ERRORS}\n}\ +${LOG_STATS:+log_stats = ${LOG_STATS}\n}\ +${STATS_PERIOD:+stats_period = ${STATS_PERIOD}\n}\ +${VERBOSE:+verbose = ${VERBOSE}\n}\ +admin_users = ${ADMIN_USERS:-postgres} +${STATS_USERS:+stats_users = ${STATS_USERS}\n}\ + +# Connection sanity checks, timeouts +${SERVER_RESET_QUERY:+server_reset_query = ${SERVER_RESET_QUERY}\n}\ +${SERVER_RESET_QUERY_ALWAYS:+server_reset_query_always = ${SERVER_RESET_QUERY_ALWAYS}\n}\ +${SERVER_CHECK_DELAY:+server_check_delay = ${SERVER_CHECK_DELAY}\n}\ +${SERVER_CHECK_QUERY:+server_check_query = ${SERVER_CHECK_QUERY}\n}\ +${SERVER_LIFETIME:+server_lifetime = ${SERVER_LIFETIME}\n}\ +${SERVER_IDLE_TIMEOUT:+server_idle_timeout = ${SERVER_IDLE_TIMEOUT}\n}\ +${SERVER_CONNECT_TIMEOUT:+server_connect_timeout = ${SERVER_CONNECT_TIMEOUT}\n}\ +${SERVER_LOGIN_RETRY:+server_login_retry = ${SERVER_LOGIN_RETRY}\n}\ +${CLIENT_LOGIN_TIMEOUT:+client_login_timeout = ${CLIENT_LOGIN_TIMEOUT}\n}\ +${AUTODB_IDLE_TIMEOUT:+autodb_idle_timeout = ${AUTODB_IDLE_TIMEOUT}\n}\ +${DNS_MAX_TTL:+dns_max_ttl = ${DNS_MAX_TTL}\n}\ +${DNS_NXDOMAIN_TTL:+dns_nxdomain_ttl = ${DNS_NXDOMAIN_TTL}\n}\ + +# TLS settings +${CLIENT_TLS_SSLMODE:+client_tls_sslmode = ${CLIENT_TLS_SSLMODE}\n}\ +${CLIENT_TLS_KEY_FILE:+client_tls_key_file = ${CLIENT_TLS_KEY_FILE}\n}\ +${CLIENT_TLS_CERT_FILE:+client_tls_cert_file = ${CLIENT_TLS_CERT_FILE}\n}\ +${CLIENT_TLS_CA_FILE:+client_tls_ca_file = ${CLIENT_TLS_CA_FILE}\n}\ +${CLIENT_TLS_PROTOCOLS:+client_tls_protocols = ${CLIENT_TLS_PROTOCOLS}\n}\ +${CLIENT_TLS_CIPHERS:+client_tls_ciphers = ${CLIENT_TLS_CIPHERS}\n}\ +${CLIENT_TLS_ECDHCURVE:+client_tls_ecdhcurve = ${CLIENT_TLS_ECDHCURVE}\n}\ +${CLIENT_TLS_DHEPARAMS:+client_tls_dheparams = ${CLIENT_TLS_DHEPARAMS}\n}\ +${SERVER_TLS_SSLMODE:+server_tls_sslmode = ${SERVER_TLS_SSLMODE}\n}\ +${SERVER_TLS_CA_FILE:+server_tls_ca_file = ${SERVER_TLS_CA_FILE}\n}\ +${SERVER_TLS_KEY_FILE:+server_tls_key_file = ${SERVER_TLS_KEY_FILE}\n}\ +${SERVER_TLS_CERT_FILE:+server_tls_cert_file = ${SERVER_TLS_CERT_FILE}\n}\ +${SERVER_TLS_PROTOCOLS:+server_tls_protocols = ${SERVER_TLS_PROTOCOLS}\n}\ +${SERVER_TLS_CIPHERS:+server_tls_ciphers = ${SERVER_TLS_CIPHERS}\n}\ + +# Dangerous timeouts +${QUERY_TIMEOUT:+query_timeout = ${QUERY_TIMEOUT}\n}\ +${QUERY_WAIT_TIMEOUT:+query_wait_timeout = ${QUERY_WAIT_TIMEOUT}\n}\ +${CLIENT_IDLE_TIMEOUT:+client_idle_timeout = ${CLIENT_IDLE_TIMEOUT}\n}\ +${IDLE_TRANSACTION_TIMEOUT:+idle_transaction_timeout = ${IDLE_TRANSACTION_TIMEOUT}\n}\ +${PKT_BUF:+pkt_buf = ${PKT_BUF}\n}\ +${MAX_PACKET_SIZE:+max_packet_size = ${MAX_PACKET_SIZE}\n}\ +${LISTEN_BACKLOG:+listen_backlog = ${LISTEN_BACKLOG}\n}\ +${SBUF_LOOPCNT:+sbuf_loopcnt = ${SBUF_LOOPCNT}\n}\ +${SUSPEND_TIMEOUT:+suspend_timeout = ${SUSPEND_TIMEOUT}\n}\ +${TCP_DEFER_ACCEPT:+tcp_defer_accept = ${TCP_DEFER_ACCEPT}\n}\ +${TCP_KEEPALIVE:+tcp_keepalive = ${TCP_KEEPALIVE}\n}\ +${TCP_KEEPCNT:+tcp_keepcnt = ${TCP_KEEPCNT}\n}\ +${TCP_KEEPIDLE:+tcp_keepidle = ${TCP_KEEPIDLE}\n}\ +${TCP_KEEPINTVL:+tcp_keepintvl = ${TCP_KEEPINTVL}\n}\ +${TCP_USER_TIMEOUT:+tcp_user_timeout = ${TCP_USER_TIMEOUT}\n}\ +################## end file ################## +" >> "${PG_CONFIG_FILE}" + cat "${PG_CONFIG_FILE}" +fi + +echo "Starting $*..." +exec "$@" \ No newline at end of file diff --git a/drizzle.config.ts b/drizzle.config.ts index eb5083a..89cc62e 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ + import fs from 'node:fs'; import path from 'node:path'; import { defineConfig } from 'drizzle-kit'; @@ -14,9 +16,9 @@ export default defineConfig({ ssl: (() => { try { return { - ca: fs.readFileSync(path.resolve('./certs/psql-ca.crt')), - key: fs.readFileSync(path.resolve('./certs/psql-client.key')), - cert: fs.readFileSync(path.resolve('./certs/psql-server.crt')), + ca: fs.readFileSync(path.resolve('./certs/pgbouncer-ca.crt')), + key: fs.readFileSync(path.resolve('./certs/pgbouncer-client.key')), + cert: fs.readFileSync(path.resolve('./certs/pgbouncer-server.crt')), }; } catch (error) { console.warn( diff --git a/generate-certs.sh b/generate-certs.sh index e025695..9b57d08 100755 --- a/generate-certs.sh +++ b/generate-certs.sh @@ -2,6 +2,7 @@ # Get the Effective User ID _uid="$(id -u)" +_gid="$(id -g)" # Create the certificates directory mkdir -p certs @@ -18,26 +19,35 @@ openssl req -new -x509 -days 365 -nodes \ -keyout certs/cache-server.key \ -subj "/CN=localhost" +# Genreate pgbouncer Certificates +openssl req -new -x509 -days 365 -nodes \ + -out certs/pgbouncer-server.crt \ + -keyout certs/pgbouncer-server.key \ + -subj "/CN=localhost" + # Get CA Certificates cp certs/psql-server.crt certs/psql-ca.crt cp certs/cache-server.crt certs/cache-ca.crt +cp certs/pgbouncer-server.crt certs/pgbouncer-ca.crt # Setup Permissions chmod 0600 certs/psql-server.key chmod 0600 certs/cache-server.key +chmod 0600 certs/pgbouncer-server.key # Assign Ownership sudo chown 70:70 certs/psql-*.* sudo chown 999:1000 certs/cache-*.* +sudo chown 1100:1100 certs/pgbouncer-*.* # Get Client Keys -sudo cp certs/psql-server.key certs/psql-client.key +sudo cp certs/pgbouncer-server.key certs/pgbouncer-client.key sudo cp certs/cache-server.key certs/cache-client.key # Change Client Key Ownership -sudo chown $_uid:$_uid certs/psql-client.key -sudo chown $_uid:$_uid certs/cache-client.key +sudo chown $_uid:$_gid certs/pgbouncer-client.key +sudo chown $_uid:$_gid certs/cache-client.key # Change Client Key Permissions -sudo chmod +r certs/psql-client.key +sudo chmod +r certs/pgbouncer-client.key sudo chmod +r certs/cache-client.key diff --git a/src/db/db.ts b/src/db/db.ts index bc5005f..d4a0207 100644 --- a/src/db/db.ts +++ b/src/db/db.ts @@ -103,9 +103,9 @@ export async function initializeDatabaseConnection(): Promise { ssl: (() => { try { return { - ca: fs.readFileSync(path.resolve('./certs/psql-ca.crt')), - key: fs.readFileSync(path.resolve('./certs/psql-client.key')), - cert: fs.readFileSync(path.resolve('./certs/psql-server.crt')), + ca: fs.readFileSync(path.resolve('./certs/pgbouncer-ca.crt')), + key: fs.readFileSync(path.resolve('./certs/pgbouncer-client.key')), + cert: fs.readFileSync(path.resolve('./certs/pgbouncer-server.crt')), }; } catch (error) { console.warn(