A production-ready PostgreSQL image with PgBackRest preinstalled and sensible default configuration.
Maintained by EthosLink, the company behind Reviato, Nuntio, and Profix. This image comes from our database operations work for Reviato.
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 build business products and share the engineering tools behind our work.
- Reviato — Understand what customers are telling you. Collect private feedback, explore recurring themes in public reviews, and keep the original words and follow-up details close at hand.
- Nuntio — Prepare social posts ahead of time. Keep drafts, channel-specific versions, team review, scheduling, and publishing outcomes in one workspace.
- Profix — See what sold, what it earned, and what is still on the shelf. Profit and stock analysis for clothing shops and boutiques. Early access.
- postgres-backrest — This PostgreSQL image: PgBackRest preinstalled, WAL archiving defaults, and configuration you can mount and manage yourself.
- git-markdown — Export a GitHub pull request, reviews, and discussion into one Markdown file for offline review, AI workflows, or engineering handoffs.
- indexmap — Build and validate XML sitemaps from explicit Ruby definitions, with Rails tasks and safe publishing that keeps the last good files if generation fails.
- Crawlscope — Crawl your sitemap to check indexability, metadata, structured data, and internal links. Use structured findings in scripts, a CLI, or Rails tasks.
See the product and project guide for more detail and useful next steps, or browse all products and open-source project notes.
- 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 --init \
-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 --init \
-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 --init \
-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 --init \
-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.
Run the container with --init (or init: true in Docker Compose). PgBackRest's asynchronous archiver starts background processes; an init process reaps them so PostgreSQL does not receive their exit notifications.
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
File and console logging default to info (including warnings and errors).
Use docker exec --user postgres <container> pgbackrest-docker --stanza=main backup
for scheduled backups: the helper sends output to Docker's logger and disables
duplicate file logging for that invocation. Use plain pgbackrest for archiving;
detached asynchronous workers need their file logs at /var/log/pgbackrest.
Set PGBACKREST_LOG_LEVEL_FILE=debug explicitly for troubleshooting.
Production deployments should bind-mount the file log directory and install the
ops/ configuration for the host's existing logrotate.timer and native
tmpfiles cleanup. Docker rotates console logs; OS logrotate handles file logs.
The image runs no scheduler or log tailer. See the logging operations guide
for Docker settings, installation, 14-day file retention, migration, safe cleanup,
archive health checks and rollback. Upgrading the image alone does not install
the host rotation policy.
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 main.
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 "build(release): bump PostgreSQL to 18.3" -m "Update the base image and release version together."
git push origin <branch>Then create a PR and merge to main. 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