Skip to content

feat: add backup and restore for Docker Compose#2

Open
shanzez wants to merge 3 commits into
Platform-Collective:mainfrom
shanzez:feat/compose-backup-restore
Open

feat: add backup and restore for Docker Compose#2
shanzez wants to merge 3 commits into
Platform-Collective:mainfrom
shanzez:feat/compose-backup-restore

Conversation

@shanzez

@shanzez shanzez commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Closes #1.

Adds a documented backup/restore path for Docker Compose deployments, which currently have none (the Helm chart already has scheduled backups).

What

  • backup.sh - cold, crash-consistent snapshot: resolves the real volume sources via docker inspect (works with named volumes and VOLUME_*_PATH bind mounts), stops the stack, archives the CockroachDB and MinIO volumes plus config/secrets (.env, huly*.conf, nginx.conf, .huly.secret, etc.), restarts, and writes a manifest.txt. Optional --keep=N retention and --full (include elastic/redpanda).
  • restore.sh - replaces volumes and config from a backup, with a confirmation prompt and a stop-before-overwrite safeguard so a running container never has its volume rewritten underneath it.
  • guides/backup-restore.md + a short Backups section linking it from the README.

Design notes

  • Skips the rebuildable search index (elastic) and transient event log (redpanda) by default, matching the scope of the existing Helm backup CronJobs. --full includes them.
  • No new dependencies: only docker, docker compose, and a throwaway alpine container.
  • Shell style follows the existing setup.sh/nginx.sh (4-space, [ ], #!/usr/bin/env bash). shellcheck-clean.

Testing

Validated end-to-end on a Compose stack mirroring the real service/volume layout (cockroach + minio): seeded a DB row and a file, ran backup.sh, destroyed both, ran restore.sh, and confirmed both were fully restored. The restore safeguard (stop before overwrite) was verified.

Contributed by Exaviz (exaviz.com).

Add backup.sh, restore.sh, and a guide for backing up and restoring a
Docker Compose deployment.

- backup.sh takes a cold snapshot: stops the stack, archives the
  CockroachDB and MinIO volumes plus config and secrets, then restarts
- restore.sh replaces volumes and config from a backup, with a
  confirmation prompt and a stop-before-overwrite safeguard
- skip the rebuildable search index and transient event log by default
  (--full includes them), matching the Helm chart's backup scope
- document both in guides/backup-restore.md and link from the README

Addresses the recurring need for a documented Compose backup path
(upstream huly-selfhost #273, #223, #62).

Signed-off-by: Exaviz <info@exaviz.com>
Exaviz added 2 commits June 30, 2026 19:25
Two fixes found by running this against a real deployment:

- Resolve data volumes by mount destination as a fallback, not only by a
  hardcoded service name. Deployments that name the database service
  'cockroachdb' (instead of 'cockroach') were silently skipped, producing
  a backup with no database. Now scans all project containers for the
  destination when the expected service name is absent.
- Always restart the stack via an EXIT trap. With 'set -e', a failure
  while archiving (after the stack was stopped) exited without restarting,
  leaving the deployment down - unacceptable for a scheduled backup. The
  stack is now brought back up even on failure, and as soon as the volume
  archive finishes on success (minimizing downtime).

Also make volume resolution safe under 'set -e' (a not-found lookup no
longer aborts the script).

Signed-off-by: Exaviz <info@exaviz.com>
Add an --offsite flag to backup.sh that uploads each completed backup to
S3-compatible storage via rclone (Backblaze B2, DO Spaces, AWS S3, MinIO,
etc.), so backups are not stranded on the same host as the deployment.

- creds via a gitignored backup-offsite.env (example provided); env-var
  names match the Helm chart's backup CronJobs for consistency
- upload runs in a throwaway rclone container, nothing extra to install
- remote retention via bucket lifecycle policy (documented)
- backups/ and backup-offsite.env added to .gitignore
- documented in guides/backup-restore.md

Validated: rclone upload of a full backup (db + files + config + manifest)
to a MinIO target, bucket auto-created.

Signed-off-by: Exaviz <info@exaviz.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a documented backup/restore path for Docker Compose

1 participant