forked from coop-cloud/bonfire
Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e620c70403 | |||
| 79a43dbadc | |||
| 466ff8e447 | |||
| d74f05c0d1 | |||
| df3229884d | |||
| 87f9209cd5 | |||
| 8c4d9cce46 | |||
| 5a183a0579 | |||
| 197c18a9b2 | |||
| 21a00c23c3 | |||
| f1499d6fda | |||
| 061a986d72 | |||
| 15b48c6033 | |||
| d3d5973ff6 | |||
| d6ce1547c9 | |||
| 7747970d1c | |||
| c9d2f4e7da | |||
| 6f1dd8db55 | |||
| f278be788c | |||
| 63ba064930 | |||
| 6588ce03ea | |||
| 38cbbf770c | |||
| 9082523712 | |||
| 6c5e6c64ea | |||
| 257918125f | |||
| a81c2123d1 | |||
| 969fcbd25b | |||
| f3c58df3c6 | |||
| 6142dde5fb | |||
| 31719f1fd3 | |||
| 0dbbb1d57e | |||
| 16236fe177 | |||
| 621781820e | |||
| 7938130edd | |||
| bd78cce74c | |||
| 5f610c96ce | |||
| 1bdd42fa9f | |||
| 4195dafa38 | |||
| 4371d2fedf | |||
| 0c1f6038d6 | |||
| e0291cb1fa | |||
| 966c717638 | |||
| 853832355a | |||
| d52472eb3b | |||
| 52dfa64b61 | |||
| 847306e168 | |||
| 8fcf1d4bcb | |||
| 4521bd7f81 | |||
| f1e5ad0f76 | |||
| 23ffe6b17d | |||
| 12813a3900 | |||
| 7f82ad0da8 | |||
| 992284418a | |||
| e619a451f0 | |||
| bbd3d9e989 | |||
| f4a1658d38 | |||
| 083ddc8516 | |||
| 1843f0ee27 | |||
| fb9c6a9faa | |||
| c92c669f39 | |||
| 6c0dd9d3cb | |||
| a5d24231e8 | |||
| 8beb727d24 | |||
| b0cc2dd9c2 |
+189
-68
@@ -1,20 +1,13 @@
|
||||
TYPE=bonfire
|
||||
|
||||
# choose what flavour of Bonfire to run
|
||||
FLAVOUR=classic
|
||||
LETS_ENCRYPT_ENV=production
|
||||
|
||||
# Different flavours/forks or architectures may require different builds of bonfire:
|
||||
# for ARM (manual build):
|
||||
APP_DOCKER_IMAGE=bonfirenetworks/bonfire:latest-${FLAVOUR}-aarch64
|
||||
for x86 (built by CI):
|
||||
APP_DOCKER_IMAGE=bonfirenetworks/bonfire:latest-${FLAVOUR}-amd64
|
||||
# multi-arch image (built by CI, but currently not working):
|
||||
#APP_DOCKER_IMAGE=bonfirenetworks/bonfire:latest-${FLAVOUR}
|
||||
|
||||
# different flavours or architectures may require different postgres builds:
|
||||
DB_DOCKER_IMAGE=postgres:12-alpine
|
||||
#DB_DOCKER_IMAGE=postgis/postgis:12-3.2-alpine
|
||||
#DB_DOCKER_IMAGE=ghcr.io/baosystems/postgis:12-3.2
|
||||
# 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
|
||||
@@ -22,78 +15,206 @@ DOMAIN=bonfire.example.com
|
||||
## Domain aliases
|
||||
#EXTRA_DOMAINS=', `www.bonfire.example.com`'
|
||||
|
||||
# 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=mailgun
|
||||
# enable abra backups
|
||||
ENABLE_BACKUPS=true
|
||||
|
||||
# require an email address to be invited before being able to sign up? (true or false)
|
||||
INVITE_ONLY=true
|
||||
COMPOSE_FILE="compose.yml"
|
||||
|
||||
# ====================================
|
||||
# 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
|
||||
|
||||
# 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"
|
||||
|
||||
# ====================================
|
||||
## BASIC_AUTH
|
||||
|
||||
## 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
|
||||
|
||||
# ====================================
|
||||
# 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_FROM=admin@example.com
|
||||
# MAIL_PROJECT_ID=
|
||||
# MAIL_BASE_URI=
|
||||
# MAIL_REGION=
|
||||
# MAIL_SESSION_TOKEN=
|
||||
# MAIL_SERVER=
|
||||
# MAIL_USER=
|
||||
# MAIL_PORT=
|
||||
# MAIL_SSL=true
|
||||
# MAIL_TLS=if_available
|
||||
# MAIL_SMTP_AUTH=
|
||||
# MAIL_RETRIES=
|
||||
# MAIL_ARGS=
|
||||
|
||||
# ====================================
|
||||
# UPLOADS
|
||||
|
||||
# max file upload size - default is 20 meg
|
||||
UPLOAD_LIMIT=20000000
|
||||
|
||||
DB_MEMORY_LIMIT=1000M
|
||||
# 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_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=
|
||||
|
||||
# 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
|
||||
|
||||
#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=
|
||||
|
||||
# ====================================
|
||||
# SECRETS
|
||||
# these secrets will be autogenerated/managed by abra and docker
|
||||
|
||||
# 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:
|
||||
|
||||
# if `INVITE_ONLY` is true, what should be the secret code to sign up?
|
||||
INVITE_KEY=123
|
||||
|
||||
# signup to mailgun.com and edit with your domain and API key
|
||||
MAIL_DOMAIN=mgo.example.com
|
||||
MAIL_KEY=xyz
|
||||
MAIL_FROM=admin@example.com
|
||||
|
||||
# error reporting
|
||||
SENTRY_DSN=
|
||||
|
||||
# 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=
|
||||
|
||||
# Bonfire extensions configs:
|
||||
WEB_PUSH_SUBJECT=mailto:admin@example.com
|
||||
WEB_PUSH_PUBLIC_KEY=xyz
|
||||
WEB_PUSH_PRIVATE_KEY=abc
|
||||
GEOLOCATE_OPENCAGEDATA=
|
||||
GITHUB_TOKEN=xyz
|
||||
|
||||
# ====================================
|
||||
# these secrets will be autogenerated/managed by abra and docker"
|
||||
SECRET_POSTGRES_PASSWORD_VERSION=v1
|
||||
SECRET_MEILI_MASTER_KEY_VERSION=v1
|
||||
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
|
||||
|
||||
@@ -15,17 +15,22 @@ A [coop-cloud](https://coopcloud.tech) recipe for deploying [Bonfire](https://bo
|
||||
|
||||
## Basic usage
|
||||
|
||||
1. Install [`abra`] on your computer
|
||||
2. Prepare your server with `abra server add --provision your-server.domain.name server_username 22`
|
||||
3. Deploy the [`coop-cloud/traefik`] proxy if you haven't already
|
||||
3. `abra app new --secrets bonfire`
|
||||
4. `abra app config your-server.domain.name` to check and edit the config (there are comments to explain the different options)
|
||||
5. `abra app deploy your-server.domain.name`
|
||||
1. Set up Docker Swarm and [`abra`]
|
||||
2. Deploy [`coop-cloud/traefik`]
|
||||
3. `abra app new bonfire --secrets` (optionally with `--pass` if you'd like to save secrets in `pass`) and select your server from the list and enter the domain name you want Bonfire to be served from
|
||||
4. `abra app config YOUR_APP_DOMAIN_NAME` and check/edit the config keys
|
||||
5. `abra app deploy YOUR_APP_DOMAIN_NAME`
|
||||
6. Open the configured domain in your browser and sign up!
|
||||
|
||||
## 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
|
||||
|
||||
@@ -34,5 +39,8 @@ A [coop-cloud](https://coopcloud.tech) recipe for deploying [Bonfire](https://bo
|
||||
### The app isn't starting
|
||||
On the server, try this command to see what services are starting or not: `docker service ls` and this one to debug why one isn't starting: `docker service ps $container_name`
|
||||
|
||||
### How can I sign up via CLI?
|
||||
Go into your app's Elixir console and enter something like `Bonfire.Me.make_account_only("my@email.net", "my pw")`
|
||||
|
||||
### How can I get to the app's Elixir console?
|
||||
`abra app run your-server.domain.name app bin/bonfire remote`
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
export APP_ENTRYPOINT_VERSION=v1
|
||||
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
|
||||
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
depends_on:
|
||||
- search
|
||||
environment:
|
||||
- SEARCH_MEILI_INSTANCE=http://${STACK_NAME}_search:7700
|
||||
secrets:
|
||||
- meili_master_key
|
||||
|
||||
search:
|
||||
image: getmeili/meilisearch:v1.14 # WIP: upgrade from v1.11 to 1.14
|
||||
secrets:
|
||||
- meili_master_key
|
||||
volumes:
|
||||
- "search-data:/meili_data"
|
||||
- "dump-data:/meili_dumps"
|
||||
networks:
|
||||
- internal
|
||||
entrypoint: ["tini", "--", "/docker-entrypoint.sh", "/bin/meilisearch"]
|
||||
environment:
|
||||
- MEILI_DUMP_DIR=/meili_dumps
|
||||
configs:
|
||||
- source: app_entrypoint
|
||||
target: /docker-entrypoint.sh
|
||||
mode: 0555
|
||||
- source: meili_backup
|
||||
target: /meili_backup.sh
|
||||
mode: 0555
|
||||
labels:
|
||||
backupbot.backup: ${ENABLE_BACKUPS:-true}
|
||||
backupbot.backup.volumes.search-data: "false"
|
||||
backupbot.backup.volumes.dump-data.path: "/meili_dumps/meilisearch_latest.dump"
|
||||
backupbot.backup.pre-hook: "/meili_backup.sh backup"
|
||||
backupbot.restore.post-hook: '/meili_backup.sh restore'
|
||||
|
||||
volumes:
|
||||
search-data:
|
||||
dump-data:
|
||||
|
||||
configs:
|
||||
meili_backup:
|
||||
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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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.7.4
|
||||
# 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}
|
||||
@@ -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}
|
||||
+58
-108
@@ -3,74 +3,66 @@ version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
image: ${APP_DOCKER_IMAGE}
|
||||
# logging:
|
||||
# driver: none
|
||||
image: ${CONTAINER_REGISTRY:-bonfirenetworks/bonfire}:${APP_VERSION:-1.0.5}-${APP_FLAVOUR:-social}-${APP_PLATFORM:-amd64}
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "10"
|
||||
depends_on:
|
||||
- db
|
||||
- search
|
||||
environment:
|
||||
- POSTGRES_HOST=${STACK_NAME}_db
|
||||
- SEARCH_MEILI_INSTANCE=http://${STACK_NAME}_search:7700
|
||||
- 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_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
|
||||
|
||||
- MAIL_BACKEND
|
||||
- MAIL_DOMAIN
|
||||
- MAIL_FROM
|
||||
|
||||
# for Mailgun
|
||||
- MAIL_KEY
|
||||
- MAIL_BASE_URI
|
||||
|
||||
# for SMTP
|
||||
- MAIL_SERVER
|
||||
- MAIL_USER
|
||||
- MAIL_PASSWORD
|
||||
- DB_SLOW_QUERY_MS
|
||||
- DB_STATEMENT_TIMEOUT
|
||||
- DB_QUERY_TIMEOUT
|
||||
- DB_JIT
|
||||
- DB_MIGRATE_INDEXES_CONCURRENTLY
|
||||
- PROD_LOG_LEVEL
|
||||
|
||||
- SENTRY_DSN
|
||||
|
||||
- WEB_PUSH_SUBJECT
|
||||
- WEB_PUSH_PUBLIC_KEY
|
||||
- WEB_PUSH_PRIVATE_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
|
||||
|
||||
- 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
|
||||
networks:
|
||||
@@ -85,63 +77,24 @@ services:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
labels:
|
||||
# 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}"
|
||||
#- "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: 1096000000 # (about 1GB)
|
||||
networks:
|
||||
- internal
|
||||
# shm_size: ${DB_MEMORY_LIMIT}
|
||||
# tmpfs:
|
||||
# - /tmp:size=${DB_MEMORY_LIMIT}
|
||||
#entrypoint: ['tail', '-f', '/dev/null'] # uncomment when the Postgres DB is corrupted and won't start
|
||||
|
||||
search:
|
||||
image: getmeili/meilisearch:latest
|
||||
secrets:
|
||||
- meili_master_key
|
||||
volumes:
|
||||
- "search-data:/data.ms"
|
||||
networks:
|
||||
- internal
|
||||
entrypoint: ["tini", "--", "/docker-entrypoint.sh", "/bin/meilisearch"]
|
||||
configs:
|
||||
- source: app_entrypoint
|
||||
target: /docker-entrypoint.sh
|
||||
mode: 0555
|
||||
- "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:
|
||||
search-data:
|
||||
upload-data:
|
||||
|
||||
networks:
|
||||
@@ -151,29 +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
|
||||
|
||||
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
@@ -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 "$@"
|
||||
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
backup() {
|
||||
SECRET=$(cat /run/secrets/meili_master_key)
|
||||
# Create dump
|
||||
echo "Creating new Meilisearch dump..."
|
||||
RESPONSE=$(curl -s -X POST 'http://localhost:7700/dumps' -H "Authorization: Bearer $SECRET")
|
||||
echo "Response: $RESPONSE"
|
||||
|
||||
# More robust extraction of task UID
|
||||
TASK_UID=$(echo "$RESPONSE" | sed -n 's/.*"taskUid":\([0-9]*\).*/\1/p')
|
||||
|
||||
if [ -z "$TASK_UID" ]; then
|
||||
echo "Failed to extract task UID from response. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Waiting for dump creation (task $TASK_UID)..."
|
||||
|
||||
MAX_ATTEMPTS=600
|
||||
ATTEMPT=0
|
||||
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
|
||||
RESPONSE=$(curl -s "http://localhost:7700/tasks/$TASK_UID" -H "Authorization: Bearer $SECRET")
|
||||
echo "Task status response: $RESPONSE"
|
||||
|
||||
TASK_STATUS=$(echo "$RESPONSE" | sed -n 's/.*"status":"\([^"]*\)".*/\1/p')
|
||||
|
||||
if [ -z "$TASK_STATUS" ]; then
|
||||
echo "Failed to extract task status. Retrying..."
|
||||
ATTEMPT=$((ATTEMPT+1))
|
||||
sleep 5
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Current status: $TASK_STATUS"
|
||||
|
||||
if [ "$TASK_STATUS" = "succeeded" ]; then
|
||||
echo "Dump creation succeeded"
|
||||
break
|
||||
elif [ "$TASK_STATUS" = "enqueued" ] || [ "$TASK_STATUS" = "processing" ]; then
|
||||
echo "Dump creation in progress... ($TASK_STATUS)"
|
||||
ATTEMPT=$((ATTEMPT+1))
|
||||
sleep 5
|
||||
else
|
||||
echo "Dump creation in unexpected state: $TASK_STATUS. Giving up."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
|
||||
echo "Timed out waiting for dump creation"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract dump UID more reliably
|
||||
DUMP_UID=$(echo "$RESPONSE" | sed -n 's/.*"dumpUid":"\([^"]*\)".*/\1/p')
|
||||
|
||||
if [ -z "$DUMP_UID" ]; then
|
||||
echo "Failed to extract dump UID. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Using dump $DUMP_UID"
|
||||
|
||||
# Check if file exists before copying
|
||||
if [ ! -f "/meili_dumps/$DUMP_UID.dump" ]; then
|
||||
echo "Dump file /meili_dumps/$DUMP_UID.dump not found!"
|
||||
ls -la /meili_dumps/
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp -f "/meili_dumps/$DUMP_UID.dump" "/meili_dumps/meilisearch_latest.dump"
|
||||
echo "Dump created and copied successfully. You can find it at /meili_dumps/meilisearch_latest.dump"
|
||||
}
|
||||
|
||||
restore() {
|
||||
echo 'Restarting Meilisearch with imported dump, may take a while to become available...'
|
||||
|
||||
# Check if dump file exists
|
||||
if [ ! -f "/meili_dumps/meilisearch_latest.dump" ]; then
|
||||
echo "Error: Dump file not found at /meili_dumps/meilisearch_latest.dump"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pkill meilisearch || echo "No Meilisearch process found to kill"
|
||||
|
||||
echo "Starting Meilisearch with import dump option..."
|
||||
MEILI_NO_ANALYTICS=true /bin/meilisearch --import-dump /meili_dumps/meilisearch_latest.dump &
|
||||
|
||||
echo "Meilisearch restore process initiated..."
|
||||
}
|
||||
|
||||
# Handle command line argument
|
||||
case "$1" in
|
||||
backup)
|
||||
backup
|
||||
;;
|
||||
restore)
|
||||
restore
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {backup|restore}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
BACKUP_PATH="/var/lib/postgresql/data"
|
||||
LATEST_BACKUP_FILE="${BACKUP_PATH}/backup.sql"
|
||||
|
||||
function backup {
|
||||
if [ -f "$POSTGRES_PASSWORD_FILE" ]; then
|
||||
export PGPASSWORD=$(cat "$POSTGRES_PASSWORD_FILE")
|
||||
fi
|
||||
|
||||
# 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 ${BACKUP_PATH}
|
||||
|
||||
function restore_config {
|
||||
echo "Restoring original pg_hba.conf configuration..."
|
||||
cat pg_hba.conf.bak > pg_hba.conf
|
||||
su postgres -c 'pg_ctl reload'
|
||||
}
|
||||
|
||||
# Don't allow any other connections than local
|
||||
echo "Setting up temporary pg_hba.conf to only allow local connections..."
|
||||
cp pg_hba.conf pg_hba.conf.bak
|
||||
echo "local all all trust" > pg_hba.conf
|
||||
su postgres -c 'pg_ctl reload'
|
||||
trap restore_config EXIT INT TERM
|
||||
|
||||
# Recreate Database
|
||||
echo "Dropping existing database ${POSTGRES_DB:-postgres}..."
|
||||
psql -U "${POSTGRES_USER:-postgres}" -d postgres -c "DROP DATABASE \"${POSTGRES_DB:-postgres}\" WITH (FORCE);"
|
||||
|
||||
echo "Creating fresh database ${POSTGRES_DB:-postgres}..."
|
||||
createdb -U "${POSTGRES_USER:-postgres}" "${POSTGRES_DB:-postgres}"
|
||||
|
||||
echo "Restoring data from ${LATEST_BACKUP_FILE}..."
|
||||
psql -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_DB:-postgres}" -1 -f "${LATEST_BACKUP_FILE}"
|
||||
|
||||
trap - EXIT INT TERM
|
||||
restore_config
|
||||
|
||||
echo "Database restore completed successfully."
|
||||
}
|
||||
|
||||
# Execute the function passed as argument
|
||||
case "$1" in
|
||||
backup)
|
||||
backup
|
||||
;;
|
||||
restore)
|
||||
restore
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {backup|restore}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Executable
+61
@@ -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
|
||||
Executable
+505
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
#/bin/sh
|
||||
|
||||
# NOTE: this script should no longer be needed now that we have `# length=128` next to these secrets in the .env
|
||||
|
||||
# abra app secret generate --all $1
|
||||
|
||||
s1=$(openssl rand -base64 128)
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
export SONIC_CHANNEL__AUTH_PASSWORD="$(cat /run/secrets/sonic_password)"
|
||||
|
||||
exec sonic -c /etc/sonic.cfg
|
||||
Reference in New Issue
Block a user