What
Restore a snapshot back onto a running install: app.db, nginx/generated,
certificates, and optionally project volumes.
New endpoint: POST /api/system/backups/{stamp}/restore.
Why
Backups are currently write-only. backup.Service has Create, List and
Prune and no way back. A tarball nobody has ever unpacked is not a backup, it
is an untested assumption, and the day it matters is the worst day to find out
the archive was wrong.
This is not a missing feature. It is a feature that stops halfway.
How
- Add
Restore(stamp string, includeVolumes bool) to manager/internal/backup/,
the inverse of Create: copy files back, plus
docker run --rm -v vol:/dst ... tar xzf mirroring archiveVolume
(manager/internal/backup/volumes.go:70).
- SQLite is open while the manager runs. Rather than hot-swapping the
connection, stage the restored files next to the live ones, set a marker, and
exit non-zero. Docker restarts the container and manager/cmd/server/main.go
swaps them in on boot before opening the database. Smaller and far easier to
reason about than draining connections at runtime.
- Handler next to
handleBackup (manager/internal/api/system_handlers.go:275),
route in api.go, row in apiRoutes (openapi.go), button in
apps/web/src/routes/system.backups.tsx.
- Docs: section in
docs/api.md, and docs/security.md because this is a
destructive action. Require typing the snapshot name to confirm.
- Test:
Create → mutate a file → Restore → compare checksums.
Done when
make dev-up, deploy a project, take a backup, delete the project, restore.
The project comes back with its certificate and its nginx config.
What
Restore a snapshot back onto a running install:
app.db,nginx/generated,certificates, and optionally project volumes.New endpoint:
POST /api/system/backups/{stamp}/restore.Why
Backups are currently write-only.
backup.ServicehasCreate,ListandPruneand no way back. A tarball nobody has ever unpacked is not a backup, itis an untested assumption, and the day it matters is the worst day to find out
the archive was wrong.
This is not a missing feature. It is a feature that stops halfway.
How
Restore(stamp string, includeVolumes bool)tomanager/internal/backup/,the inverse of
Create: copy files back, plusdocker run --rm -v vol:/dst ... tar xzfmirroringarchiveVolume(
manager/internal/backup/volumes.go:70).connection, stage the restored files next to the live ones, set a marker, and
exit non-zero. Docker restarts the container and
manager/cmd/server/main.goswaps them in on boot before opening the database. Smaller and far easier to
reason about than draining connections at runtime.
handleBackup(manager/internal/api/system_handlers.go:275),route in
api.go, row inapiRoutes(openapi.go), button inapps/web/src/routes/system.backups.tsx.docs/api.md, anddocs/security.mdbecause this is adestructive action. Require typing the snapshot name to confirm.
Create→ mutate a file →Restore→ compare checksums.Done when
make dev-up, deploy a project, take a backup, delete the project, restore.The project comes back with its certificate and its nginx config.