A production-ready PostgreSQL image with PgBackRest preinstalled and sensible default configuration.
This image is maintained by Ethos Link. It is a small, reusable extract from operational work we do for Reviato.
Capture. Interpret. Act.
Turn guest feedback into clear next steps for your team. Collect private appraisals, spot patterns across reviews, and act before small issues turn into public ones.
The goal is simple: make it easy to run Postgres with backups and predictable configuration without turning your repo into an ops research project.
We believe in open source and sharing operational knowledge. If you like this project, see:
- git-markdown: A tool to convert git repos into LLM-friendly markdown.
- Reviato: Guest feedback workflows for hospitality operators.
- PostgreSQL + PgBackRest in one image (based on the upstream
postgresimage) - WAL archiving-ready defaults (pair this with a PgBackRest repo config)
- Bring-your-own
postgresql.conf(pgtune-friendly) via a mounted file - Drop-in overrides via
/etc/postgresql/conf.d/*.conf(optional) - Multi-arch support (amd64, arm64)
docker run \
-e POSTGRES_PASSWORD=mysecretpassword \
ethoslink/postgres-backrest:latestThe image ships with a default /etc/postgresql/postgresql.conf.
For anything beyond a couple of settings, the recommended practice is to provide a real Postgres config file (for example one generated by https://pgtune.leopard.in.ua) and mount it into the container.
- Generate a config on pgtune.
- Save it as
postgresql.conf. - Mount it to
/etc/postgresql/postgresql.conf.
Example (docker run):
docker run \
-e POSTGRES_PASSWORD=mysecretpassword \
-v "$PWD/postgresql.conf:/etc/postgresql/postgresql.conf:ro" \
ethoslink/postgres-backrest:latestSet POSTGRES_CONFIG_FILE to the file you mounted:
docker run \
-e POSTGRES_PASSWORD=mysecretpassword \
-e POSTGRES_CONFIG_FILE=/etc/postgresql/pgtune/postgresql.conf \
-v "$PWD/postgresql.conf:/etc/postgresql/pgtune/postgresql.conf:ro" \
ethoslink/postgres-backrest:latestThe shipped postgresql.conf includes include_dir = 'conf.d', so you can mount a small snippet without replacing the full file:
docker run \
-e POSTGRES_PASSWORD=mysecretpassword \
-v "$PWD/overrides.conf:/etc/postgresql/conf.d/overrides.conf:ro" \
ethoslink/postgres-backrest:latest- PostgreSQL doesn't provide a standardized set of environment variables for tuning knobs like
shared_buffers,work_mem,effective_cache_size, etc. The established approach is to managepostgresql.conf(and optionallyconf.dsnippets) as configuration artifacts. - If you use container memory limits, treat pgtune output as a baseline and validate values against your runtime limits.
POSTGRES_CONFIG_FILE(default:/etc/postgresql/postgresql.conf)POSTGRES_HBA_FILE(default:/etc/postgresql/pg_hba.conf)
These are used to inject -c config_file=... and -c hba_file=... when the container is started with the postgres command.
On startup, the container renders /etc/pgbackrest/pgbackrest.conf from the template at /usr/local/share/pgbackrest/pgbackrest.conf.template using envsubst.
The default template is intentionally minimal and local-by-default. To customize PgBackRest behavior (including S3/R2/backends, retention, compression, etc.), provide your own template by mounting it into the container at:
/usr/local/share/pgbackrest/pgbackrest.conf.template
See the shipped template in this repo at postgres-backrest/pgbackrest.conf.template.
Common env vars referenced by the default template:
PGBACKREST_REPO1_PATHPGBACKREST_REPO1_RETENTION_FULLPGBACKREST_REPO1_RETENTION_DIFFPGBACKREST_PROCESS_MAXPGBACKREST_LOG_LEVEL_CONSOLEPGBACKREST_LOG_LEVEL_FILEPGBACKREST_LOG_PATHPGBACKREST_COMPRESS_TYPEPGBACKREST_COMPRESS_LEVELPGBACKREST_PG1_PATH
To build the image locally with a specific PostgreSQL version:
# Using update.sh (recommended)
./update.sh <version>
docker build --build-arg POSTGRES_VERSION=<version> -t ethoslink/postgres-backrest:<version> .
# Or directly with build-arg
docker build --build-arg POSTGRES_VERSION=18.2 -t ethoslink/postgres-backrest:18.2 .To publish the multi-arch image for linux/amd64 and linux/arm64, use
Buildx:
docker login docker.io
docker login ghcr.io
./build.shThe script pushes both the version tag and latest to Docker Hub and GHCR.
POSTGRES_VERSION is the upstream base image tag. IMAGE_VERSION is this
image's published release tag. Keep them separate when rebuilding this image on
the same PostgreSQL release.
For image-only rebuilds, prefer a revision suffix such as 18.3-r1 over
18.3.1, because 18.3.1 can be mistaken for an upstream PostgreSQL patch
version.
Override PLATFORMS, POSTGRES_VERSION, IMAGE_VERSION, PUBLISH_LATEST,
or IMAGES when needed:
PLATFORMS=linux/amd64,linux/arm64 \
POSTGRES_VERSION=18.3 \
IMAGE_VERSION=18.3-r1 \
IMAGES="docker.io/ethoslink/postgres-backrest ghcr.io/ethos-link/postgres-backrest" \
./build.shbuild.sh refuses to publish an image version that already exists in any
target registry. Use a new IMAGE_VERSION for normal releases.
The GitHub Actions publish workflow also builds and pushes
linux/amd64,linux/arm64 on master.
The image is based on the official Debian-based PostgreSQL image and installs pgbackrest from the official apt repositories.
- Updates: Images are immutable. To get security updates, pull a newer tag.
- Scanning: We run Trivy scans on every build to monitor for vulnerabilities.
The image is published to:
- GitHub: https://github.com/ethos-link/postgres-backrest
- Docker Hub: https://hub.docker.com/r/ethoslink/postgres-backrest
- GitHub Container Registry: https://ghcr.io/ethos-link/postgres-backrest
To bump the PostgreSQL version and create a new release:
# Bump the base and image versions
./update.sh 18.3
# Commit and push
git add -A && git commit -m "Bump PostgreSQL to 18.3"
git push origin <branch>Then create a PR and merge to master. GitHub Actions will:
- Refuse to publish if the image version tag already exists
- Build and push the Docker image with the new image version tag
- Create a git tag (e.g.,
18.3) - Create a GitHub Release
For an image-only rebuild on the same PostgreSQL base version, pass a revision:
./update.sh 18.3 -r=1This keeps POSTGRES_VERSION=18.3 and sets IMAGE_VERSION=18.3-r1.
You can also pass a base version and revision manually to trigger a workflow dispatch:
# Via GitHub UI to manually trigger a build
# Or via CLI:
gh workflow run publish.yml -f postgres_version=18.3 -f revision=1MIT