Conversation
The entrypoint hardcodes 'mkdir -p /data/private/uploads/tmp' for tusd, so overriding PRIVATE_PATH to /data put the local storage channel's uploads in a different tree than the scaffolding the image creates for itself.
|
Closing without merging — not adopting Portabase. The implementation here is complete and reviewed, and the design questions it raised (dedicated
Neither is fatal on its own, and both have workarounds. But together they amount to carrying local patches against upstream's assumptions for a service whose entire job is to be boringly reliable — and the thing it would replace is not broken. Cronicle now runs v0.9.134 on Node.js 24 after the NodeSource Nothing from this branch is merged. The The spec and plan ( |
What
Adds Portabase — a containerized PostgreSQL backup tool (dashboard + Rust agent) — as a new
deploy_portabaserole, taking over the job that bare-metal Cronicle currently does (pg_dumpallviadocker exec, on a schedule).Both systems keep running in parallel. Nothing here retires or disables Cronicle.
Spec:
docs/superpowers/specs/2026-09-20-portabase-db-backups-design.mdPlan:
docs/superpowers/plans/2026-09-23-portabase-db-backups.mdWhy
Every Cronicle job on the server was the same alias,
d-db-dump <app> <pg container>. Keeping a bare-metal Node.js install (and the NodeSource apt repo) on the host purely to schedule database dumps is the cost being removed. Portabase does that specific job — scheduled dumps, retention, restore, a UI — as containers.How it connects to the databases
The agent is a plain PostgreSQL client: it runs
pg_dump --host <container> --port 5432. So it needs network reachability, not a docker socket.Rather than reusing
nginxnetwork(today every service in every app joins it — a known over-exposure to fix separately), this adds a dedicateddb_backupnetwork created withinternal: true, so it has no route off the host. Each app's PostgreSQL service opts in explicitly; application containers are untouched.Because a compose service that declares
networks:stops implicitly joiningdefault, every DB service lists both — verified across all ten files (90 insertions, 0 deletions).Changes
setup_dockerdb_backupnetwork,internal: truedb_backup, keepsdefaultdeploy_portabasemain.yml,vars/apps.ymlinit_setupisu_cronicle_enabledflag, defaultstrueDumps land at
/mnt/pools/slow/backups/portabase/private/uploads/. Cronicle'sdb_dumps/tree is untouched.Notes for review
nginxnetwork.portabase-appdeliberately has nouser:pin, unlikeportabase-pg: the upstream image's prod stage ends withUSER rootand its entrypoint execs nginx without dropping privileges. There's a comment in the compose file recording this.PRIVATE_PATHis left at the image default/data/private— the entrypoint hardcodesmkdir -p /data/private/uploads/tmpfor tusd, so overriding it would split the storage layout in two.ghcr.io/immich-app/postgres(VectorChord):pg_dumpworks, but restoring needs an image carrying the same extension. Documented in the role README.Not done in this PR
v_portabasevault block (secrets — added out of band).EDGE_KEYis minted by the dashboard, so first deploy is two-phase; the runbook is inroles/deploy_portabase/README.md.🤖 Generated with Claude Code