Releases: ekho/gobackup-docker
Release list
v2.3.0 — literal $ escaping (no more mangled passwords)
Highlights
💲 Literal $ in config values no longer corrupts backups
gobackup loads its config by running os.ExpandEnv over the entire file before parsing it — so any $ in a value (most painfully a password like m9qq!$7v!s^$!UU) was silently eaten as a variable reference (→ m9qq!v!s^UU) and auth failed. YAML quoting couldn't help (expansion is pre-parse, on raw bytes) and os.ExpandEnv has no escape character.
The supervisor now keeps a $ only when it begins a real reference — $NAME or ${NAME} where NAME is [a-zA-Z][a-zA-Z0-9_]+ — and rewrites every other $ to ${GB_DOLLAR}, a sentinel it injects into the engine's env as a literal $. gobackup expands ${GB_DOLLAR} back to $ in a single pass, so the value round-trips exactly.
gobackup.databases.main.password: "m9qq!$7v!s^$!UU" # just works — no $$ gymnastics- Real references still expand:
$DB_PASSWORDand${DB_PASSWORD}are preserved and expanded by gobackup. - Everything else is literal:
$7,$!, a trailing$,$$, and even a too-short name like$A/${A}are kept verbatim. - Requires the supervisor to manage the engine (Docker socket +
gobackup-docker.component=gobackup), since it injects the sentinel. Label-only mode instead logs a warning naming each affected value. - Limit: a secret that genuinely contains a reference-shaped sequence (
p$word,Se${cret}) is treated as a reference — use a*_env/*_filecredential label for those.
Verified end-to-end (spike/e2e-dollar/): a Postgres password full of $ is dumped successfully — pg_dump authenticates, proving the round-trip.
🔁 Fix: single config write per reconcile
Previously render() wrote a raw config that Phase 2 then rewrote with transformed volume paths — flip-flopping the writer's dedup (spurious changed every pass) and briefly exposing untransformed, unmounted paths to the engine. Path transforms and $-escaping now run first and the config is written exactly once. Regression guard added.
Multi-arch image ghcr.io/ekho/gobackup-docker tags 2.3.0, 2.3, 2, latest.
v2.2.0 — SQLite databases by file path (auto-mount)
Highlights
🗃️ SQLite databases by file path — automatic volume mounting
A type: sqlite database is dumped by reading its file (sqlite3 <path> .dump), so that file must live inside the gobackup engine. Now you just declare the DB by the path it has in your application container, and the supervisor mounts it in for you:
labels:
gobackup.enable: "true"
gobackup.name: "shop"
gobackup.databases.main.type: "sqlite"
gobackup.databases.main.path: "/app/data/bot_database.sqlite3"The supervisor discovers the volume backing that path, re-mounts it into the recreated gobackup container at /volumes/<model>/…, and rewrites databases.<id>.path to the mounted location — the same discovery + recreate machinery as archive auto-mount, driven by the same gobackup_container.* spec and gobackup-docker.component: "gobackup" marker.
- Read-write mount (archive mounts are read-only):
.dumpopens the DB and a WAL-mode database writes-wal/-shmsidecars next to it. The volume's directory is mounted so the sidecars have somewhere to go. - Mounts that collide on a target are deduped with read-write winning over read-only (a volume shared by an archive include and a sqlite path resolves once, writable).
- A
pathalready under/volumes/, or not backed by any volume, is left untouched (with a log). The stockgobackupimage already bundlessqlite3— no extra setup.
Verified end-to-end (spike/e2e-sqlite/): the app's DB volume is mounted read-write at /volumes/shop/app/data, databases.main.path is rewritten, and the produced tgz archive contains the seeded row INSERT INTO orders VALUES(1,'sqlite-e2e-ok').
Multi-arch image ghcr.io/ekho/gobackup-docker tags 2.2.0, 2.2, 2, latest.
v2.1.0 — credential sources (env var / Docker secret)
Highlights
🔐 Declare where a credential lives — env var or Docker secret
A client container can now source a credential indirectly instead of inlining it:
gobackup.databases.main.password_env: "DB_PASSWORD" # from the client container's env
gobackup.databases.main.password_file: "/run/secrets/db_pw" # from a Docker secret fileApplies to the secret keys password, token, secret, access_key, secret_key under databases/storages/notifiers. The rendered gobackup.yml only ever contains a ${GB_…} placeholder — plaintext is never written to the config.
_env→ the value is read from the client's env and set in the engine's env._file→ the secret's host file is re-mounted into the engine and read via a command wrapper at start. The secret value never appears ingobackup.ymlordocker inspect, and the supervisor never reads it.
Notes & limits
_filesupports Composefile:secrets. Swarmdocker secret/ Composeenvironment:secrets have no re-mountable host source and are skipped with a log (use_env).- The
_filevalue lives in the daemon's process env — trigger those backups via the schedule orPOST /api/perform, notdocker exec … perform. credentials_file(gobackup's GCS keyfile key) is deliberately not treated as a credential ref.- Conflicting inline+
_env/_file, or an unresolved value, skips the model (fail-closed).
Verified end-to-end (spike/e2e-creds/): postgres authenticates using a file secret and 0 occurrences of the value appear in docker inspect. Multi-arch image ghcr.io/ekho/gobackup-docker tags 2.1.0, 2.1, 2, latest.
v2.0.1
Maintenance release: the release CI now publishes the semver docker tag hierarchy.
A clean vX.Y.Z tag now pushes the image as X.Y.Z, X.Y, X, and latest (pre-release tags publish only their exact version). No functional code change vs v2.0.0.
Images (multi-arch linux/amd64 + linux/arm64):
ghcr.io/ekho/gobackup-docker tags 2.0.1, 2.0, 2, latest.
v2.0.0 — archive volume auto-mount
Highlights
🔌 Automatic file-backup volume mounting
Models with gobackup.archive.includes now work with zero manual volume wiring. The supervisor discovers the source container's volumes, rewrites the archive paths to /volumes/<model>/…, and recreates the gobackup container with those volumes mounted read-only — while preserving its config/backups/state mounts.
The recreated container's spec (image, command, networks, env, labels) is controlled by gobackup_container.* labels on the supervisor itself.
🧩 Array-typed label fields
Comma-separated label values are converted to real YAML arrays for every array field in gobackup's schema — archive.includes/excludes, databases.*.tables, exclude_tables, exclude_tables_prefix, skip_databases, endpoints — while identifier/secret-like fields (e.g. to, credentials, args) correctly stay strings.
⚠️ Behavior change (why 2.0)
The supervisor now recreates the gobackup container to attach archive volumes. Requirements:
- the gobackup container must carry the label
gobackup-docker.component: "gobackup"; - the supervisor needs the Docker socket mounted (
:rois sufficient); gobackup_container.commandmust be the full argv (the stock image has noENTRYPOINT).
Notes
- Multi-arch image:
ghcr.io/ekho/gobackup-docker:v2.0.0(linux/amd64+linux/arm64). - Verified end-to-end (
spike/e2e-mount/): app volume auto-mounted, archive contains the file, single recreate (no thrash). - Details: README +
docs/ARCHITECTURE.md§5.7–5.8.