Skip to content
SupaCovedocs

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):

DependencyPurposeVersion
PostgreSQL client toolspg_dump / pg_restore14–18 (in image)
age (library)encryption/decryptionGo library filippo.io/age built in — no age CLI needed
S3-compatible storageremote 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/supabackup

make 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/data in 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:

  1. TLS in front (session cookies are Secure; plain-HTTP logins failing is a deliberate fail-closed default unless SB_INSECURE_COOKIE=1, local only).
  2. 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

On this page