03 / 13
Installation
Image, source build and deployment topology; compose is development-only
Runtime shape
One Go binary with the console embedded, plus two external runtime dependencies (age ships as a Go library):
| Dependency | Purpose | Version |
|---|---|---|
| PostgreSQL client tools | pg_dump / pg_restore | 14–18 (in image) |
| age (library) | encryption/decryption | Go library filippo.io/age built in — no age CLI needed |
| S3-compatible storage | remote commit (optional, recommended) | S3 / R2 / B2 / MinIO |
Image
docker build --target runtime -t supabackup:<tag> .The default (last) stage is the experimental runtime-spike image with an
embedded PostgreSQL server. Production builds MUST pass --target runtime.
Source
# Needs Node 22 (console frontend) and Go 1.26.6+ (matches go.mod)
make build # = frontend + backend: builds the console, embeds it, emits bin/supabackupmake backend alone only compiles Go: without the frontend embedded via
make frontend, the instance answers page requests with 503. Source
deployments must use make build.
Directories and permissions
SB_DATA_DIR(default./data,/app/datain the image): master secret, metadata database, staging, expected 0700. UID 10001 applies to the container image only; source/systemd deployments run as whatever user you choose — give that user exclusive ownership of the data directory.- The master secret file is 0600 and symlink-refusing; the age identity does NOT belong in the data directory.
docker compose: development only
The bundled compose.yaml sets SB_INSECURE_COOKIE=1 and fixed development
passwords and starts dev PostgreSQL/MinIO — local experimentation only. For
production, ensure:
- TLS in front (session cookies are
Secure; plain-HTTP logins failing is a deliberate fail-closed default unlessSB_INSECURE_COOKIE=1, local only). - The data volume is backed up independently — it holds the master secret.
Upgrading
Stop → replace binary/image → start. Schema migrations run at startup with
per-version pre-migrate snapshots. A shutdown that lands on a running backup records interrupted (not failed);
ciphertext meeting the resume conditions (interrupted + locally committed +
recorded remote intent + artifact and manifest readable + usable
destination) is re-uploaded at the next startup.
Last updated