Backs up Backrest config.json to an S3-compatible object store.
On each run, the service reads the local config file, computes its SHA-512 hash, compares it with the latest uploaded backup, and skips the upload if nothing changed. When the file changed, it encrypts the content locally with age, uploads the new object, removes older backups after a successful upload, and sends a Healthchecks ping.
- A Backrest
config.jsonfile - An S3-compatible bucket
- An
agepassphrase file
See .env.example for a ready-to-copy example.
Required by the application:
CONFIG_PATHS3_BUCKETS3_ENDPOINTS3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEYAGE_PASSPHRASE_FILECRON_SCHEDULEunlessRUN_ONCE=true
Optional variables:
S3_PREFIXdefaults to empty in the application. The includeddocker-compose.ymlsetsbackrest.AWS_REGIONdefaults tous-east-1TZdefaults toUTCRUN_TIMEOUTdefaults to2mRUN_ONCEdefaults tofalseS3_SESSION_TOKENif required by your providerHEALTHCHECKS_URLis optional; when unset, healthchecks pings are disabled
- Create
.envfrom.env.exampleand set your values:CONFIG_PATHS3_BUCKETS3_ENDPOINTS3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEYAGE_PASSPHRASE_FILECRON_SCHEDULE(orRUN_ONCE=true)- optional:
HEALTHCHECKS_URL,S3_PREFIX,AWS_REGION,TZ,RUN_TIMEOUT,S3_SESSION_TOKEN
- Put your Backrest config where you want and mount it read-only in
docker-compose.yml.- host path example:
./config.json - container path example:
/data/config.json - set
CONFIG_PATH=/data/config.json
- host path example:
- Create the passphrase secret file (default:
./age_passphrase.txt) and keepAGE_PASSPHRASE_FILEaligned with the secret mount path.- default in compose:
/run/secrets/age_passphrase - if you change secret target path, update
AGE_PASSPHRASE_FILEtoo
- default in compose:
- Start the service:
docker compose up -dThis container runs as root so it can read a config.json produced by the official Backrest container without
permission issues.
Backrest's Docker image runs as the default container user and uses /root paths internally. Its config store writes
config.json with mode 0600, creates timestamped config.json.bak.* copies, then atomically rewrites the live file.
In practice that makes the file application-managed and typically root-owned, so this backup container also runs as
root when mounting the file read-only.
To restore a backup:
- Download the
.json.ageobject from your bucket. - Decrypt it with the same passphrase used for backup.
- Replace your Backrest
config.jsonwith the decrypted file.
To decrypt using the age CLI:
age -d -o config.json config-backup-YYYY-MM-DDTHH-mm-ss.json.ageThis project exists to back up the Backrest configuration, which contains all credentials for restic repositories. Losing that file also means losing access to all backups. Thanks to Backrest for providing an excellent UI and management layer for restic, which provides the amazing backup engine, and age for providing simple, solid file encryption.