# Verified compose for BorgBackup backup benchmark, tested 2026-10-19 by the SelfHostBench lab (3 runs; the figures are the median). # Lab host: AMD EPYC 9V74 80-Core Processor, 2 vCPU, 7.8 GiB RAM, x86_64, Docker 28.0.4. # Floating image tags below were replaced by the version resolved at test time; # the registry digest is in the comment on each image line. # Measurements: backup-borg.json (schema 3). # Companion env file: backup-borg.env (save it as .env next to this file). # Secrets are not published: the lab's values are public. In backup-borg.env: # BORG_PASSPHRASE is commented out. Uncomment it and set your own value (the comment above it explains how). # BorgBackup 1.4.5 (stable 1.4 series; Borg 2.0 is still in beta and is not used): a deduplicating backup program for the command line. This is the container the SelfHostBench backup # benchmark runs Borg in, with a local repository on a Docker volume. Borg is a command, not a service: the container only stays up (sleep) so that you can run `docker exec borg borg ...`, # or point a cron job or a systemd timer at it. Most people run Borg straight on the host (apt install borgbackup, or the standalone binary) from a timer, or through borgmatic. # # There is no official Borg image. This file starts a plain Debian-based image (python:3.12-slim, glibc 2.41, used here only because it has Python to do the download below) and puts the # project's own standalone binary on it: borg-linux-glibc231-x86_64 from the 1.4.5 release on github.com/borgbackup/borg (assets of release 1.4.5, 18 Jul 2026). The download is checked # against the SHA-256 the release page shows for that file before it is made executable (the project also publishes GPG signatures, .asc files, that this file does not check). For an arm64 # machine use borg-linux-glibc235-arm64-gh and its checksum. A packaged Borg (apt, dnf, apk) is the usual alternative and starts a little faster: the standalone binary unpacks itself # into /tmp every time it starts. # # Quick start (after putting a long random BORG_PASSPHRASE in .env): # docker compose up -d # docker compose exec borg borg init --encryption=repokey-blake2 /repo # once; the key is stored in the repository, locked with BORG_PASSPHRASE # docker compose exec borg borg create --stats /repo::day1 /data/src # then a new archive name each time (add {now} for a time stamp): only changes are stored # docker compose exec borg sh -c 'cd /restore && borg extract /repo::day1' # Back up the key too (`borg key export /repo`): with repokey modes it is inside the repository, so if the repository is damaged and you lose the passphrase, there is no way back. # Local repository only. A repository on the same disk as your data is not a backup: use another disk, another machine over ssh (ssh://user@host/path) or a Borg hosting service. name: borg services: borg: image: python:3.12-slim # sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 (version 1.4.5, from exec) entrypoint: - sh - -c - | set -e python3 - <<'PY' import hashlib, os, urllib.request url = "https://github.com/borgbackup/borg/releases/download/1.4.5/borg-linux-glibc231-x86_64" want = "c8457f70660064d0f45b38283ab4cc65b342970012013201d3aec713a75898fb" data = urllib.request.urlopen(url, timeout=120).read() if hashlib.sha256(data).hexdigest() != want: raise SystemExit("borg download: sha256 does not match") with open("/usr/local/bin/borg.part", "wb") as fh: fh.write(data) os.chmod("/usr/local/bin/borg.part", 0o755) os.rename("/usr/local/bin/borg.part", "/usr/local/bin/borg") PY exec sleep infinity # Borg records the host name in every archive. A fixed name keeps the history together when the container is recreated. hostname: backup-host restart: unless-stopped environment: # Unlocks the repository key. Set in .env. If you lose it the backups cannot be opened: store it somewhere that is NOT the backed-up machine (a password manager). BORG_PASSPHRASE: "${BORG_PASSPHRASE:?set BORG_PASSPHRASE in .env}" volumes: # What to back up. In real use mount your own data read-only instead, for example `- /srv/photos:/data/photos:ro`. (The lab test changes files in this volume to simulate a second day.) - data:/data # The repository. In real use this should be on another disk or machine. - repo:/repo # Where `borg extract` writes. - restore:/restore healthcheck: # Healthy once the download above has been checked and the binary is in place. test: ["CMD", "test", "-x", "/usr/local/bin/borg"] interval: 5s timeout: 3s start_period: 2s retries: 60 volumes: data: repo: restore: