41 Commits

Author SHA1 Message Date
stevensting 79a43dbadc chore: publish 1.0.0+1.0.5-social-amd64 release 2026-07-08 12:35:31 +02:00
stevensting 466ff8e447 add release label 2026-07-08 12:17:40 +02:00
stevensting d74f05c0d1 Prepare recipe release (#14)
Reviewed-on: #14
Co-authored-by: stevensting <stefan@klasse-methode.it>
Co-committed-by: stevensting <stefan@klasse-methode.it>
2026-07-08 10:12:53 +00:00
stevensting df3229884d Merge pull request 'add basicauth service' (#16) from basicauth into main
Reviewed-on: #16
2026-07-07 07:55:55 +00:00
mayel 87f9209cd5 db tuning 2026-07-04 08:47:38 +01:00
mayel 8c4d9cce46 memory limits in pg tuner 2026-07-04 00:29:52 +01:00
mayel 5a183a0579 add stop_grace_period + a couple new env for db perf 2026-07-04 00:16:14 +01:00
stevensting 197c18a9b2 remove unused env var 2026-06-28 11:36:46 +02:00
stevensting 21a00c23c3 add basicauth 2026-06-28 11:32:16 +02:00
mayel f1499d6fda Merge pull request 'Prepare recipe release' (#12) from recipe-release into main
Reviewed-on: #12
2026-06-25 08:50:15 +00:00
stevensting 061a986d72 add ghost integration env vars 2026-06-25 10:46:26 +02:00
ivanminutillo 15b48c6033 bump pg_backup_version 2026-06-22 12:11:56 +02:00
ivanminutillo d3d5973ff6 single backup 2026-06-22 12:02:34 +02:00
mayel d6ce1547c9 add LIVE_DASHBOARD_LOGGER 2026-06-17 10:29:33 +01:00
mayel 7747970d1c Merge pull request 'fix(db): missing deploy key in config was preventing backup to work' (#10) from fix-backup-db into main
Reviewed-on: #10
2026-06-03 15:53:42 +00:00
p4u1 c9d2f4e7da fix(db): missing deploy key in config was preventing backup to work 2026-06-03 17:51:37 +02:00
mayel 6f1dd8db55 sonic config 2026-06-02 21:45:27 +01:00
mayel f278be788c add defaults 2026-06-02 21:33:52 +01:00
mayel 63ba064930 Update README.md 2026-06-02 21:27:51 +01:00
mayel 6588ce03ea Merge pull request 'chore(deps): update valeriansaliou/sonic docker tag to v1.5.1' (#9) from renovate/valeriansaliou-sonic-1.x into main
Reviewed-on: #9
2026-06-02 20:09:32 +00:00
renovate-bot 38cbbf770c chore(deps): update valeriansaliou/sonic docker tag to v1.5.1 2026-06-02 20:02:29 +00:00
mayel 9082523712 Add Sonic search overlay (#8)
Co-authored-by: ivan <ivanminutillo@outlook.it>
Reviewed-on: #8
2026-06-02 19:58:08 +00:00
mayel 6c5e6c64ea env 2026-05-26 13:42:19 +01:00
mayel 257918125f Merge pull request 'feat: add mail_key secret' (#6) from flancian/bonfire:feat-mail-key-secret into main
Reviewed-on: #6
2026-05-25 07:36:08 +00:00
flancian a81c2123d1 feat: add mail_key secret 2026-04-27 23:34:48 +02:00
mayel 969fcbd25b Merge pull request 'feat: add mail_password' (#2) from smtp-secret into main
Reviewed-on: #2
2026-03-27 18:49:52 +00:00
p4u1 f3c58df3c6 feat: add mail_password 2026-03-27 19:36:43 +01:00
mayel 6142dde5fb Merge pull request 'Configure Renovate' (#3) from renovate/configure into main
Reviewed-on: #3
2026-03-27 18:18:17 +00:00
renovate-bot 31719f1fd3 Add renovate.json 2026-03-27 18:11:32 +00:00
mayel 0dbbb1d57e DB_MIGRATE_INDEXES_CONCURRENTLY 2025-10-29 16:28:37 +00:00
mayel 16236fe177 better default 2025-10-05 16:01:30 +01:00
mayel 621781820e OAUTH_ISSUER 2025-10-05 15:59:00 +01:00
mayel 7938130edd make autotune optional 2025-10-03 15:57:38 +01:00
mayel bd78cce74c add postgres tuning 2025-10-02 20:43:01 +01:00
mayel 5f610c96ce more s3 env 2025-06-30 20:10:10 +01:00
mayel 1bdd42fa9f UPLOADS_S3_DEFAULT_URL 2025-06-29 11:16:20 +01:00
mayel 4195dafa38 ENABLE_SSO_PROVIDER 2025-06-29 11:14:25 +01:00
mayel 4371d2fedf more SSO env 2025-06-29 11:13:18 +01:00
mayel 0c1f6038d6 more SSO config 2025-06-28 11:14:36 +01:00
mayel e0291cb1fa cleanup 2025-06-27 15:17:52 +01:00
mayel 966c717638 misc 2025-04-21 17:57:43 +01:00
33 changed files with 2187 additions and 253 deletions
+159 -85
View File
@@ -1,32 +1,13 @@
TYPE=bonfire
# choose what flavour of Bonfire to run
FLAVOUR=social
APP_VERSION=latest
# choose what extra services you want to run
COMPOSE_FILE="compose.yml:compose.meilisearch.yml"
APP_VERSION_FLAVOUR=${APP_VERSION}-${FLAVOUR}
# Different flavours/forks or architectures may require different builds of bonfire:
# for ARM (manual build):
# APP_DOCKER_IMAGE=bonfirenetworks/bonfire:${APP_VERSION_FLAVOUR}-aarch64
# for x86 (built by CI):
APP_DOCKER_IMAGE=bonfirenetworks/bonfire:${APP_VERSION_FLAVOUR}-amd64
# multi-arch image (built by CI, but currently not working):
#APP_DOCKER_IMAGE=bonfirenetworks/bonfire:${APP_VERSION_FLAVOUR}
DB_DOCKER_VERSION=17-3.5
# note that different flavours or architectures may require different postgres builds:
# For ARM or x86:
DB_DOCKER_IMAGE=ghcr.io/baosystems/postgis:${DB_DOCKER_VERSION}
# for x86:
# DB_DOCKER_IMAGE=postgis/postgis:${DB_DOCKER_VERSION}-alpine
# multiarch (but doesn't have required Postgis extension)
#DB_DOCKER_IMAGE=postgres:${DB_DOCKER_VERSION}-alpine
# TODO: maybe to use for Upgrading to a new Postgres version? (NOTE: does not work with postgis data)
# DB_DOCKER_IMAGE=pgautoupgrade/pgautoupgrade:16-alpine
LETS_ENCRYPT_ENV=production
# choose what flavour of Bonfire to run. default: social
#APP_FLAVOUR=social
# uncomment to run specific version e.g. 1.0.4 or latest release branch. available: latest, latest-rc, latest-beta, latest-alpha
#APP_VERSION=latest
# choose specific build. default: amd64, available: aarch64
#APP_PLATFORM=aarch64
# enter your instance's domain name
DOMAIN=bonfire.example.com
@@ -37,110 +18,203 @@ DOMAIN=bonfire.example.com
# enable abra backups
ENABLE_BACKUPS=true
# what service to use for sending out emails (eg. smtp, mailgun, none) NOTE: you should also set the corresponding keys in secrets.env
MAIL_BACKEND=none
COMPOSE_FILE="compose.yml"
# require an email address to be invited before being able to sign up? (true or false)
INVITE_ONLY=true
# ====================================
# DATABASE CONFIG
COMPOSE_FILE="$COMPOSE_FILE:compose.postgres.yml"
SECRET_POSTGRES_PASSWORD_VERSION=v1
# upper limit for how much RAM you want the DB to use, in megabytes (the same amount of swap will also be allocated to the DB container) As a rule of thumb use 25% of system RAM.
DB_MEMORY_LIMIT=1024
#DB_MAX_CONNECTIONS=200
# set to true *after* your initial deployment to enable concurrent index creation for faster migrations in future upgrades
DB_MIGRATE_INDEXES_CONCURRENTLY=false
# for manual selection of DB version and docker image uncomment
#DB_DOCKER_VERSION=17-3.5
# note that different flavours or architectures may require different postgres builds:
# For ARM or x86:
#DB_DOCKER_IMAGE=ghcr.io/baosystems/postgis
# for x86:
#DB_DOCKER_IMAGE=postgis/postgis
#DB_DOCKER_VERSION=17-3.5-alpine
# uncomment in order to NOT automatically change the database schema when you upgrade the app
# DISABLE_DB_AUTOMIGRATION=true
# max file upload size - default is 20 meg
UPLOAD_LIMIT=20000000
# in megabytes
DB_MEMORY_LIMIT=1000
# how much info to include in logs (from less to more: emergency, alert, critical, error, warning, notice, info, debug)
LOG_LEVEL=info
# Enable `compose.postgres.tune.yml` for Postgres tuning (can only be enabled *after* your instance already is deployed and working)
# COMPOSE_FILE="$COMPOSE_FILE:postgres/compose.postgres.tune.yml"
# ====================================
# SECRETS
## BASIC_AUTH
# please make sure you change everything to your own secrets!
# and do not check your env file into any public git repo
# change ALL the values:
## Use 'echo $(htpasswd -nB username)' to generate the secret and store it in secret 'usersfile', multiple user/hashedpassword combinations can be added as comma separated list
#COMPOSE_FILE="$COMPOSE_FILE:compose.basicauth.yml"
#SECRET_USERSFILE_VERSION=v1
# if `INVITE_ONLY` is true, what should be the secret code to sign up?
# INVITE_KEY=123
# ====================================
# SEARCH BACKEND
# recommended search backend sonic
#COMPOSE_FILE="$COMPOSE_FILE:compose.sonic.yml"
# docker secret cannot be used due to distroless image, threfore add secret here
#SONIC_PASSWORD=
# alternative search service
#COMPOSE_FILE="$COMPOSE_FILE:compose.meilisearch.yml"
#SECRET_MEILI_MASTER_KEY_VERSION=v1
# ====================================
# MAIL
# COMPOSE_FILE="$COMPOSE_FILE:compose.mail.yml"
# SECRET_MAIL_KEY_VERSION=v1
# private key only necessary for some mail provider
# COMPOSE_FILE="$COMPOSE_FILE:compose.mail.privatekey.yml"
# SECRET_MAIL_PRIVATE_KEY_VERSION=v1
# what service to use for sending out emails (eg. smtp, mailgun, none) NOTE: you should also set the corresponding keys below for the relevant service you choose, and uncomment the COMPOSE_FILE line for the relevant service if needed
#MAIL_BACKEND=none
# signup to an email service and edit with relevant info, see: https://docs.bonfirenetworks.org/Bonfire.Mailer.html
# MAIL_DOMAIN=mgo.example.com
# MAIL_KEY=xyz
# MAIL_FROM=admin@example.com
# MAIL_PROJECT_ID=
# MAIL_PRIVATE_KEY=
# MAIL_BASE_URI=
# MAIL_REGION=
# MAIL_SESSION_TOKEN=
# MAIL_SERVER=
# MAIL_USER=
# MAIL_PASSWORD=
# MAIL_PORT=
# MAIL_TLS=
# MAIL_SSL=
# MAIL_SSL=true
# MAIL_TLS=if_available
# MAIL_SMTP_AUTH=
# MAIL_RETRIES=
# MAIL_ARGS=
# Store uploads in S3-compatible service:
# UPLOADS_S3_BUCKET=
# UPLOADS_S3_ACCESS_KEY_ID=
# UPLOADS_S3_SECRET_ACCESS_KEY=
# UPLOADS_S3_REGION=fr-par
# UPLOADS_S3_HOST=s3.fr-par.scw.cloud
# UPLOADS_S3_SCHEME=https://
# UPLOADS_S3_URL=
# ====================================
# UPLOADS
# OpenID Connect:
# max file upload size - default is 20 meg
UPLOAD_LIMIT=20000000
# Store uploads in S3-compatible service:
#COMPOSE_FILE="$COMPOSE_FILE:compose.s3.yml"
#SECRET_UPLOADS_S3_ACCESS_KEY_ID_VERSION=v1
#SECRET_UPLOADS_S3_SECRET_ACCESS_KEY_VERSION=v1
#UPLOADS_S3_BUCKET=
#UPLOADS_S3_REGION=fr-par
#UPLOADS_S3_HOST=s3.fr-par.scw.cloud
#UPLOADS_S3_SCHEME=https://
#UPLOADS_S3_URL=
#UPLOADS_S3_DEFAULT_URL=
#AWS_ROLE_ARN=
# Optionally use AWS identity token file
#COMPOSE_FILE="$COMPOSE_FILE:compose.s3.tokenfile.yml"
#SECRET_AWS_WEB_IDENTITY_TOKEN_VERSION=v1
# ====================================
# SSO
# Enable using Bonfire as an SSO provider for external apps to sign in with?
# ENABLE_SSO_PROVIDER=false
#OAUTH_ISSUER=https://${DOMAIN}
# OpenID Connect: connect as a client to the OpenID Connect provider with callback url https://yourinstance.tld/openid/client/openid_1
#COMPOSE_FILE="$COMPOSE_FILE:compose.auth.openid.yml"
#SECRET_OPENID_CLIENT_SECRET_VERSION=v1
# OPENID_1_DISCOVERY=
# OPENID_1_DISPLAY_NAME=
# OPENID_1_CLIENT_ID=
# OPENID_1_CLIENT_SECRET=
# OPENID_1_SCOPE=
# OPENID_1_RESPONSE_TYPE=code
# OPENID_1_ENABLE_SIGNUP=false
# ^ can be code, token or id_token
# orcid.org SSO: connect as a client to the orcid.org OpenID Connect provider with callback url https://yourinstance.tld/openid/client/orcid
#COMPOSE_FILE="$COMPOSE_FILE:compose.auth.orcid.yml"
#SECRET_ORCID_CLIENT_SECRET_VERSION=v1
# ORCID_CLIENT_ID=
# ORCID_CLIENT_SECRET=
# Bonfire extensions configs:
# OAuth2 provider: connect as a client to the OAuth2 provider with callback url https://yourinstance.tld/oauth/client/oauth_1
#COMPOSE_FILE="$COMPOSE_FILE:compose.auth.oauth.yml"
# SECRET_OAUTH_CLIENT_SECRET_VERSION=v1
# OAUTH_1_DISPLAY_NAME=
# OAUTH_1_CLIENT_ID=
# OAUTH_1_AUTHORIZE_URI=
# OAUTH_1_ACCESS_TOKEN_URI=
# OAUTH_1_USER_INFO_URI=
# OAUTH_1_ENABLE_SIGNUP=false
# github.com SSO: connect as a client to the github.com OAuth2 provider with callback url https://yourinstance.tld/oauth/client/github
#COMPOSE_FILE="$COMPOSE_FILE:compose.auth.github.yml"
# SECRET_GITHUB_CLIENT_SECRET_VERSION=v1
# GITHUB_APP_CLIENT_ID=
# Zenodo SSO: connect as a client to the Zenodo OAuth2 provider with callback url https://yourinstance.tld/oauth/client/zenodo
# ZENODO_CLIENT_ID=
# ZENODO_CLIENT_SECRET=
# ZENODO_GRANT_TYPE=
# ZENODO_SCOPE=
# ZENODO_ENV=
# ====================================
# GHOST INTEGRATION
#COMPOSE_FILE="$COMPOSE_FILE:compose.ghost.yml"
#SECRET_GHOST_CONTENT_API_KEY_VERSION=v1
#SECRET_GHOST_ADMIN_API_KEY_VERSION=v1
#SECRET_GHOST_WEBHOOK_SECRET_VERSION=v1
#GHOST_URL=https://example.ghost.io
# ====================================
# OPEN TELEMETRY
#COMPOSE_FILE="$COMPOSE_FILE:compose.otel.yml"
#SECRET_HONEYCOMB_API_KEY_VERSION=v1
#SECRET_LIGHTSTEP_API_KEY_VERSION=v1
# ====================================
# BONFIRE EXTENSIONS AND MISC
#COMPOSE_FILE="$COMPOSE_FILE:compose.webpush.yml"
# SECRET_WEBPUSH_PRIVATE_KEY_VERSION=v1
# WEB_PUSH_SUBJECT=mailto:admin@example.com
# WEB_PUSH_PUBLIC_KEY=xyz
# WEB_PUSH_PRIVATE_KEY=abc
# GEOLOCATE_OPENCAGEDATA=
# GITHUB_TOKEN=xyz
# AKISMET_API_KEY=
WITH_LV_NATIVE=0
WITH_IMAGE_VIX=1
WITH_AI=0
#COMPOSE_FILE="$COMPOSE_FILE:compose.github.yml"
#SECRET_GITHUB_TOKEN_VERSION=v1
#COMPOSE_FILE="$COMPOSE_FILE:compose.akismet.yml"
#SECRET_AKISMET_API_KEY_VERSION=v1
#COMPOSE_FILE="$COMPOSE_FILE:compose.mapbox.yml"
#SECRET_MAPBOX_API_KEY_VERSION=v1
# GEOLOCATE_OPENCAGEDATA=
#IFRAME_ALLOWED_ORIGINS=https://example.com
# how much info to include in app logs (from less to more: emergency, alert, critical, error, warning, notice, info, debug); default is warning — note that debug-level entries are removed from release builds entirely, so the most verbose usable level here is info
# PROD_LOG_LEVEL=warning
# how much info to include in logs (from less to more: emergency, alert, critical, error, warning, notice, info, debug)
LOG_LEVEL=info
# error reporting:
# SENTRY_DSN=
# ====================================
# these secrets will be autogenerated/managed by abra and docker"
SECRET_POSTGRES_PASSWORD_VERSION=v1
SECRET_MEILI_MASTER_KEY_VERSION=v1
# SECRETS
# these secrets will be autogenerated/managed by abra and docker
SECRET_SEEDS_PW_VERSION=v1
SECRET_LIVEBOOK_PASSWORD_VERSION=v1
SECRET_SECRET_KEY_BASE_VERSION=v1 # length=128
SECRET_SIGNING_SALT_VERSION=v1 # length=128
SECRET_ENCRYPTION_SALT_VERSION=v1 # length=128
SECRET_RELEASE_COOKIE_VERSION=v1
# ====================================
# You should not have to edit any of the following ones:
APP_NAME=Bonfire
LANG=en_US.UTF-8
SEEDS_USER=root
ERLANG_COOKIE=bonfire_cookie
REPLACE_OS_VARS=true
LIVEVIEW_ENABLED=true
ACME_AGREE=true
SHOW_DEBUG_IN_DEV=true
LETS_ENCRYPT_ENV=production
HOSTNAME=$DOMAIN
#PLUG_SERVER=bandit
+6
View File
@@ -25,6 +25,12 @@ A [coop-cloud](https://coopcloud.tech) recipe for deploying [Bonfire](https://bo
## Upgrades
`abra app deploy --force your-server.domain.name`
NOTE: we recommend switching to the new `sonic` search backend (instead of the deprecated `meilisearch`):
1. comment the `COMPOSE_FILE` line that contains `compose.meilisearch.yml` in the `.env` file for your bonfire instancem and replace with a line like `COMPOSE_FILE="compose.yml:compose.sonic.yml"`
2. add `SONIC_PASSWORD=a-super-secret-password` to the same file (make sure to change the password after pasting!)
3. redeploy with `abra app deploy --force your-server.domain.name`
[`abra`]: https://docs.coopcloud.tech/abra/
[`coop-cloud/traefik`]: https://git.coopcloud.tech/coop-cloud/traefik
+4 -3
View File
@@ -1,4 +1,5 @@
export APP_ENTRYPOINT_VERSION=v1
export PG_BACKUP_VERSION=v4
export APP_ENTRYPOINT_VERSION=v4
export PG_BACKUP_VERSION=v6
export MEILI_BACKUP_VERSION=v4
export SONIC_CFG_VERSION=v1
export SONIC_ENTRYPOINT_VERSION=v1
+14
View File
@@ -0,0 +1,14 @@
version: "3.8"
services:
app:
environment:
- AKISMET_API_KEY_FILE=/run/secrets/akismet_api_key
secrets:
- akismet_api_key
secrets:
akismet_api_key:
external: true
name: ${STACK_NAME}_akismet_api_key_${SECRET_AKISMET_API_KEY_VERSION:-v1}
+14
View File
@@ -0,0 +1,14 @@
version: "3.8"
services:
app:
environment:
- GITHUB_APP_CLIENT_ID
- GITHUB_CLIENT_SECRET_FILE=/run/secrets/github_client_secret
secrets:
- github_client_secret
secrets:
oauth_client_secret:
external: true
name: ${STACK_NAME}_github_client_secret_${SECRET_GITHUB_CLIENT_SECRET_VERSION:-v1}
+19
View File
@@ -0,0 +1,19 @@
version: "3.8"
services:
app:
environment:
- OAUTH_1_DISPLAY_NAME
- OAUTH_1_CLIENT_ID
- OAUTH_1_CLIENT_SECRET_FILE=/run/secrets/oauth_client_secret
- OAUTH_1_AUTHORIZE_URI
- OAUTH_1_ACCESS_TOKEN_URI
- OAUTH_1_USER_INFO_URI
- OAUTH_1_ENABLE_SIGNUP
secrets:
- oauth_client_secret
secrets:
oauth_client_secret:
external: true
name: ${STACK_NAME}_oauth_client_secret_${SECRET_OAUTH_CLIENT_SECRET_VERSION:-v1}
+19
View File
@@ -0,0 +1,19 @@
version: "3.8"
services:
app:
environment:
- OPENID_1_DISPLAY_NAME
- OPENID_1_DISCOVERY
- OPENID_1_CLIENT_ID
- OPENID_1_CLIENT_SECRET_FILE=/run/secrets/openid_client_secret
- OPENID_1_SCOPE
- OPENID_1_RESPONSE_TYPE
- OPENID_1_ENABLE_SIGNUP
secrets:
- openid_client_secret
secrets:
openid_client_secret:
external: true
name: ${STACK_NAME}_openid_client_secret_${SECRET_OPENID_CLIENT_SECRET_VERSION:-v1}
+14
View File
@@ -0,0 +1,14 @@
version: "3.8"
services:
app:
environment:
- ORCID_CLIENT_ID
- ORCID_CLIENT_SECRET_FILE=/run/secrets/orchid_client_secret
secrets:
- orchid_client_secret
secrets:
orchid_client_secret:
external: true
name: ${STACK_NAME}_orchid_client_secret_${SECRET_ORCID_CLIENT_SECRET_VERSION:-v1}
+14
View File
@@ -0,0 +1,14 @@
version: "3.8"
services:
app:
secrets:
- usersfile
deploy:
labels:
- "traefik.http.middlewares.${STACK_NAME}_basicauth.basicauth.usersFile=/run/secrets/usersfile"
- "traefik.http.routers.${STACK_NAME}.middlewares=${STACK_NAME}_basicauth"
secrets:
usersfile:
name: ${STACK_NAME}_usersfile_${SECRET_USERSFILE_VERSION}
external: true
+24
View File
@@ -0,0 +1,24 @@
version: "3.8"
services:
app:
environment:
- GHOST_URL
- GHOST_CONTENT_API_KEY_FILE=/run/secrets/ghost_content_api_key
- GHOST_ADMIN_API_KEY_FILE=/run/secrets/ghost_admin_api_key
- GHOST_WEBHOOK_SECRET_FILE=/run/secrets/ghost_webhook_secret
secrets:
- ghost_content_api_key
- ghost_admin_api_key
- ghost_webhook_secret
secrets:
ghost_content_api_key:
external: true
name: ${STACK_NAME}_ghost_content_api_key_${SECRET_GHOST_CONTENT_API_KEY_VERSION:-v1}
ghost_admin_api_key:
external: true
name: ${STACK_NAME}_ghost_admin_api_key_${SECRET_GHOST_ADMIN_API_KEY_VERSION:-v1}
ghost_webhook_secret:
external: true
name: ${STACK_NAME}_ghost_webhook_secret_${SECRET_GHOST_WEBHOOK_SECRET_VERSION:-v1}
+14
View File
@@ -0,0 +1,14 @@
version: "3.8"
services:
app:
environment:
- GITHUB_TOKEN_FILE=/run/secrets/github_token
secrets:
- github_token
secrets:
github_token:
external: true
name: ${STACK_NAME}_github_token_${SECRET_GITHUB_TOKEN_VERSION:-v1}
+13
View File
@@ -0,0 +1,13 @@
version: "3.8"
services:
app:
environment:
- MAIL_PRIVATE_KEY_FILE=/run/secrets/mail_private_key
secrets:
- mail_private_key
secrets:
mail_private_key:
external: true
name: ${STACK_NAME}_mail_private_key_${SECRET_MAIL_PRIVATE_KEY_VERSION:-v1}
+27
View File
@@ -0,0 +1,27 @@
version: "3.8"
services:
app:
environment:
- MAIL_BACKEND=${MAIL_BACKEND:-none}
- MAIL_DOMAIN
- MAIL_FROM
- MAIL_KEY_FILE=/run/secrets/mail_key
- MAIL_PROJECT_ID
- MAIL_BASE_URI
- MAIL_REGION
- MAIL_SERVER
- MAIL_USER
- MAIL_PORT
- MAIL_TLS
- MAIL_SSL
- MAIL_SMTP_AUTH
- MAIL_RETRIES
- MAIL_ARGS
secrets:
- mail_key
secrets:
mail_key:
external: true
name: ${STACK_NAME}_mail_key_${SECRET_MAIL_KEY_VERSION:-v1}
+14
View File
@@ -0,0 +1,14 @@
version: "3.8"
services:
app:
environment:
- MAPBOX_API_KEY_FILE=/run/secrets/mapbox_api_key
secrets:
- mapbox_api_key
secrets:
mapbox_api_key:
external: true
name: ${STACK_NAME}_mapbox_api_key_${SECRET_MAPBOX_API_KEY_VERSION:-v1}
+9 -2
View File
@@ -7,9 +7,11 @@ services:
- search
environment:
- SEARCH_MEILI_INSTANCE=http://${STACK_NAME}_search:7700
secrets:
- meili_master_key
search:
image: getmeili/meilisearch:v1.11 # WIP: upgrade from v1.11 to 1.14
image: getmeili/meilisearch:v1.14 # WIP: upgrade from v1.11 to 1.14
secrets:
- meili_master_key
volumes:
@@ -40,5 +42,10 @@ volumes:
configs:
meili_backup:
name: ${STACK_NAME}_meili_backup_${MEILI_BACKUP_VERSION}
name: ${STACK_NAME}_meili_backup_${MEILI_BACKUP_VERSION:-v4}
file: meili_backup.sh
secrets:
meili_master_key:
external: true
name: ${STACK_NAME}_meili_master_key_${SECRET_MEILI_MASTER_KEY_VERSION:-v1}
+21
View File
@@ -0,0 +1,21 @@
version: "3.8"
services:
app:
environment:
- OTEL_ENABLED
- OTEL_SERVICE_NAME
- OTEL_HONEYCOMB_API_KEY_FILE=/run/secrets/honeycomb_api_key
- OTEL_LIGHTSTEP_API_KEY_FILE=/run/secrets/lightstep_api_key
secrets:
- honeycomb_api_key
- lightstep_api_key
secrets:
honeycomb_api_key:
external: true
name: ${STACK_NAME}_honeycomb_api_key_${SECRET_HONEYCOMB_API_KEY_VERSION:-v1}
lightstep_api_key:
external: true
name: ${STACK_NAME}_lightstep_api_key_${SECRET_LIGHTSTEP_API_KEY_VERSION:-v1}
+93
View File
@@ -0,0 +1,93 @@
version: '3.8'
x-postgres-env: &postgres-env
POSTGRES_DB: bonfire_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
services:
app:
environment:
<<: *postgres-env
POSTGRES_HOST: ${STACK_NAME}_db
secrets:
- postgres_password
db:
image: ${DB_DOCKER_IMAGE:-ghcr.io/baosystems/postgis}:${DB_DOCKER_VERSION:-17-3.5}
# give Postgres time to shut down cleanly: the Swarm default (10s) force-kills it mid-shutdown on every redeploy, which wipes the cumulative stats (pg_stat_*) that autovacuum's triggers depend on — a root cause of autovacuum never running on big tables
stop_grace_period: 2m # NOTE: abra validates the schema before env interpolation, so this duration field can't be env-parameterized
# static tuning defaults for deployments NOT using the postgres tuner overlay (NOTE: `compose.postgres.tune.yml` computes these from your system resources instead of hardcoding them, so please use it!)
# Notes:
# memory defaults are deliberately SAFE-SMALL (fit a 1 or 2GB VPS with the app co-hosted): shared_buffers is allocated at boot and maintenance_work_mem is per vacuum worker, so oversizing can prevent startup or OOM small machines — the tuner overlay right-sizes them instead (~25% / ~6% of the DB's RAM budget);
# max_connections is deliberately low because Bonfire's Ecto pool is the connection pooler (~25-50 conns; oversizing shrinks usable work_mem);
# jit off = measured per-query compile tax on Bonfire's many-join queries with no benefit;
# the autovacuum settings suit Bonfire's soft-delete/append workload where default thresholds never trigger on big tables.
command: >
postgres
-c max_connections=${PG_MAX_CONNECTIONS:-100}
-c shared_buffers=${PG_SHARED_BUFFERS_MB:-256}MB
-c effective_cache_size=${PG_EFFECTIVE_CACHE_SIZE_MB:-768}MB
-c work_mem=${PG_WORK_MEM_MB:-16}MB
-c maintenance_work_mem=${PG_MAINTENANCE_WORK_MEM_MB:-128}MB
-c random_page_cost=${PG_RANDOM_PAGE_COST:-1.1}
-c effective_io_concurrency=${PG_EFFECTIVE_IO_CONCURRENCY:-200}
-c jit=${PG_JIT:-off}
-c wal_compression=${PG_WAL_COMPRESSION:-lz4}
-c default_toast_compression=${PG_TOAST_COMPRESSION:-lz4}
-c shared_preload_libraries=${PG_PRELOAD_LIBS:-pg_stat_statements}
-c pg_stat_statements.track=all
-c track_io_timing=on
-c track_activity_query_size=16384
-c autovacuum_vacuum_scale_factor=0.05
-c autovacuum_vacuum_insert_scale_factor=0.05
-c autovacuum_vacuum_cost_limit=1000
-c log_autovacuum_min_duration=0
-c log_min_duration_statement=${PG_LOG_MIN_DURATION_STATEMENT:-2000}
-c log_lock_waits=on
-c log_temp_files=0
# -c statement_timeout=1800000
#entrypoint: ['tail', '-f', '/dev/null'] # uncomment when the Postgres DB is corrupted and won't start
volumes:
- db-data:/var/lib/postgresql/data
- type: tmpfs
target: /dev/shm
tmpfs:
size: 1000000000
# about 1 GB in bytes
tmpfs:
- /tmp:size=${DB_MEMORY_LIMIT:-1024}M^
networks:
- internal
environment:
<<: *postgres-env
secrets:
- postgres_password
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U $$POSTGRES_USER"]
interval: 10s
timeout: 5s
retries: 5
deploy:
labels:
backupbot.backup: ${ENABLE_BACKUPS:-true}
backupbot.backup.pre-hook: "/pg_backup.sh backup"
backupbot.backup.volumes.db-data.path: "backup.sql"
backupbot.restore.post-hook: '/pg_backup.sh restore'
configs:
- source: pg_backup
target: /pg_backup.sh
mode: 0555
volumes:
db-data:
configs:
pg_backup:
name: ${STACK_NAME}_pg_backup_${PG_BACKUP_VERSION}
file: pg_backup.sh
secrets:
postgres_password:
external: true
name: ${STACK_NAME}_postgres_password_${SECRET_POSTGRES_PASSWORD_VERSION:-v1}
+14
View File
@@ -0,0 +1,14 @@
version: "3.8"
services:
app:
environment:
- AWS_WEB_IDENTITY_TOKEN_FILE=/run/secrets/aws_web_identity_token
secrets:
- aws_web_identity_token
secrets:
aws_web_identity_token:
external: true
name: ${STACK_NAME}_aws_web_identity_token_${SECRET_AWS_WEB_IDENTITY_TOKEN_VERSION:-v1}
+31
View File
@@ -0,0 +1,31 @@
version: "3.8"
services:
app:
environment:
- UPLOADS_S3_BUCKET
- UPLOADS_S3_ACCESS_KEY_ID_FILE=/run/secrets/uploads_s3_access_key_id
- UPLOADS_S3_SECRET_ACCESS_KEY_FILE=/run/secrets/uploads_s3_secret_access_key
- UPLOADS_S3_REGION
- UPLOADS_S3_HOST
- UPLOADS_S3_SCHEME
- UPLOADS_S3_URL
- UPLOADS_S3_DEFAULT_URL
- UPLOADS_S3_URL_EXPIRATION_TTL
- AWS_ROLE_ARN
secrets:
- mail_key
- uploads_s3_access_key_id
- uploads_s3_secret_access_key
secrets:
mail_key:
external: true
name: ${STACK_NAME}_mail_key_${SECRET_MAIL_KEY_VERSION:-v1}
uploads_s3_access_key_id:
external: true
name: ${STACK_NAME}_uploads_s3_access_key_id_${SECRET_UPLOADS_S3_ACCESS_KEY_ID_VERSION:-v1}
uploads_s3_secret_access_key:
external: true
name: ${STACK_NAME}_uploads_s3_secret_access_key_${SECRET_UPLOADS_S3_SECRET_ACCESS_KEY_VERSION:-v1}
+49
View File
@@ -0,0 +1,49 @@
---
version: "3.8"
services:
app:
depends_on:
- search
environment:
- SEARCH_ADAPTER=sonic
- SONIC_HOST=${STACK_NAME}_search
- SONIC_PORT=1491
- SONIC_PASSWORD
# - SONIC_PASSWORD_FILE=/run/secrets/sonic_password
# secrets:
# - sonic_password
search:
image: valeriansaliou/sonic:v1.5.1
# secrets:
# - sonic_password
volumes:
- "sonic-data:/var/lib/sonic/store"
networks:
- internal
# NOTE: latest versions of Sonic (v1.5.1+) don't have a shell, so we can't have a custom entrypoint script that does pre-startup configuration, so we just need to store the PW in env for now
# entrypoint: ["/docker-entrypoint.sh"]
configs:
- source: sonic_cfg
target: /etc/sonic.cfg
mode: 0444
# - source: sonic_entrypoint
# target: /docker-entrypoint.sh
# mode: 0555
volumes:
sonic-data:
configs:
sonic_cfg:
name: ${STACK_NAME}_sonic_cfg_${SONIC_CFG_VERSION:-v1}
file: sonic.cfg
# sonic_entrypoint:
# name: ${STACK_NAME}_sonic_entrypoint_${SONIC_ENTRYPOINT_VERSION:-v1}
# file: sonic_entrypoint.sh
# secrets:
# sonic_password:
# external: true
# name: ${STACK_NAME}_sonic_password_${SECRET_SONIC_PASSWORD_VERSION:-v1}
+15
View File
@@ -0,0 +1,15 @@
version: "3.8"
services:
app:
environment:
- WEB_PUSH_SUBJECT
- WEB_PUSH_PUBLIC_KEY
- WEB_PUSH_PRIVATE_KEY_FILE=/run/secrets/webpush_private_key
secrets:
- webpush_private_key
secrets:
webpush_private_key:
external: true
name: ${STACK_NAME}_webpush_private_key_${SECRET_WEBPUSH_PRIVATE_KEY_VERSION:-v1}
+56 -144
View File
@@ -3,7 +3,7 @@ version: "3.8"
services:
app:
image: ${APP_DOCKER_IMAGE}
image: ${CONTAINER_REGISTRY:-bonfirenetworks/bonfire}:${APP_VERSION:-1.0.5}-${APP_FLAVOUR:-social}-${APP_PLATFORM:-amd64}
logging:
driver: "json-file"
options:
@@ -12,95 +12,59 @@ services:
depends_on:
- db
environment:
- POSTGRES_HOST=${STACK_NAME}_db
- POSTGRES_USER=postgres
- POSTGRES_DB=bonfire_db
- PUBLIC_PORT=443
- MIX_ENV=prod
- HOSTNAME
- INVITE_ONLY
- HOSTNAME=${DOMAIN}
- INSTANCE_DESCRIPTION
- DISABLE_DB_AUTOMIGRATION
- UPLOAD_LIMIT
- INVITE_KEY
- LANG
- SEEDS_USER
- ERLANG_COOKIE
- REPLACE_OS_VARS
- LIVEVIEW_ENABLED
- APP_NAME
- LANG=${LANG:-en_US.UTF-8}
- SEEDS_USER=${SEEDS_USER:-root}
- REPLACE_OS_VARS=${REPLACE_OS_VARS:-true}
- LIVEVIEW_ENABLED=${LIVEVIEW_ENABLED:-true}
- APP_NAME=${APP_NAME:-Bonfire}
- PLUG_SERVER
- WITH_LV_NATIVE
- WITH_IMAGE_VIX
- WITH_AI
- WITH_LV_NATIVE=${WITH_LV_NATIVE:-0}
- WITH_IMAGE_VIX=${WITH_IMAGE_VIX:-1}
- WITH_AI=${WITH_AI:-0}
- LIVE_DASHBOARD_LOGGER=${LIVE_DASHBOARD_LOGGER:-false}
- IFRAME_ALLOWED_ORIGINS
- RELEASE_DISTRIBUTION
- RELEASE_NODE
- RELEASE_MODE
- DB_SLOW_QUERY_MS
- DB_STATEMENT_TIMEOUT
- MAIL_BACKEND
- MAIL_DOMAIN
- MAIL_FROM
- MAIL_KEY
- MAIL_PROJECT_ID
- MAIL_PRIVATE_KEY
- MAIL_BASE_URI
- MAIL_REGION
- MAIL_SESSION_TOKEN
- MAIL_SERVER
- MAIL_USER
- MAIL_PASSWORD
- MAIL_PORT
- MAIL_TLS
- MAIL_SSL
- MAIL_SMTP_AUTH
- MAIL_RETRIES
- MAIL_ARGS
- DB_QUERY_TIMEOUT
- DB_JIT
- DB_MIGRATE_INDEXES_CONCURRENTLY
- PROD_LOG_LEVEL
- SENTRY_DSN
- OTEL_ENABLED
- OTEL_SERVICE_NAME
- OTEL_HONEYCOMB_API_KEY
- OTEL_LIGHTSTEP_API_KEY
- WEB_PUSH_SUBJECT
- WEB_PUSH_PUBLIC_KEY
- WEB_PUSH_PRIVATE_KEY
- AKISMET_API_KEY
- MAPBOX_API_KEY
- GEOLOCATE_OPENCAGEDATA
- GITHUB_TOKEN
- UPLOADS_S3_BUCKET
- UPLOADS_S3_ACCESS_KEY_ID
- UPLOADS_S3_SECRET_ACCESS_KEY
- UPLOADS_S3_REGION
- UPLOADS_S3_HOST
- UPLOADS_S3_SCHEME
- UPLOADS_S3_URL
- OPENID_1_DISPLAY_NAME
- OPENID_1_DISCOVERY
- OPENID_1_CLIENT_ID
- OPENID_1_CLIENT_SECRET
- OPENID_1_SCOPE
- OPENID_1_RESPONSE_TYPE
- ORCID_CLIENT_ID
- ORCID_CLIENT_SECRET
- GEOLOCATE_OPENCAGEDATA
- ENABLE_SSO_PROVIDER
- OAUTH_ISSUER
- SECRET_KEY_BASE_FILE=/run/secrets/secret_key_base
- SIGNING_SALT_FILE=/run/secrets/signing_salt
- ENCRYPTION_SALT_FILE=/run/secrets/encryption_salt
- SEEDS_PW_FILE=/run/secrets/seeds_pw
- LIVEBOOK_PASSWORD_FILE=/run/secrets/livebook_password
- RELEASE_COOKIE_FILE=/run/secrets/release_cookie
secrets:
- postgres_password
- secret_key_base
- signing_salt
- encryption_salt
- meili_master_key
- seeds_pw
- livebook_password
- release_cookie
volumes:
- upload-data:/opt/app/data/uploads
# - backup-data:/opt/app/data/backup
networks:
- proxy
- internal
@@ -113,71 +77,25 @@ services:
restart_policy:
condition: on-failure
labels:
backupbot.backup: ${ENABLE_BACKUPS:-true}
# backupbot.backup.volumes.upload-data: "true"
# backupbot.backup.volumes.upload-data.path: "/opt/app/data/uploads"
traefik.enable: "true"
traefik.http.services.${STACK_NAME}.loadbalancer.server.port: "4000"
traefik.http.routers.${STACK_NAME}.rule: Host(`${DOMAIN}`${EXTRA_DOMAINS})
traefik.http.routers.${STACK_NAME}.entrypoints: web-secure
traefik.http.routers.${STACK_NAME}.tls.certresolver: ${LETS_ENCRYPT_ENV}
#traefik.http.routers.${STACK_NAME}.middlewares: error-pages-middleware
#traefik.http.services.${STACK_NAME}.loadbalancer.server.port: 80
## Redirect from EXTRA_DOMAINS to DOMAIN
#traefik.http.routers.${STACK_NAME}.middlewares: ${STACK_NAME}-redirect
#traefik.http.middlewares.${STACK_NAME}-redirect.headers.SSLForceHost: true
#traefik.http.middlewares.${STACK_NAME}-redirect.headers.SSLHost: ${DOMAIN}
# healthcheck:
# test: ["CMD", "curl", "-f", "http://localhost"]
# interval: 30s
# timeout: 10s
# retries: 10
# start_period: 1m
db:
image: ${DB_DOCKER_IMAGE}
environment:
# - POSTGRES_PASSWORD
- POSTGRES_USER=postgres
- POSTGRES_DB=bonfire_db
- POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
secrets:
- postgres_password
volumes:
- db-data:/var/lib/postgresql/data
- type: tmpfs
target: /dev/shm
tmpfs:
size: 1000000000
# about 1 GB in bytes ^
networks:
- internal
# shm_size: ${DB_MEMORY_LIMIT} # unsupported by docker swarm
tmpfs:
- /tmp:size=${DB_MEMORY_LIMIT}M
command: >
postgres
-c max_connections=200
-c shared_buffers=${DB_MEMORY_LIMIT}MB
# -c shared_preload_libraries='pg_stat_statements'
# -c statement_timeout=1800000
# -c pg_stat_statements.track=all
#entrypoint: ['tail', '-f', '/dev/null'] # uncomment when the Postgres DB is corrupted and won't start
labels:
backupbot.backup: ${ENABLE_BACKUPS:-true}
# backupbot.backup.volumes.db-data: false
backupbot.backup.volumes.db-data.path: "backup.sql"
backupbot.backup.pre-hook: "/pg_backup.sh backup"
backupbot.restore.post-hook: '/pg_backup.sh restore'
configs:
- source: pg_backup
target: /pg_backup.sh
mode: 0555
# how long abra waits for the deploy to converge, as needs headroom for DB migrations on upgrades
# and the db service's 2m stop_grace_period during redeploys
- "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT:-300}"
- "backupbot.backup=${ENABLE_BACKUPS:-true}"
- "traefik.enable=true"
- "traefik.http.services.${STACK_NAME}.loadbalancer.server.port=4000"
- "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`${EXTRA_DOMAINS})"
- "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure"
- "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}"
- "coop-cloud.${STACK_NAME}.version=1.0.0+1.0.5-social-amd64"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4000"]
interval: 30s
timeout: 10s
retries: 10
start_period: 15s
volumes:
db-data:
upload-data:
# backup-data:
networks:
proxy:
@@ -186,32 +104,26 @@ networks:
configs:
app_entrypoint:
name: ${STACK_NAME}_app_entrypoint_${APP_ENTRYPOINT_VERSION}
name: ${STACK_NAME}_app_entrypoint_${APP_ENTRYPOINT_VERSION:-v3}
file: entrypoint.sh.tmpl
template_driver: golang
pg_backup:
name: ${STACK_NAME}_pg_backup_${PG_BACKUP_VERSION}
file: pg_backup.sh
secrets:
postgres_password:
external: true
name: ${STACK_NAME}_postgres_password_${SECRET_POSTGRES_PASSWORD_VERSION}
secret_key_base:
external: true
name: ${STACK_NAME}_secret_key_base_${SECRET_SECRET_KEY_BASE_VERSION}
name: ${STACK_NAME}_secret_key_base_${SECRET_SECRET_KEY_BASE_VERSION:-v1}
signing_salt:
external: true
name: ${STACK_NAME}_signing_salt_${SECRET_SIGNING_SALT_VERSION}
name: ${STACK_NAME}_signing_salt_${SECRET_SIGNING_SALT_VERSION:-v1}
encryption_salt:
external: true
name: ${STACK_NAME}_encryption_salt_${SECRET_ENCRYPTION_SALT_VERSION}
meili_master_key:
external: true
name: ${STACK_NAME}_meili_master_key_${SECRET_MEILI_MASTER_KEY_VERSION}
name: ${STACK_NAME}_encryption_salt_${SECRET_ENCRYPTION_SALT_VERSION:-v1}
seeds_pw:
external: true
name: ${STACK_NAME}_seeds_pw_${SECRET_SEEDS_PW_VERSION}
name: ${STACK_NAME}_seeds_pw_${SECRET_SEEDS_PW_VERSION:-v1}
livebook_password:
external: true
name: ${STACK_NAME}_livebook_password_${SECRET_LIVEBOOK_PASSWORD_VERSION}
name: ${STACK_NAME}_livebook_password_${SECRET_LIVEBOOK_PASSWORD_VERSION:-v1}
release_cookie:
external: true
name: ${STACK_NAME}_release_cookie_${SECRET_RELEASE_COOKIE_VERSION:-v1}
+5 -9
View File
@@ -1,15 +1,11 @@
#!/bin/sh
# put secrets from files into env
export MEILI_MASTER_KEY=$(cat /run/secrets/meili_master_key)
export POSTGRES_PASSWORD=$(cat /run/secrets/postgres_password)
export SECRET_KEY_BASE=$(cat /run/secrets/secret_key_base)
export SIGNING_SALT=$(cat /run/secrets/signing_salt)
export ENCRYPTION_SALT=$(cat /run/secrets/encryption_salt)
export SEEDS_PW=$(cat /run/secrets/seeds_pw)
export LIVEBOOK_PASSWORD=$(cat /run/secrets/livebook_password)
# meilisearch does not support MEILI_MASTER_KEY_FILE, so we export it here for the search service
if [ -f /run/secrets/meili_master_key ]; then
export MEILI_MASTER_KEY=$(cat /run/secrets/meili_master_key)
fi
echo "....Secrets have been loaded, now run $@...."
# This will exec the CMD from your Dockerfile
exec "$@"
exec "$@"
+9 -10
View File
@@ -6,25 +6,24 @@ BACKUP_PATH="/var/lib/postgresql/data"
LATEST_BACKUP_FILE="${BACKUP_PATH}/backup.sql"
function backup {
FILE_WITH_DATE="${BACKUP_PATH}/backup_$(date +%F).sql"
if [ -f "$POSTGRES_PASSWORD_FILE" ]; then
export PGPASSWORD=$(cat "$POSTGRES_PASSWORD_FILE")
fi
echo "Creating backup at ${FILE_WITH_DATE}..."
pg_dump -U "${POSTGRES_USER:-postgres}" "${POSTGRES_DB:-postgres}" > "${FILE_WITH_DATE}"
echo "Copying to ${LATEST_BACKUP_FILE}..."
cp -f "${FILE_WITH_DATE}" "${LATEST_BACKUP_FILE}"
# Keep a single backup.sql (restic handles versioning); write to a temp file and move
# atomically so a failed dump never clobbers the last good backup.
echo "Creating backup at ${LATEST_BACKUP_FILE}..."
rm -f "${LATEST_BACKUP_FILE}.tmp"
pg_dump -U "${POSTGRES_USER:-postgres}" "${POSTGRES_DB:-postgres}" > "${LATEST_BACKUP_FILE}.tmp"
mv -f "${LATEST_BACKUP_FILE}.tmp" "${LATEST_BACKUP_FILE}"
echo "Backup done. You will find it at ${LATEST_BACKUP_FILE}"
}
function restore {
echo "Restoring database from ${LATEST_BACKUP_FILE}..."
cd /var/lib/postgresql/data/
cd ${BACKUP_PATH}
function restore_config {
echo "Restoring original pg_hba.conf configuration..."
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Pure bash implementation of envsubst for environments where it's not available
# This provides a fallback when the native envsubst command (from gettext package) is missing
# Function: envsubst
# Reads from stdin and replaces ${VAR_NAME} patterns with environment variable values
# Usage: envsubst < template_file > output_file
envsubst() {
local line
while IFS= read -r line; do
# Replace all ${VAR} patterns in the line
# This regex finds ${...} patterns and replaces them with the variable value
while [[ "$line" =~ \$\{([^}]+)\} ]]; do
local var_name="${BASH_REMATCH[1]}"
local var_value="${!var_name:-}"
# Replace the first occurrence
line="${line/\$\{${var_name}\}/${var_value}}"
done
echo "$line"
done
}
+53
View File
@@ -0,0 +1,53 @@
---
version: "3.8"
services:
db:
environment:
- AVAILABLE_RAM_MB=${DB_MEMORY_LIMIT}
- PG_DB_TYPE
- PG_STORAGE_TYPE
# - POSTGRES_START_CMD=
# - postgres
# -c max_connections=200
# -c shared_buffers=${DB_MEMORY_LIMIT}MB
# # -c shared_preload_libraries='pg_stat_statements'
# # -c statement_timeout=1800000
# # -c pg_stat_statements.track=all
# give Postgres time to shut down cleanly: the Swarm default (10s) force-kills it mid-shutdown on every redeploy, which wipes the cumulative stats (pg_stat_*) that autovacuum's triggers depend on — a root cause of autovacuum never running on big tables
stop_grace_period: 2m # NOTE: abra validates the schema before env interpolation, so this duration field can't be env-parameterized
# shm_size: ${DB_MEMORY_LIMIT} # unsupported by docker swarm
tmpfs:
- /tmp:size=${DB_MEMORY_LIMIT}M
entrypoint: ["/postgres-entrypoint.sh"]
#entrypoint: ['tail', '-f', '/dev/null'] # can replace entrypoint when the Postgres DB is corrupted and won't start
configs:
- source: postgres_entrypoint
target: /postgres-entrypoint.sh
mode: 0555
- source: postgres_tune
target: /postgres-tune.sh
mode: 0555
- source: postgres_conf_tmpl
target: /postgres.conf.tmpl
mode: 0444
- source: bash_envsubst
target: /bash-envsubst.sh
mode: 0444
configs:
postgres_entrypoint:
name: ${STACK_NAME}_postgres_entrypoint_${POSTGRES_ENTRYPOINT_VERSION:-v6}
file: postgres/postgres-entrypoint.sh
postgres_tune:
name: ${STACK_NAME}_postgres_tune_${POSTGRES_TUNE_VERSION:-v2}
file: postgres/postgres-tune.sh
postgres_conf_tmpl:
name: ${STACK_NAME}_postgres_conf_tmpl_${POSTGRES_CONF_TMPL_VERSION:-v3}
file: postgres/postgres.conf.tmpl
bash_envsubst:
name: ${STACK_NAME}_bash_envsubst_${BASH_ENVSUBST_VERSION:-v1}
file: postgres/bash-envsubst.sh
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail
# Get the directory where this script is located
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Normalize SCRIPT_DIR to avoid double slashes when it's root
[[ "$SCRIPT_DIR" == "/" ]] && SCRIPT_DIR=""
# Configuration via environment variables
POSTGRES_CONF_PATH="${POSTGRES_CONF_PATH:-/var/lib/postgresql/data/postgresql.auto.conf}"
POSTGRES_START_CMD="${POSTGRES_START_CMD:-docker-entrypoint.sh postgres}"
# Check if envsubst is available, if not, load our bash implementation
if ! command -v envsubst &> /dev/null; then
echo "PostgreSQL: envsubst not found, using pure bash fallback..."
source "${SCRIPT_DIR}/bash-envsubst.sh"
fi
echo "PostgreSQL: Generating optimized configuration..."
# Generate and evaluate the ENV vars (only sets values that aren't already set)
eval "$(bash "${SCRIPT_DIR}/postgres-tune.sh")"
echo "PostgreSQL: Configuration values:"
echo " Profile: ${PG_DB_TYPE:-oltp}"
echo " Max Connections: ${PG_MAX_CONNECTIONS}"
echo " Shared Buffers: ${PG_SHARED_BUFFERS_MB}MB"
echo " Effective Cache: ${PG_EFFECTIVE_CACHE_SIZE_MB}MB"
echo " Work Mem: ${PG_WORK_MEM_KB}kB"
echo " Max Workers: ${PG_MAX_WORKER_PROCESSES}"
# Filter out comments and blank lines for cleaner output
config=$(envsubst < "${SCRIPT_DIR}/postgres.conf.tmpl" | grep -v '^\s*#' | grep -v '^\s*$')
# Get the directory for the config file
CONF_DIR="$(dirname "${POSTGRES_CONF_PATH}")"
echo "=========================================="
echo "$config"
echo "=========================================="
# Check if we can write to the config location
if mkdir -p "${CONF_DIR}" 2>/dev/null; then
# Write the processed config
echo "$config" > "${POSTGRES_CONF_PATH}"
echo "PostgreSQL: Configuration generated at ${POSTGRES_CONF_PATH}"
# Check if we should start postgres
if [[ -n "${POSTGRES_START_CMD}" && "${POSTGRES_START_CMD}" != "none" ]]; then
# Start PostgreSQL - postgresql.auto.conf is automatically loaded from data dir
exec ${POSTGRES_START_CMD}
else
echo "PostgreSQL: Skipping startup (POSTGRES_START_CMD is '${POSTGRES_START_CMD}')"
exit 0
fi
else
echo "WARNING: Cannot write to ${CONF_DIR}"
echo "To use this config, save it to a file and start postgres with: postgres -c config_file=/path/to/postgresql.conf"
exit 1
fi
+505
View File
@@ -0,0 +1,505 @@
#!/usr/bin/env bash
set -euo pipefail
# PostgreSQL Configuration Tuner
# Based on PGTune algorithm (https://pgtune.leopard.in.ua)
# Detects system resources and calculates optimal settings
# Outputs ENV vars that can be sourced before running envsubst
# Constants
readonly KB=1024
readonly MB=$((1024 * KB))
readonly GB=$((1024 * MB))
readonly TB=$((1024 * GB))
# Database types
readonly DB_TYPE_WEB="web"
readonly DB_TYPE_OLTP="oltp"
readonly DB_TYPE_DW="dw"
readonly DB_TYPE_DESKTOP="desktop"
readonly DB_TYPE_MIXED="mixed"
# Storage types
readonly STORAGE_SSD="ssd"
readonly STORAGE_HDD="hdd"
readonly STORAGE_SAN="san"
# Auto-detect or use environment variables
# NOTE: default profile is `mixed` (not `oltp`): Bonfire is OLTP plus a tail of analytics-shaped
# queries (many-join boundarised feeds/threads), which is exactly PGTune's mixed workload. It also
# right-sizes max_connections (100 vs oltp's 300 — Bonfire's Ecto pool is the pooler, ~25-50 conns;
# an oversized value wastes RAM headroom and shrinks the computed work_mem, which caused measured
# multi-TB temp-file spills in prod).
PG_DB_TYPE="${PG_DB_TYPE:-${DB_TYPE:-mixed}}"
PG_STORAGE_TYPE="${PG_STORAGE_TYPE:-${DISK_STORAGE_TYPE:-ssd}}"
PG_DB_VERSION="${PG_DB_VERSION:-17}"
# System resources detection
detect_total_memory_kb() {
if [[ -n "${AVAILABLE_RAM_GB:-}" ]]; then
echo $((AVAILABLE_RAM_GB * GB / KB))
elif [[ -n "${AVAILABLE_RAM_MB:-}" ]]; then
echo $((AVAILABLE_RAM_MB * MB / KB))
elif [[ -r /sys/fs/cgroup/memory.max && "$(cat /sys/fs/cgroup/memory.max)" != "max" ]]; then
# cgroup v2: an explicit container memory limit is the deliberate budget signal
echo $(($(cat /sys/fs/cgroup/memory.max) / KB))
elif [[ -r /sys/fs/cgroup/memory/memory.limit_in_bytes ]] &&
[[ "$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)" -lt $((1 << 60)) ]]; then
# cgroup v1 (its "no limit" sentinel is a huge number rather than "max")
echo $(($(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) / KB))
elif [[ -f /proc/meminfo ]]; then
# Calculate based on total available memory: claiming a fraction as co-hosted services need the rest. Sized for our standard stack (app + postgres + search + proxy). Override with PG_RAM_PERCENT or AVAILABLE_RAM_MB.
awk -v pct="${PG_RAM_PERCENT:-40}" '/MemTotal/ {print int($2 * pct / 100)}' /proc/meminfo
elif command -v sysctl &> /dev/null; then
# macOS/BSD
local mem_bytes
mem_bytes=$(sysctl -n hw.memsize 2>/dev/null || sysctl -n hw.physmem 2>/dev/null)
echo $((mem_bytes * ${PG_RAM_PERCENT:-40} / 100 / KB))
else
# Fallback: assume 4GB
echo $((4 * GB / KB))
fi
}
detect_cpu_count() {
if [[ -n "${NUM_CPU:-}" ]]; then
echo "$NUM_CPU"
elif command -v nproc &> /dev/null; then
nproc
elif [[ -f /proc/cpuinfo ]]; then
grep -c ^processor /proc/cpuinfo
elif command -v sysctl &> /dev/null; then
sysctl -n hw.ncpu 2>/dev/null || echo "2"
else
echo "2"
fi
}
# Get system resources
TOTAL_MEMORY_KB=$(detect_total_memory_kb)
CPU_COUNT=$(detect_cpu_count)
# Helper functions
to_mb() {
echo $(($1 / KB))
}
to_gb() {
echo $(($1 / MB))
}
# Print detected/configured values to stderr so they don't interfere with the export output
{
echo "=========================================="
echo "PostgreSQL Configuration Detection"
echo "=========================================="
echo "System Resources:"
echo " Total Memory: $(to_mb $TOTAL_MEMORY_KB) MB ($(to_gb $TOTAL_MEMORY_KB) GB)"
echo " CPU Cores: ${CPU_COUNT}"
echo ""
echo "Configuration:"
echo " Database Type: ${PG_DB_TYPE}"
echo " Storage Type: ${PG_STORAGE_TYPE}"
echo " PostgreSQL Version: ${PG_DB_VERSION}"
echo "=========================================="
echo ""
} >&2
# Calculate max_connections
calc_max_connections() {
if [[ -n "${PG_MAX_CONNECTIONS:-}" ]]; then
echo "$PG_MAX_CONNECTIONS"
return
fi
case "$PG_DB_TYPE" in
"$DB_TYPE_WEB") echo 200 ;;
"$DB_TYPE_OLTP") echo 300 ;;
"$DB_TYPE_DW") echo 40 ;;
"$DB_TYPE_DESKTOP") echo 20 ;;
"$DB_TYPE_MIXED") echo 100 ;;
*) echo 100 ;;
esac
}
# Calculate shared_buffers
calc_shared_buffers() {
if [[ -n "${PG_SHARED_BUFFERS_MB:-}" ]]; then
echo $((PG_SHARED_BUFFERS_MB * MB / KB))
return
fi
local shared_buffers_kb
case "$PG_DB_TYPE" in
"$DB_TYPE_WEB"|"$DB_TYPE_OLTP"|"$DB_TYPE_DW"|"$DB_TYPE_MIXED")
shared_buffers_kb=$((TOTAL_MEMORY_KB / 4))
;;
"$DB_TYPE_DESKTOP")
shared_buffers_kb=$((TOTAL_MEMORY_KB / 16))
;;
*)
shared_buffers_kb=$((TOTAL_MEMORY_KB / 4))
;;
esac
echo "$shared_buffers_kb"
}
# Calculate effective_cache_size
calc_effective_cache_size() {
if [[ -n "${PG_EFFECTIVE_CACHE_SIZE_MB:-}" ]]; then
echo $((PG_EFFECTIVE_CACHE_SIZE_MB * MB / KB))
return
fi
case "$PG_DB_TYPE" in
"$DB_TYPE_WEB"|"$DB_TYPE_OLTP"|"$DB_TYPE_DW"|"$DB_TYPE_MIXED")
echo $((TOTAL_MEMORY_KB * 3 / 4))
;;
"$DB_TYPE_DESKTOP")
echo $((TOTAL_MEMORY_KB / 4))
;;
*)
echo $((TOTAL_MEMORY_KB * 3 / 4))
;;
esac
}
# Calculate maintenance_work_mem
calc_maintenance_work_mem() {
if [[ -n "${PG_MAINTENANCE_WORK_MEM_MB:-}" ]]; then
echo $((PG_MAINTENANCE_WORK_MEM_MB * MB / KB))
return
fi
local maint_mem_kb
case "$PG_DB_TYPE" in
"$DB_TYPE_DW")
maint_mem_kb=$((TOTAL_MEMORY_KB / 8))
;;
*)
maint_mem_kb=$((TOTAL_MEMORY_KB / 16))
;;
esac
# Cap at 2GB
local max_maint_mem=$((2 * GB / KB))
if [[ $maint_mem_kb -gt $max_maint_mem ]]; then
maint_mem_kb=$max_maint_mem
fi
echo "$maint_mem_kb"
}
# Calculate checkpoint settings
calc_checkpoint_settings() {
local min_wal_kb max_wal_kb
if [[ -n "${PG_MIN_WAL_SIZE_MB:-}" ]]; then
min_wal_kb=$((PG_MIN_WAL_SIZE_MB * MB / KB))
else
case "$PG_DB_TYPE" in
"$DB_TYPE_WEB"|"$DB_TYPE_MIXED") min_wal_kb=$((1024 * MB / KB)) ;;
"$DB_TYPE_OLTP") min_wal_kb=$((2048 * MB / KB)) ;;
"$DB_TYPE_DW") min_wal_kb=$((4096 * MB / KB)) ;;
"$DB_TYPE_DESKTOP") min_wal_kb=$((100 * MB / KB)) ;;
*) min_wal_kb=$((1024 * MB / KB)) ;;
esac
fi
if [[ -n "${PG_MAX_WAL_SIZE_MB:-}" ]]; then
max_wal_kb=$((PG_MAX_WAL_SIZE_MB * MB / KB))
else
case "$PG_DB_TYPE" in
"$DB_TYPE_WEB"|"$DB_TYPE_MIXED") max_wal_kb=$((4096 * MB / KB)) ;;
"$DB_TYPE_OLTP") max_wal_kb=$((8192 * MB / KB)) ;;
"$DB_TYPE_DW") max_wal_kb=$((16384 * MB / KB)) ;;
"$DB_TYPE_DESKTOP") max_wal_kb=$((2048 * MB / KB)) ;;
*) max_wal_kb=$((4096 * MB / KB)) ;;
esac
fi
echo "$min_wal_kb $max_wal_kb"
}
# Calculate wal_buffers
calc_wal_buffers() {
if [[ -n "${PG_WAL_BUFFERS_MB:-}" ]]; then
echo $((PG_WAL_BUFFERS_MB * MB / KB))
return
fi
local shared_buffers_kb=$1
local wal_buffers_kb=$((shared_buffers_kb * 3 / 100))
local max_wal_buffer=$((16 * MB / KB))
if [[ $wal_buffers_kb -gt $max_wal_buffer ]]; then
wal_buffers_kb=$max_wal_buffer
fi
# Round up to 16MB if close
local near_max=$((14 * MB / KB))
if [[ $wal_buffers_kb -gt $near_max && $wal_buffers_kb -lt $max_wal_buffer ]]; then
wal_buffers_kb=$max_wal_buffer
fi
# Minimum 32KB
if [[ $wal_buffers_kb -lt 32 ]]; then
wal_buffers_kb=32
fi
echo "$wal_buffers_kb"
}
# Calculate default_statistics_target
calc_default_statistics_target() {
if [[ -n "${PG_DEFAULT_STATISTICS_TARGET:-}" ]]; then
echo "$PG_DEFAULT_STATISTICS_TARGET"
return
fi
case "$PG_DB_TYPE" in
"$DB_TYPE_DW") echo 500 ;;
*) echo 100 ;;
esac
}
# Calculate random_page_cost
calc_random_page_cost() {
if [[ -n "${PG_RANDOM_PAGE_COST:-}" ]]; then
echo "$PG_RANDOM_PAGE_COST"
return
fi
case "$PG_STORAGE_TYPE" in
"$STORAGE_HDD") echo "4" ;;
"$STORAGE_SSD"|"$STORAGE_SAN") echo "1.1" ;;
*) echo "1.1" ;;
esac
}
# Calculate effective_io_concurrency
calc_effective_io_concurrency() {
if [[ -n "${PG_EFFECTIVE_IO_CONCURRENCY:-}" ]]; then
echo "$PG_EFFECTIVE_IO_CONCURRENCY"
return
fi
case "$PG_STORAGE_TYPE" in
"$STORAGE_HDD") echo 2 ;;
"$STORAGE_SSD") echo 200 ;;
"$STORAGE_SAN") echo 300 ;;
*) echo 200 ;;
esac
}
# Calculate parallel workers settings
# Echoes 4 space-separated values: max_worker_processes max_parallel_workers_per_gather max_parallel_workers max_parallel_maintenance_workers
# (single source of truth — generate_env_vars reads these instead of duplicating the logic)
calc_parallel_settings() {
local max_worker_processes max_parallel_workers_per_gather max_parallel_workers max_parallel_maintenance_workers
if [[ $CPU_COUNT -ge 4 ]]; then
local workers_per_gather=$((CPU_COUNT / 2))
# Cap at 4 for non-DW workloads
if [[ "$PG_DB_TYPE" != "$DB_TYPE_DW" && $workers_per_gather -gt 4 ]]; then
workers_per_gather=4
fi
local parallel_maint_workers=$((CPU_COUNT / 2))
if [[ $parallel_maint_workers -gt 4 ]]; then
parallel_maint_workers=4
fi
max_worker_processes=${PG_MAX_WORKER_PROCESSES:-$CPU_COUNT}
max_parallel_workers_per_gather=${PG_MAX_PARALLEL_WORKERS_PER_GATHER:-$workers_per_gather}
max_parallel_workers=${PG_MAX_PARALLEL_WORKERS:-$CPU_COUNT}
max_parallel_maintenance_workers=${PG_MAX_PARALLEL_MAINTENANCE_WORKERS:-$parallel_maint_workers}
else
max_worker_processes=${PG_MAX_WORKER_PROCESSES:-8}
max_parallel_workers_per_gather=${PG_MAX_PARALLEL_WORKERS_PER_GATHER:-2}
max_parallel_workers=${PG_MAX_PARALLEL_WORKERS:-8}
max_parallel_maintenance_workers=${PG_MAX_PARALLEL_MAINTENANCE_WORKERS:-2}
fi
echo "$max_worker_processes $max_parallel_workers_per_gather $max_parallel_workers $max_parallel_maintenance_workers"
}
# Calculate work_mem
calc_work_mem() {
if [[ -n "${PG_WORK_MEM_KB:-}" ]]; then
echo "$PG_WORK_MEM_KB"
return
fi
local shared_buffers_kb=$1
local max_connections=$2
# the actual computed worker count, passed in by generate_env_vars so the divisor stays
# consistent with the exported max_worker_processes (was previously assumed to be 8)
local max_worker_processes=${3:-${PG_MAX_WORKER_PROCESSES:-8}}
local work_mem_kb=$(( (TOTAL_MEMORY_KB - shared_buffers_kb) / ((max_connections + max_worker_processes) * 3) ))
case "$PG_DB_TYPE" in
"$DB_TYPE_DW"|"$DB_TYPE_MIXED"|"$DB_TYPE_DESKTOP")
work_mem_kb=$((work_mem_kb / 2))
;;
esac
# Floor for web/oltp/mixed app workloads: below ~16MB, many-join queries (sorts + hashes)
# constantly spill to disk-based algorithms writing temp files (measured multi-TB on a busy
# instance at 16.6MB with an oversized max_connections divisor). Other profiles keep 64KB.
local min_work_mem=64
case "$PG_DB_TYPE" in
"$DB_TYPE_WEB"|"$DB_TYPE_OLTP"|"$DB_TYPE_MIXED")
min_work_mem=$((16 * MB / KB))
;;
esac
if [[ $work_mem_kb -lt $min_work_mem ]]; then
work_mem_kb=$min_work_mem
fi
echo "$work_mem_kb"
}
# Calculate huge_pages
calc_huge_pages() {
if [[ -n "${PG_HUGE_PAGES:-}" ]]; then
echo "$PG_HUGE_PAGES"
return
fi
# Enable for systems with >= 32GB RAM
if [[ $TOTAL_MEMORY_KB -ge $((32 * GB / KB)) ]]; then
echo "try"
else
echo "off"
fi
}
# Calculate checkpoint_completion_target
calc_checkpoint_completion_target() {
echo "${PG_CHECKPOINT_COMPLETION_TARGET:-0.9}"
}
# Calculate autovacuum_max_workers (~1/3 of cores, min 3 which is also the PG default)
calc_autovacuum_max_workers() {
if [[ -n "${PG_AUTOVACUUM_MAX_WORKERS:-}" ]]; then
echo "$PG_AUTOVACUUM_MAX_WORKERS"
return
fi
local workers=$((CPU_COUNT / 3))
if [[ $workers -lt 3 ]]; then
workers=3
fi
echo "$workers"
}
# WAL compression: lz4 is cheaper than the pglz default but needs PG >= 15
calc_wal_compression() {
if [[ -n "${PG_WAL_COMPRESSION:-}" ]]; then
echo "$PG_WAL_COMPRESSION"
return
fi
if [[ "${PG_DB_VERSION%%.*}" -ge 15 ]]; then
echo "lz4"
else
echo "off"
fi
}
# TOAST compression for large values (post content etc.): lz4 needs PG >= 14
calc_toast_compression() {
if [[ -n "${PG_TOAST_COMPRESSION:-}" ]]; then
echo "$PG_TOAST_COMPRESSION"
return
fi
if [[ "${PG_DB_VERSION%%.*}" -ge 14 ]]; then
echo "lz4"
else
echo "pglz"
fi
}
# Main generation function - output as ENV vars
generate_env_vars() {
local max_connections shared_buffers_kb effective_cache_kb maint_work_mem_kb
local min_wal_kb max_wal_kb wal_buffers_kb work_mem_kb
local default_stats_target random_page_cost effective_io_concurrency
local huge_pages checkpoint_target
max_connections=$(calc_max_connections)
shared_buffers_kb=$(calc_shared_buffers)
effective_cache_kb=$(calc_effective_cache_size)
maint_work_mem_kb=$(calc_maintenance_work_mem)
read -r min_wal_kb max_wal_kb <<< "$(calc_checkpoint_settings)"
wal_buffers_kb=$(calc_wal_buffers "$shared_buffers_kb")
default_stats_target=$(calc_default_statistics_target)
random_page_cost=$(calc_random_page_cost)
effective_io_concurrency=$(calc_effective_io_concurrency)
huge_pages=$(calc_huge_pages)
checkpoint_target=$(calc_checkpoint_completion_target)
# Parallel settings (single source: calc_parallel_settings), needed BEFORE work_mem
# since the worker count is part of its divisor
local max_worker_processes max_parallel_workers_per_gather max_parallel_workers max_parallel_maintenance_workers
read -r max_worker_processes max_parallel_workers_per_gather max_parallel_workers max_parallel_maintenance_workers <<< "$(calc_parallel_settings)"
work_mem_kb=$(calc_work_mem "$shared_buffers_kb" "$max_connections" "$max_worker_processes")
local autovacuum_max_workers wal_compression toast_compression
autovacuum_max_workers=$(calc_autovacuum_max_workers)
wal_compression=$(calc_wal_compression)
toast_compression=$(calc_toast_compression)
# Output ENV vars (only if not already set)
cat << EOF
# PostgreSQL configuration calculated for: $PG_DB_TYPE workload, ${CPU_COUNT} CPUs, $(to_mb $TOTAL_MEMORY_KB)MB RAM, $PG_STORAGE_TYPE storage
export PG_MAX_CONNECTIONS=\${PG_MAX_CONNECTIONS:-$max_connections}
export PG_SHARED_BUFFERS_MB=\${PG_SHARED_BUFFERS_MB:-$(to_mb "$shared_buffers_kb")}
export PG_EFFECTIVE_CACHE_SIZE_MB=\${PG_EFFECTIVE_CACHE_SIZE_MB:-$(to_mb "$effective_cache_kb")}
export PG_MAINTENANCE_WORK_MEM_MB=\${PG_MAINTENANCE_WORK_MEM_MB:-$(to_mb "$maint_work_mem_kb")}
export PG_WORK_MEM_KB=\${PG_WORK_MEM_KB:-$work_mem_kb}
export PG_HUGE_PAGES=\${PG_HUGE_PAGES:-$huge_pages}
export PG_WAL_BUFFERS_MB=\${PG_WAL_BUFFERS_MB:-$(to_mb "$wal_buffers_kb")}
export PG_MIN_WAL_SIZE_MB=\${PG_MIN_WAL_SIZE_MB:-$(to_mb "$min_wal_kb")}
export PG_MAX_WAL_SIZE_MB=\${PG_MAX_WAL_SIZE_MB:-$(to_mb "$max_wal_kb")}
export PG_CHECKPOINT_COMPLETION_TARGET=\${PG_CHECKPOINT_COMPLETION_TARGET:-$checkpoint_target}
export PG_DEFAULT_STATISTICS_TARGET=\${PG_DEFAULT_STATISTICS_TARGET:-$default_stats_target}
export PG_RANDOM_PAGE_COST=\${PG_RANDOM_PAGE_COST:-$random_page_cost}
export PG_EFFECTIVE_IO_CONCURRENCY=\${PG_EFFECTIVE_IO_CONCURRENCY:-$effective_io_concurrency}
export PG_MAX_WORKER_PROCESSES=\${PG_MAX_WORKER_PROCESSES:-$max_worker_processes}
export PG_MAX_PARALLEL_WORKERS_PER_GATHER=\${PG_MAX_PARALLEL_WORKERS_PER_GATHER:-$max_parallel_workers_per_gather}
export PG_MAX_PARALLEL_WORKERS=\${PG_MAX_PARALLEL_WORKERS:-$max_parallel_workers}
export PG_MAX_PARALLEL_MAINTENANCE_WORKERS=\${PG_MAX_PARALLEL_MAINTENANCE_WORKERS:-$max_parallel_maintenance_workers}
# JIT: a per-execution LLVM compile tax on complex-but-fast app queries; off unless doing long analytics scans
export PG_JIT=\${PG_JIT:-off}
# observability: query stats extension (restart-required to change), I/O timing, full query texts in pg_stat_activity
export PG_PRELOAD_LIBS=\${PG_PRELOAD_LIBS:-pg_stat_statements}
export PG_TRACK_IO_TIMING=\${PG_TRACK_IO_TIMING:-on}
export PG_TRACK_ACTIVITY_QUERY_SIZE=\${PG_TRACK_ACTIVITY_QUERY_SIZE:-16384}
# autovacuum tuned for soft-delete/append app workloads (default 20% thresholds never trigger on big tables);
# per-table thresholds for the hottest tables also ship as an app migration
export PG_AUTOVACUUM_VACUUM_SCALE_FACTOR=\${PG_AUTOVACUUM_VACUUM_SCALE_FACTOR:-0.05}
export PG_AUTOVACUUM_VACUUM_INSERT_SCALE_FACTOR=\${PG_AUTOVACUUM_VACUUM_INSERT_SCALE_FACTOR:-0.05}
export PG_AUTOVACUUM_ANALYZE_SCALE_FACTOR=\${PG_AUTOVACUUM_ANALYZE_SCALE_FACTOR:-0.02}
export PG_AUTOVACUUM_VACUUM_COST_LIMIT=\${PG_AUTOVACUUM_VACUUM_COST_LIMIT:-1000}
export PG_AUTOVACUUM_MAX_WORKERS=\${PG_AUTOVACUUM_MAX_WORKERS:-$autovacuum_max_workers}
export PG_LOG_AUTOVACUUM_MIN_DURATION=\${PG_LOG_AUTOVACUUM_MIN_DURATION:-0}
# cheaper compression codecs (version-gated: wal lz4 needs PG15+, toast lz4 PG14+)
export PG_WAL_COMPRESSION=\${PG_WAL_COMPRESSION:-$wal_compression}
export PG_TOAST_COMPRESSION=\${PG_TOAST_COMPRESSION:-$toast_compression}
# diagnostics logging: slow statements (server-side; the app logs its own from 100ms), lock waits, temp-file spills
export PG_LOG_MIN_DURATION_STATEMENT=\${PG_LOG_MIN_DURATION_STATEMENT:-2000}
export PG_LOG_LOCK_WAITS=\${PG_LOG_LOCK_WAITS:-on}
export PG_LOG_TEMP_FILES=\${PG_LOG_TEMP_FILES:-0}
EOF
}
# Run generation
generate_env_vars
+835
View File
@@ -0,0 +1,835 @@
# -----------------------------
# PostgreSQL configuration file
# -----------------------------
#
# This file consists of lines of the form:
#
# name = value
#
# (The "=" is optional.) Whitespace may be used. Comments are introduced with
# "#" anywhere on a line. The complete list of parameter names and allowed
# values can be found in the PostgreSQL documentation.
#
# The commented-out settings shown in this file represent the default values.
# Re-commenting a setting is NOT sufficient to revert it to the default value;
# you need to reload the server.
#
# This file is read on server startup and when the server receives a SIGHUP
# signal. If you edit the file on a running system, you have to SIGHUP the
# server for the changes to take effect, run "pg_ctl reload", or execute
# "SELECT pg_reload_conf()". Some parameters, which are marked below,
# require a server shutdown and restart to take effect.
#
# Any parameter can also be given as a command-line option to the server, e.g.,
# "postgres -c log_connections=on". Some parameters can be changed at run time
# with the "SET" SQL command.
#
# Memory units: B = bytes Time units: us = microseconds
# kB = kilobytes ms = milliseconds
# MB = megabytes s = seconds
# GB = gigabytes min = minutes
# TB = terabytes h = hours
# d = days
#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
# The default values of these variables are driven from the -D command-line
# option or PGDATA environment variable, represented here as ConfigDir.
#data_directory = 'ConfigDir' # use data in another directory
# (change requires restart)
#hba_file = 'ConfigDir/pg_hba.conf' # host-based authentication file
# (change requires restart)
#ident_file = 'ConfigDir/pg_ident.conf' # ident configuration file
# (change requires restart)
# If external_pid_file is not explicitly set, no extra PID file is written.
#external_pid_file = '' # write an extra PID file
# (change requires restart)
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------
# - Connection Settings -
listen_addresses = '*' # comma-separated list of addresses; defaults to 'localhost'; use '*' for all
max_connections = ${PG_MAX_CONNECTIONS}
#port = 5432 # (change requires restart)
#reserved_connections = 0 # (change requires restart)
#superuser_reserved_connections = 3 # (change requires restart)
#unix_socket_directories = '/tmp' # comma-separated list of directories
# (change requires restart)
#unix_socket_group = '' # (change requires restart)
#unix_socket_permissions = 0777 # begin with 0 to use octal notation
# (change requires restart)
#bonjour = off # advertise server via Bonjour
# (change requires restart)
#bonjour_name = '' # defaults to the computer name
# (change requires restart)
# - TCP settings -
# see "man tcp" for details
#tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds;
# 0 selects the system default
#tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds;
# 0 selects the system default
#tcp_keepalives_count = 0 # TCP_KEEPCNT;
# 0 selects the system default
#tcp_user_timeout = 0 # TCP_USER_TIMEOUT, in milliseconds;
# 0 selects the system default
#client_connection_check_interval = 0 # time between checks for client
# disconnection while running queries;
# 0 for never
# - Authentication -
#authentication_timeout = 1min # 1s-600s
#password_encryption = scram-sha-256 # scram-sha-256 or md5
#scram_iterations = 4096
#db_user_namespace = off
# GSSAPI using Kerberos
#krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab'
#krb_caseins_users = off
#gss_accept_delegation = off
# - SSL -
#ssl = off
#ssl_ca_file = ''
#ssl_cert_file = 'server.crt'
#ssl_crl_file = ''
#ssl_crl_dir = ''
#ssl_key_file = 'server.key'
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
#ssl_prefer_server_ciphers = on
#ssl_ecdh_curve = 'prime256v1'
#ssl_min_protocol_version = 'TLSv1.2'
#ssl_max_protocol_version = ''
#ssl_dh_params_file = ''
#ssl_passphrase_command = ''
#ssl_passphrase_command_supports_reload = off
#------------------------------------------------------------------------------
# RESOURCE USAGE (except WAL)
#------------------------------------------------------------------------------
# - Memory -
shared_buffers = ${PG_SHARED_BUFFERS_MB}MB # min 128kB
huge_pages = ${PG_HUGE_PAGES} # on, off, or try
work_mem = ${PG_WORK_MEM_KB}kB # min 64kB
maintenance_work_mem = ${PG_MAINTENANCE_WORK_MEM_MB}MB # min 1MB
#huge_page_size = 0 # zero for system default
#temp_buffers = 8MB # min 800kB
#max_prepared_transactions = 0 # zero disables the feature
# (change requires restart)
# Caution: it is not advisable to set max_prepared_transactions nonzero unless
# you actively intend to use prepared transactions.
#hash_mem_multiplier = 2.0 # 1-1000.0 multiplier on hash table work_mem
#maintenance_work_mem = 64MB # min 1MB
#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem
#logical_decoding_work_mem = 64MB # min 64kB
#max_stack_depth = 2MB # min 100kB
#shared_memory_type = mmap # the default is the first option
# supported by the operating system:
# mmap
# sysv
# windows
# (change requires restart)
#dynamic_shared_memory_type = posix # the default is usually the first option
# supported by the operating system:
# posix
# sysv
# windows
# mmap
# (change requires restart)
#min_dynamic_shared_memory = 0MB # (change requires restart)
#vacuum_buffer_usage_limit = 256kB # size of vacuum and analyze buffer access strategy ring;
# 0 to disable vacuum buffer access strategy;
# range 128kB to 16GB
# - Disk -
#temp_file_limit = -1 # limits per-process temp file space
# in kilobytes, or -1 for no limit
# - Kernel Resources -
#max_files_per_process = 1000 # min 64
# (change requires restart)
# - Cost-Based Vacuum Delay -
#vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables)
#vacuum_cost_page_hit = 1 # 0-10000 credits
#vacuum_cost_page_miss = 2 # 0-10000 credits
#vacuum_cost_page_dirty = 20 # 0-10000 credits
#vacuum_cost_limit = 200 # 1-10000 credits
# - Background Writer -
#bgwriter_delay = 200ms # 10-10000ms between rounds
#bgwriter_lru_maxpages = 100 # max buffers written/round, 0 disables
#bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round
#bgwriter_flush_after = 0 # measured in pages, 0 disables
# - Asynchronous Behavior -
#backend_flush_after = 0 # measured in pages, 0 disables
effective_io_concurrency = ${PG_EFFECTIVE_IO_CONCURRENCY} # 1-1000; 0 disables prefetching
max_worker_processes = ${PG_MAX_WORKER_PROCESSES}
max_parallel_workers_per_gather = ${PG_MAX_PARALLEL_WORKERS_PER_GATHER} # limited by max_parallel_workers
max_parallel_maintenance_workers = ${PG_MAX_PARALLEL_MAINTENANCE_WORKERS} # limited by max_parallel_workers
max_parallel_workers = ${PG_MAX_PARALLEL_WORKERS} # number of max_worker_processes that can be used in parallel operations
#maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching
#parallel_leader_participation = on
#old_snapshot_threshold = -1 # 1min-60d; -1 disables; 0 is immediate
# (change requires restart)
#------------------------------------------------------------------------------
# WRITE-AHEAD LOG
#------------------------------------------------------------------------------
# - Settings -
wal_buffers = ${PG_WAL_BUFFERS_MB}MB # min 32kB, -1 sets based on shared_buffers
#wal_level = replica # minimal, replica, or logical
# (change requires restart)
#fsync = on # flush data to disk for crash safety
# (turning this off can cause
# unrecoverable data corruption)
#synchronous_commit = on # synchronization level;
# off, local, remote_write, remote_apply, or on
#wal_sync_method = fsync # the default is the first option
# supported by the operating system:
# open_datasync
# fdatasync (default on Linux and FreeBSD)
# fsync
# fsync_writethrough
# open_sync
#full_page_writes = on # recover from partial page writes
#wal_log_hints = off # also do full page writes of non-critical updates
# (change requires restart)
wal_compression = ${PG_WAL_COMPRESSION} # cheaper full-page writes (lz4 on PG15+; computed by postgres-tune.sh)
#wal_compression = off # enables compression of full-page writes;
# off, pglz, lz4, zstd, or on
#wal_init_zero = on # zero-fill new WAL files
#wal_recycle = on # recycle WAL files
#wal_writer_delay = 200ms # 1-10000 milliseconds
#wal_writer_flush_after = 1MB # measured in pages, 0 disables
#wal_skip_threshold = 2MB
#commit_delay = 0 # range 0-100000, in microseconds
#commit_siblings = 5 # range 1-1000
# - Checkpoints -
#checkpoint_timeout = 5min # range 30s-1d
checkpoint_completion_target = ${PG_CHECKPOINT_COMPLETION_TARGET} # checkpoint target duration, 0.0 - 1.0
#checkpoint_flush_after = 0 # measured in pages, 0 disables
#checkpoint_warning = 30s # 0 disables
max_wal_size = ${PG_MAX_WAL_SIZE_MB}MB
min_wal_size = ${PG_MIN_WAL_SIZE_MB}MB
# - Prefetching during recovery -
#recovery_prefetch = try # prefetch pages referenced in the WAL?
#wal_decode_buffer_size = 512kB # lookahead window used for prefetching
# (change requires restart)
# - Archiving -
#archive_mode = off # enables archiving; off, on, or always
# (change requires restart)
#archive_library = '' # library to use to archive a WAL file
# (empty string indicates archive_command should
# be used)
#archive_command = '' # command to use to archive a WAL file
# placeholders: %p = path of file to archive
# %f = file name only
# e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
#archive_timeout = 0 # force a WAL file switch after this
# number of seconds; 0 disables
# - Archive Recovery -
# These are only used in recovery mode.
#restore_command = '' # command to use to restore an archived WAL file
# placeholders: %p = path of file to restore
# %f = file name only
# e.g. 'cp /mnt/server/archivedir/%f %p'
#archive_cleanup_command = '' # command to execute at every restartpoint
#recovery_end_command = '' # command to execute at completion of recovery
# - Recovery Target -
# Set these only when performing a targeted recovery.
#recovery_target = '' # 'immediate' to end recovery as soon as a
# consistent state is reached
# (change requires restart)
#recovery_target_name = '' # the named restore point to which recovery will proceed
# (change requires restart)
#recovery_target_time = '' # the time stamp up to which recovery will proceed
# (change requires restart)
#recovery_target_xid = '' # the transaction ID up to which recovery will proceed
# (change requires restart)
#recovery_target_lsn = '' # the WAL LSN up to which recovery will proceed
# (change requires restart)
#recovery_target_inclusive = on # Specifies whether to stop:
# just after the specified recovery target (on)
# just before the recovery target (off)
# (change requires restart)
#recovery_target_timeline = 'latest' # 'current', 'latest', or timeline ID
# (change requires restart)
#recovery_target_action = 'pause' # 'pause', 'promote', 'shutdown'
# (change requires restart)
#------------------------------------------------------------------------------
# REPLICATION
#------------------------------------------------------------------------------
# - Sending Servers -
# Set these on the primary and on any standby that will send replication data.
#max_wal_senders = 10 # max number of walsender processes
# (change requires restart)
#max_replication_slots = 10 # max number of replication slots
# (change requires restart)
#wal_keep_size = 0 # in megabytes; 0 disables
#max_slot_wal_keep_size = -1 # in megabytes; -1 disables
#wal_sender_timeout = 60s # in milliseconds; 0 disables
#track_commit_timestamp = off # collect timestamp of transaction commit
# (change requires restart)
# - Primary Server -
# These settings are ignored on a standby server.
#synchronous_standby_names = '' # standby servers that provide sync rep
# method to choose sync standbys, number of sync standbys,
# and comma-separated list of application_name
# from standby(s); '*' = all
# - Standby Servers -
# These settings are ignored on a primary server.
#primary_conninfo = '' # connection string to sending server
#primary_slot_name = '' # replication slot on sending server
#hot_standby = on # "off" disallows queries during recovery
# (change requires restart)
#max_standby_archive_delay = 30s # max delay before canceling queries
# when reading WAL from archive;
# -1 allows indefinite delay
#max_standby_streaming_delay = 30s # max delay before canceling queries
# when reading streaming WAL;
# -1 allows indefinite delay
#wal_receiver_create_temp_slot = off # create temp slot if primary_slot_name
# is not set
#wal_receiver_status_interval = 10s # send replies at least this often
# 0 disables
#hot_standby_feedback = off # send info from standby to prevent
# query conflicts
#wal_receiver_timeout = 60s # time that receiver waits for
# communication from primary
# in milliseconds; 0 disables
#wal_retrieve_retry_interval = 5s # time to wait before retrying to
# retrieve WAL after a failed attempt
#recovery_min_apply_delay = 0 # minimum delay for applying changes during recovery
# - Subscribers -
# These settings are ignored on a publisher.
#max_logical_replication_workers = 4 # taken from max_worker_processes
# (change requires restart)
#max_sync_workers_per_subscription = 2 # taken from max_logical_replication_workers
#max_parallel_apply_workers_per_subscription = 2 # taken from max_logical_replication_workers
#------------------------------------------------------------------------------
# QUERY TUNING
#------------------------------------------------------------------------------
# - Planner Method Configuration -
#enable_async_append = on
#enable_bitmapscan = on
#enable_gathermerge = on
#enable_hashagg = on
#enable_hashjoin = on
#enable_incremental_sort = on
#enable_indexscan = on
#enable_indexonlyscan = on
#enable_material = on
#enable_memoize = on
#enable_mergejoin = on
#enable_nestloop = on
#enable_parallel_append = on
#enable_parallel_hash = on
#enable_partition_pruning = on
#enable_partitionwise_join = off
#enable_partitionwise_aggregate = off
#enable_presorted_aggregate = on
#enable_seqscan = on
#enable_sort = on
#enable_tidscan = on
# - Planner Cost Constants -
#seq_page_cost = 1.0 # measured on an arbitrary scale
random_page_cost = ${PG_RANDOM_PAGE_COST} # same scale as above
#cpu_tuple_cost = 0.01 # same scale as above
#cpu_index_tuple_cost = 0.005 # same scale as above
#cpu_operator_cost = 0.0025 # same scale as above
#parallel_setup_cost = 1000.0 # same scale as above
#parallel_tuple_cost = 0.1 # same scale as above
#min_parallel_table_scan_size = 8MB
#min_parallel_index_scan_size = 512kB
effective_cache_size = ${PG_EFFECTIVE_CACHE_SIZE_MB}MB
#jit_above_cost = 100000 # perform JIT compilation if available
# and query more expensive than this;
# -1 disables
#jit_inline_above_cost = 500000 # inline small functions if query is
# more expensive than this; -1 disables
#jit_optimize_above_cost = 500000 # use expensive JIT optimizations if
# query is more expensive than this;
# -1 disables
# - Genetic Query Optimizer -
#geqo = on
#geqo_threshold = 12
#geqo_effort = 5 # range 1-10
#geqo_pool_size = 0 # selects default based on effort
#geqo_generations = 0 # selects default based on effort
#geqo_selection_bias = 2.0 # range 1.5-2.0
#geqo_seed = 0.0 # range 0.0-1.0
# - Other Planner Options -
default_statistics_target = ${PG_DEFAULT_STATISTICS_TARGET} # range 1-10000
#constraint_exclusion = partition # on, off, or partition
#cursor_tuple_fraction = 0.1 # range 0.0-1.0
#from_collapse_limit = 8
jit = ${PG_JIT} # per-execution LLVM compile tax on complex-but-fast app queries; off by default (tune with PG_JIT)
#jit = on # allow JIT compilation
#join_collapse_limit = 8 # 1 disables collapsing of explicit
# JOIN clauses
#plan_cache_mode = auto # auto, force_generic_plan or
# force_custom_plan
#recursive_worktable_factor = 10.0 # range 0.001-1000000
#------------------------------------------------------------------------------
# REPORTING AND LOGGING
#------------------------------------------------------------------------------
# - Where to Log -
#log_destination = 'stderr' # Valid values are combinations of
# stderr, csvlog, jsonlog, syslog, and
# eventlog, depending on platform.
# csvlog and jsonlog require
# logging_collector to be on.
# This is used when logging to stderr:
#logging_collector = off # Enable capturing of stderr, jsonlog,
# and csvlog into log files. Required
# to be on for csvlogs and jsonlogs.
# (change requires restart)
# These are only used if logging_collector is on:
#log_directory = 'log' # directory where log files are written,
# can be absolute or relative to PGDATA
#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern,
# can include strftime() escapes
#log_file_mode = 0600 # creation mode for log files,
# begin with 0 to use octal notation
#log_rotation_age = 1d # Automatic rotation of logfiles will
# happen after that time. 0 disables.
#log_rotation_size = 10MB # Automatic rotation of logfiles will
# happen after that much log output.
# 0 disables.
#log_truncate_on_rotation = off # If on, an existing log file with the
# same name as the new log file will be
# truncated rather than appended to.
# But such truncation only occurs on
# time-driven rotation, not on restarts
# or size-driven rotation. Default is
# off, meaning append to existing files
# in all cases.
# These are relevant when logging to syslog:
#syslog_facility = 'LOCAL0'
#syslog_ident = 'postgres'
#syslog_sequence_numbers = on
#syslog_split_messages = on
# This is only relevant when logging to eventlog (Windows):
# (change requires restart)
#event_source = 'PostgreSQL'
# - When to Log -
#log_min_messages = warning # values in order of decreasing detail:
# debug5
# debug4
# debug3
# debug2
# debug1
# info
# notice
# warning
# error
# log
# fatal
# panic
#log_min_error_statement = error # values in order of decreasing detail:
# debug5
# debug4
# debug3
# debug2
# debug1
# info
# notice
# warning
# error
# log
# fatal
# panic (effectively off)
log_min_duration_statement = ${PG_LOG_MIN_DURATION_STATEMENT} # server-side slow-statement log (the app logs its own from 100ms)
#log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements
# and their durations, > 0 logs only
# statements running at least this number
# of milliseconds
#log_min_duration_sample = -1 # -1 is disabled, 0 logs a sample of statements
# and their durations, > 0 logs only a sample of
# statements running at least this number
# of milliseconds;
# sample fraction is determined by log_statement_sample_rate
#log_statement_sample_rate = 1.0 # fraction of logged statements exceeding
# log_min_duration_sample to be logged;
# 1.0 logs all such statements, 0.0 never logs
#log_transaction_sample_rate = 0.0 # fraction of transactions whose statements
# are logged regardless of their duration; 1.0 logs all
# statements from all transactions, 0.0 never logs
#log_startup_progress_interval = 10s # Time between progress updates for
# long-running startup operations.
# 0 disables the feature, > 0 indicates
# the interval in milliseconds.
# - What to Log -
#debug_print_parse = off
#debug_print_rewritten = off
#debug_print_plan = off
#debug_pretty_print = on
log_autovacuum_min_duration = ${PG_LOG_AUTOVACUUM_MIN_DURATION} # log every autovacuum run — the regression tripwire for autovacuum-never-runs
#log_autovacuum_min_duration = 10min # log autovacuum activity;
# -1 disables, 0 logs all actions and
# their durations, > 0 logs only
# actions running at least this number
# of milliseconds.
#log_checkpoints = on
#log_connections = off
#log_disconnections = off
#log_duration = off
#log_error_verbosity = default # terse, default, or verbose messages
#log_hostname = off
#log_line_prefix = '%m [%p] ' # special values:
# %a = application name
# %u = user name
# %d = database name
# %r = remote host and port
# %h = remote host
# %b = backend type
# %p = process ID
# %P = process ID of parallel group leader
# %t = timestamp without milliseconds
# %m = timestamp with milliseconds
# %n = timestamp with milliseconds (as a Unix epoch)
# %Q = query ID (0 if none or not computed)
# %i = command tag
# %e = SQL state
# %c = session ID
# %l = session line number
# %s = session start timestamp
# %v = virtual transaction ID
# %x = transaction ID (0 if none)
# %q = stop here in non-session
# processes
# %% = '%'
# e.g. '<%u%%%d> '
log_lock_waits = ${PG_LOG_LOCK_WAITS}
#log_lock_waits = off # log lock waits >= deadlock_timeout
#log_recovery_conflict_waits = off # log standby recovery conflict waits
# >= deadlock_timeout
#log_parameter_max_length = -1 # when logging statements, limit logged
# bind-parameter values to N bytes;
# -1 means print in full, 0 disables
#log_parameter_max_length_on_error = 0 # when logging an error, limit logged
# bind-parameter values to N bytes;
# -1 means print in full, 0 disables
#log_statement = 'none' # none, ddl, mod, all
#log_replication_commands = off
log_temp_files = ${PG_LOG_TEMP_FILES} # log all temp-file spills (the work_mem-too-small signal)
#log_temp_files = -1 # log temporary files equal or larger
# than the specified size in kilobytes;
# -1 disables, 0 logs all temp files
#log_timezone = 'GMT'
# - Process Title -
#cluster_name = '' # added to process titles if nonempty
# (change requires restart)
#update_process_title = on
#------------------------------------------------------------------------------
# STATISTICS
#------------------------------------------------------------------------------
# - Cumulative Query and Index Statistics -
#track_activities = on
track_activity_query_size = ${PG_TRACK_ACTIVITY_QUERY_SIZE} # full query texts in pg_stat_activity (change requires restart)
#track_activity_query_size = 1024 # (change requires restart)
#track_counts = on
track_io_timing = ${PG_TRACK_IO_TIMING} # needed for pg_stat_statements I/O attribution
#track_io_timing = off
#track_wal_io_timing = off
#track_functions = none # none, pl, all
#stats_fetch_consistency = cache # cache, none, snapshot
# - Monitoring -
#compute_query_id = auto
#log_statement_stats = off
#log_parser_stats = off
#log_planner_stats = off
#log_executor_stats = off
#------------------------------------------------------------------------------
# AUTOVACUUM
#------------------------------------------------------------------------------
#autovacuum = on # Enable autovacuum subprocess? 'on'
# requires track_counts to also be on.
autovacuum_max_workers = ${PG_AUTOVACUUM_MAX_WORKERS} # (change requires restart)
#autovacuum_max_workers = 3 # max number of autovacuum subprocesses
# (change requires restart)
#autovacuum_naptime = 1min # time between autovacuum runs
#autovacuum_vacuum_threshold = 50 # min number of row updates before
# vacuum
#autovacuum_vacuum_insert_threshold = 1000 # min number of row inserts
# before vacuum; -1 disables insert
# vacuums
#autovacuum_analyze_threshold = 50 # min number of row updates before
# analyze
autovacuum_vacuum_scale_factor = ${PG_AUTOVACUUM_VACUUM_SCALE_FACTOR} # default 0.2 never triggers on big tables
#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum
autovacuum_vacuum_insert_scale_factor = ${PG_AUTOVACUUM_VACUUM_INSERT_SCALE_FACTOR} # key for append-mostly workloads: keeps visibility maps fresh for index-only scans
#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table
# size before insert vacuum
autovacuum_analyze_scale_factor = ${PG_AUTOVACUUM_ANALYZE_SCALE_FACTOR}
#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze
#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum
# (change requires restart)
#autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age
# before forced vacuum
# (change requires restart)
#autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for
# autovacuum, in milliseconds;
# -1 means use vacuum_cost_delay
autovacuum_vacuum_cost_limit = ${PG_AUTOVACUUM_VACUUM_COST_LIMIT} # default (200 via vacuum_cost_limit) is glacial on multi-GB tables
#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for
# autovacuum, -1 means use
# vacuum_cost_limit
#------------------------------------------------------------------------------
# CLIENT CONNECTION DEFAULTS
#------------------------------------------------------------------------------
# - Statement Behavior -
#client_min_messages = notice # values in order of decreasing detail:
# debug5
# debug4
# debug3
# debug2
# debug1
# log
# notice
# warning
# error
#search_path = '"$user", public' # schema names
#row_security = on
#default_table_access_method = 'heap'
#default_tablespace = '' # a tablespace name, '' uses the default
default_toast_compression = ${PG_TOAST_COMPRESSION} # lz4 on PG14+ (computed by postgres-tune.sh)
#default_toast_compression = 'pglz' # 'pglz' or 'lz4'
#temp_tablespaces = '' # a list of tablespace names, '' uses
# only default tablespace
#check_function_bodies = on
#default_transaction_isolation = 'read committed'
#default_transaction_read_only = off
#default_transaction_deferrable = off
#session_replication_role = 'origin'
#statement_timeout = 0 # in milliseconds, 0 is disabled
#lock_timeout = 0 # in milliseconds, 0 is disabled
#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled
#idle_session_timeout = 0 # in milliseconds, 0 is disabled
#vacuum_freeze_table_age = 150000000
#vacuum_freeze_min_age = 50000000
#vacuum_failsafe_age = 1600000000
#vacuum_multixact_freeze_table_age = 150000000
#vacuum_multixact_freeze_min_age = 5000000
#vacuum_multixact_failsafe_age = 1600000000
#bytea_output = 'hex' # hex, escape
#xmlbinary = 'base64'
#xmloption = 'content'
#gin_pending_list_limit = 4MB
#createrole_self_grant = '' # set and/or inherit
# - Locale and Formatting -
#datestyle = 'iso, mdy'
#intervalstyle = 'postgres'
#timezone = 'GMT'
#timezone_abbreviations = 'Default' # Select the set of available time zone
# abbreviations. Currently, there are
# Default
# Australia (historical usage)
# India
# You can create your own file in
# share/timezonesets/.
#extra_float_digits = 1 # min -15, max 3; any value >0 actually
# selects precise output mode
#client_encoding = sql_ascii # actually, defaults to database
# encoding
# These settings are initialized by initdb, but they can be changed.
#lc_messages = '' # locale for system error message
# strings
#lc_monetary = 'C' # locale for monetary formatting
#lc_numeric = 'C' # locale for number formatting
#lc_time = 'C' # locale for time formatting
#icu_validation_level = warning # report ICU locale validation
# errors at the given level
# default configuration for text search
#default_text_search_config = 'pg_catalog.simple'
# - Shared Library Preloading -
#local_preload_libraries = ''
#session_preload_libraries = ''
shared_preload_libraries = '${PG_PRELOAD_LIBS}' # pg_stat_statements etc. (change requires restart)
#shared_preload_libraries = '' # (change requires restart)
#jit_provider = 'llvmjit' # JIT library to use
# - Other Defaults -
#dynamic_library_path = '$libdir'
#extension_destdir = '' # prepend path when loading extensions
# and shared objects (added by Debian)
#gin_fuzzy_search_limit = 0
#------------------------------------------------------------------------------
# LOCK MANAGEMENT
#------------------------------------------------------------------------------
#deadlock_timeout = 1s
#max_locks_per_transaction = 64 # min 10
# (change requires restart)
#max_pred_locks_per_transaction = 64 # min 10
# (change requires restart)
#max_pred_locks_per_relation = -2 # negative values mean
# (max_pred_locks_per_transaction
# / -max_pred_locks_per_relation) - 1
#max_pred_locks_per_page = 2 # min 0
#------------------------------------------------------------------------------
# VERSION AND PLATFORM COMPATIBILITY
#------------------------------------------------------------------------------
# - Previous PostgreSQL Versions -
#array_nulls = on
#backslash_quote = safe_encoding # on, off, or safe_encoding
#escape_string_warning = on
#lo_compat_privileges = off
#quote_all_identifiers = off
#standard_conforming_strings = on
#synchronize_seqscans = on
# - Other Platforms and Clients -
#transform_null_equals = off
#------------------------------------------------------------------------------
# ERROR HANDLING
#------------------------------------------------------------------------------
#exit_on_error = off # terminate session on any error?
#restart_after_crash = on # reinitialize after backend crash?
#data_sync_retry = off # retry or panic on failure to fsync
# data?
# (change requires restart)
#recovery_init_sync_method = fsync # fsync, syncfs (Linux 5.8+)
#------------------------------------------------------------------------------
# CONFIG FILE INCLUDES
#------------------------------------------------------------------------------
# These options allow settings to be loaded from files other than the
# default postgresql.conf. Note that these are directives, not variable
# assignments, so they can usefully be given more than once.
#include_dir = '...' # include files ending in '.conf' from
# a directory, e.g., 'conf.d'
#include_if_exists = '...' # include file only if it exists
#include = '...' # include file
#------------------------------------------------------------------------------
# CUSTOMIZED OPTIONS
#------------------------------------------------------------------------------
# Add settings for extensions here
pg_stat_statements.track = all
+1
View File
@@ -0,0 +1 @@
ATTENTION: this is the first release and contains a couple of breaking changes in comparison to the previously unreleased recipe. There are a lot of secrets, keys and passwords moved to docker secrets, and the .env.sample was completly restructured. It is recommended to start your env file from scratch from the new template to make sure nothing is missing.
+6
View File
@@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
]
}
+43
View File
@@ -0,0 +1,43 @@
# Sonic configuration
# https://github.com/valeriansaliou/sonic/blob/master/CONFIGURATION.md
[server]
log_level = "error"
[channel]
inet = "0.0.0.0:1491"
tcp_timeout = 300
[channel.search]
query_limit_default = 10
query_limit_maximum = 200
suggest_limit_default = 5
suggest_limit_maximum = 20
[store.kv]
path = "/var/lib/sonic/store/kv/"
retain_word_objects = 1000
[store.kv.pool]
inactive_after = 1800
[store.kv.database]
flush_after = 900
compress = true
parallelism = 2
max_files = 100
max_compactions = 1
max_flushes = 1
write_buffer = 16384
write_ahead_log = true
[store.fst]
path = "/var/lib/sonic/store/fst/"
[store.fst.pool]
inactive_after = 300
[store.fst.graph]
consolidate_after = 180
max_size = 2048
max_words = 250000
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
export SONIC_CHANNEL__AUTH_PASSWORD="$(cat /run/secrets/sonic_password)"
exec sonic -c /etc/sonic.cfg