Back up bind-mount data, not just the compose file (0.40.0)
A stack's real state lives in its bind-mounted config directories, and those
were never captured: the backup only tarred the stack folder as this container
sees it. When STACKS_HOST_DIR differs from the container's STACKS_DIR, compose
resolves ./config against the container path and the daemon creates it at that
path on the *host* — invisible here, so the archive held little more than
compose.yaml and .env.
New services/stack_assets_service.py inventories a stack's data (bind sources
merged from container mounts + the compose file, named volumes) and does all
data I/O through a throwaway helper container, i.e. by host path, so unseen
directories are captured anyway. It also detects the host/container stacks-path
mismatch and reports it.
- manifest v2: full inventory, per-asset capture result, skip reasons (v1 still
restores)
- NFS/CIFS-backed volumes are skipped by default and never wiped on restore
- deselected data inside the stack folder no longer sneaks in via compose/
- volume/bind archives stream through temp files instead of RAM
- restore preserves mode, ownership, mtime and symlinks, and writes bind folders
back to their host paths (rewritten when the stack is renamed)
- backup dialog shows the inventory with sizes and per-item checkboxes; restore
gained a "restore bind folders" toggle
- new GET /api/stacks/{id}/backup/inventory (+ agent + proxy), backup endpoints
take include_binds/binds/volumes, restore takes restore_binds
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -86,9 +86,19 @@ as intuitive as Dockge, as capable as Portainer for Compose workflows.
|
||||
from its container labels) — the helper survives the backend being recreated;
|
||||
the UI polls `/api/health` and reloads when the new version answers. Installs
|
||||
not managed by compose get a clear "update manually" error instead.
|
||||
- **Backup & restore**: per-stack `.tar.gz` backups including named-volume contents
|
||||
(snapshotted via a throwaway helper container); restore via upload with optional
|
||||
rename, volume restore, and overwrite/conflict detection.
|
||||
- **Backup & restore**: per-stack `.tar.gz` backups covering the whole stack —
|
||||
the stack folder, every **bind-mounted data directory** (`./config`, `/mnt/appdata/…`)
|
||||
and every named volume. Bind sources and volumes are read through a throwaway
|
||||
helper container, i.e. by **host path**, so data that StackPilot itself cannot
|
||||
see is captured too (that is the case whenever `STACKS_HOST_DIR` differs from
|
||||
the container's `STACKS_DIR` — compose then creates the data directories at the
|
||||
container path *on the host*, and a naive backup would only find the compose
|
||||
file). The Backup dialog shows the full inventory with sizes and lets you pick
|
||||
what goes in; **NFS/CIFS-backed volumes are unchecked by default** because they
|
||||
live on a NAS and restoring one would overwrite the share. Restore puts bind
|
||||
folders back at their host paths and preserves permissions, ownership and
|
||||
symlinks (PUID/PGID-based images such as the *arr suite need this), with
|
||||
optional rename and overwrite/conflict detection.
|
||||
- **Notification webhooks**: ntfy, Discord, Slack, Gotify, or generic JSON, each
|
||||
subscribed to chosen events (image update available, stack start/stop/error,
|
||||
pull failed). Managed in **Settings → Notifications**; env `NOTIFY_WEBHOOKS`
|
||||
|
||||
Reference in New Issue
Block a user