This episode secures backups at rest with AES-256-CBC encryption (repo1-cipher-type + repo1-cipher-pass), including the consequences before and after the stanza is created. You'll also learn best practices: managing the passphrase in a secret manager and protecting the /etc/pgbackrest.conf file with 600 permissions.

A backup is the most sensitive copy of data an organization owns — and ironically, it's often the weakest target. A backup repository holds all production data without additional protection; if the backup media is stolen, lost, or misdelivered, it's equivalent to total leakage. In episode 11 we close this gap with encryption at rest: an end-to-end encrypted repository with AES-256-CBC.
Imagine a backup as a box of secret documents. Encryption isn't locking the warehouse door (access control); it's making the contents of the box itself unreadable without the key — even if the box is stolen. Two different layers, and backups need both.
pgBackRest encrypts the entire repository contents: backup files and WAL, each encrypted before being written. It uses the AES-256-CBC algorithm with a key derived from the passphrase you provide. Without the correct passphrase, files in the repository can't be read — including by pgBackRest itself.
The most important decision: encryption must be enabled when the stanza is first created, before any backup. You can't "add" encryption to a stanza that already contains old backups — encryption is an attribute of the entire repository/stanza, not per-file.
[global]
repo1-path = /var/lib/pgbackrest
repo1-cipher-type = aes-256-cbc
repo1-cipher-pass = pGcU4mTgK9xRvL2zHq7wE1sA5dF8jN0bAfter changing the config, create a new stanza (or repeat stanza-create for a stanza that has no backups yet):
sudo -u postgres pgbackrest --stanza=main stanza-create
pgbackrest infoIn pgbackrest info, the cipher: aes-256-cbc line confirms encryption is active.
Warning
This passphrase can't be changed without re-backing up from scratch. If the passphrase is entered incorrectly during a restore, pgBackRest refuses to read the file. There's no backdoor — this is both a security feature and your biggest responsibility. Losing the passphrase means losing the backups.
Check that files in the repository are truly encrypted, not just labeled:
sudo -u postgres pgbackrest info
sudo ls -la /var/lib/pgbackrest/backup/main/latest/The backup files there contain encrypted data — you won't find readable PostgreSQL plaintext in them. For a more convincing test, try opening one with strings and check that no readable data appears.
A passphrase written in a plaintext config file violates the principle of encryption: the goal is to protect data if the config is stolen, but the passphrase itself is written right there in the config. The solution is layered:
sudo chown root:postgres /etc/pgbackrest.conf
sudo chmod 600 /etc/pgbackrest.conf[global]
repo1-cipher-pass = ${PGBACKREST_CIPHER_PASS}Then the PGBACKREST_CIPHER_PASS value is filled from a secret manager (Vault, OpenBao, AWS Secrets Manager, etc.) when the process runs. This limits passphrase exposure to runtime only, not in a static file.
Because a passphrase can't be changed on an existing stanza, the rotation strategy is: create a new full backup in a stanza with the new passphrase (new stanza or new repository), keep the old one until it expires by retention, then remove it. Rotation isn't an in-place operation — it's a transition between stanzas.
Tip
Document the passphrase recovery procedure in your runbook (episode 16): who keeps a copy, how it's restored from a secret manager while on-call, and what happens if everything is lost. The "what if everything is lost" section is what distinguishes an honest runbook from a formal one.
Besides the encrypted passphrase, the config file must not be readable by regular users:
ls -l /etc/pgbackrest.conf
getfacl /etc/pgbackrest.conf-rw------- (600) with root as owner is the standard. The postgres user (who runs the commands) can read it as the group owner or via sudo -u.
Be aware that a passphrase can leak through logs if a command is run with the --repo1-cipher-pass option on the command line. Always put the passphrase in the config (with secure permissions) or an environment variable — not in a command argument recorded in shell history or logs.
Encryption at rest doesn't replace access control — it complements it. Still restrict who can read the repository (permissions), the SSH keys (episode 13), and don't expose the repository to the public network. Encryption is the final safety net if all other controls fail.
Key takeaways:
repo1-cipher-type = aes-256-cbc + repo1-cipher-pass before the stanza is created.600; never put the passphrase in a command argument.In the next episode we'll move the repository off the database host: remote & object storage — a repository on another host via SSH (repo1-host) and S3-compatible storage (repo1-s3-endpoint, bucket) for cheap, location-disaster-proof off-site backups. This is the step toward a truly production-grade backup architecture!