Phase 3 complete: per-app backup toggles, restore, storage overview

- Storage overview on backup page (SSD/HDD bars, repo stats)
- Restic password visibility + hub sync for disaster recovery
- App data discovery (HDD bind mounts, Docker volumes)
- Per-app backup toggle checkboxes with settings persistence
- Dynamic backup paths: enabled app HDD data included in restic snapshots
- Limited app restore from snapshots (self-service recovery)
- Snapshots API endpoint for restore dropdown
- Version bump to 0.8.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 21:29:56 +01:00
parent a3af7c6a2d
commit 7d801d1094
15 changed files with 1088 additions and 29 deletions
+49 -15
View File
@@ -7,7 +7,7 @@
>
> Ask Claude Code: "Please update CONTEXT.md with what we did today"
Last updated: 2026-02-16 (session 24)
Last updated: 2026-02-16 (session 25)
---
@@ -22,18 +22,50 @@ Last updated: 2026-02-16 (session 24)
## Current project state
### felhom-controller (this repo)
- **Version:** v0.7.2
- **Version:** v0.8.0
- **Phase 1:** ✅ COMPLETE — Stack Manager + Deploy Flow
- **Phase 2:** ✅ COMPLETE — Monitoring & Health (scheduler, CPU/temp, healthchecks.io pings)
- **Phase 3:** ✅ COMPLETE — Backups (DB dumps, restic integration, manual trigger, **dedicated backup page**)
- **Phase 4:** ✅ COMPLETE — Monitoring Page with Metrics Store (SQLite, Chart.js, system + container metrics)
- **Phase 5:** ✅ COMPLETE — Authentication, Persistence & Settings Page (settings.json, password change, session management)
- **Phase 6:** ✅ COMPLETE — Monitoring Warnings, Dashboard Alerts & Notification System
- **Phase 7:** ✅ COMPLETE — Storage Overview, Per-App Backup Toggles & Limited Restore
- **First app deployed:** Paperless-ngx on demo-felhom.eu (2026-02-13)
- **Running on:** demo-felhom (N100 mini PC) at 192.168.0.162:8080
- **All Phase 1-5 features working:** deploy, start/stop/restart/update, logs, health-aware states, auth, monitoring, backups, backup detail page, system monitoring page, settings page
### What was just completed (2026-02-16 session 24)
### What was just completed (2026-02-16 session 25)
- **v0.8.0 — Phase 7: Storage Overview, Per-App Backup Toggles & Limited Restore:**
- **Storage overview on backup page** — new "Tárhely áttekintés" section as first section on backup page showing SSD/HDD progress bars + backup repo stats (repo size, dump file count, snapshot count). Reuses existing `system.GetInfo()` and `RepoStats`.
- **Restic password visibility** — new "Titkosítási kulcs" section inside the repository card. Masked password field with show/copy buttons (JS toggle). Password synced to hub via periodic report for disaster recovery (`ResticPassword` field added to `BackupReport`).
- **App data discovery** — new `internal/backup/appdata.go`:
- `StackDataProvider` interface to avoid circular imports between backup and stacks packages
- `AppBackupInfo`, `AppDataPath`, `AppDockerVolume` structs
- `DiscoverAppData()` iterates deployed stacks, discovers HDD bind mounts (via adapter calling `ParseComposeHDDMounts`), Docker named volumes (via `parseComposeNamedVolumes` using YAML parser), and DB dump status
- Stack adapter in `main.go` implements `StackDataProvider` using `stacks.Manager`
- **Per-app backup toggles** — new "Alkalmazás adatok" section on backup page:
- Toggle checkbox per app (only for apps with HDD data)
- Shows HDD paths with sizes, Docker volume info, DB dump notes
- `POST /settings/app-backup` handler saves preferences to `settings.json`
- `AppBackupPrefs` struct + bulk getter/setter in `settings.go`
- `RefreshCache()` populates `AppDataInfo` via `DiscoverAppData()`
- **Dynamic backup paths** — `RunBackup()` now includes enabled app HDD data paths:
- `resolveAppBackupPaths()` reads enabled apps from settings, resolves HDD paths via provider
- Paths logged at INFO level, included in restic snapshot
- `BackupPaths` display on backup page includes app data paths
- **Limited app restore** — new restore section on backup page:
- `RestoreApp()` in `restore.go`: validates enabled, resolves HDD paths, validates snapshot exists, uses running mutex
- `RestoreAppData()` on `ResticManager`: runs `restic restore` with `--include` flags for specific paths
- `POST /backup/restore` web handler with confirmation flow
- `GET /api/backup/snapshots` JSON endpoint for restore dropdown
- UI: app/snapshot dropdowns, warning box, confirmation checkbox, JS-driven form submission
- **Exported `ParseComposeHDDMounts`** from stacks package (was unexported `parseComposeHDDMounts`)
- **Flash messages** on backup page via query params (success/error redirects from handlers)
- **CSS**: New styles for storage overview grid, app backup toggles, encryption key field, restore section, flash messages
- **Files created**: `appdata.go`, `restore.go`
- **Files modified**: `backup.go`, `restic.go`, `handlers.go`, `server.go`, `backups.html`, `style.css`, `settings.go`, `delete.go`, `router.go`, `types.go`, `builder.go`, `main.go`
### What was previously completed (2026-02-16 session 24)
- **v0.7.2 — Fix Notification Preferences Sync (Controller → Hub):**
- **Two repos changed** (deploy-felhom-compose + felhom.eu):
- **Hub: `POST /api/v1/preferences` endpoint** (`hub/internal/api/handler.go`):
@@ -498,18 +530,16 @@ Last updated: 2026-02-16 (session 24)
7. Documentation: restart vs up -d for image updates
### What's next (priorities)
1. **Deploy v0.7.2** — Build + deploy both hub (0.1.5) and controller (0.7.2):
- Hub must be deployed FIRST (controller needs /api/v1/preferences endpoint)
- Then build + deploy controller
- Test: save notification settings → hub logs "Notification preferences updated" → "Teszt email küldése" → email arrives
- Verify: hub customer detail page shows notification email + events + log
2. **Test alert banners** — Configure some missing ping UUIDs or disable backup to verify yellow/red banners appear
3. **Test backup flow** — trigger manual backup via dashboard, verify restic repo + DB dumps
4. Add `app_info` + `optional_config` to more apps (start with Immich, Mealie, Vaultwarden)
5. Deploy a second app (e.g., ActualBudget — simplest, or Immich — tests HDD + secrets)
6. Test on Raspberry Pi (pi-customer-1)
7. Self-update mechanism
8. Hub alerting (webhook to Healthchecks for stale customers)
1. **Deploy v0.8.0** — Build + deploy controller v0.8.0 to demo-felhom.eu
2. **Test per-app backup** — enable backup for Paperless-ngx HDD data, trigger manual backup, verify restic snapshot includes HDD paths
3. **Test restore** — restore app data from snapshot, verify file recovery
4. **Change HDD mount to :rw** — currently `:ro` in controller docker-compose.yml; required for restore to work
5. Add `app_info` + `optional_config` to more apps (start with Immich, Mealie, Vaultwarden)
6. Deploy a second app (e.g., ActualBudget — simplest, or Immich — tests HDD + secrets)
7. Test on Raspberry Pi (pi-customer-1)
8. Self-update mechanism
9. Hub alerting (webhook to Healthchecks for stale customers)
10. Docker volume backup (mount `/var/lib/docker/volumes:ro` into controller)
## Architecture decisions
@@ -548,6 +578,10 @@ Last updated: 2026-02-16 (session 24)
| Resend HTTP API (no SMTP) | Direct POST to api.resend.com — same pattern as website contact-mailer. Simpler than SMTP setup, good deliverability |
| Preferences sync on save + startup | Controller pushes prefs to hub (not pull). Startup sync handles hub DB rebuild. Local save always succeeds even if sync fails |
| Chart.js embedded locally | Customer hardware may not have internet — CDN not reliable for offline environments |
| StackDataProvider interface | backup package needs stack data but can't import stacks (circular). Interface in backup, thin adapter in main.go |
| Password sync to hub via report | Restic password in Docker named volume on SSD. Hub sync provides redundancy for disaster recovery |
| App backup via HDD mounts only | Docker volumes at /var/lib/docker/volumes/ not mounted in controller. HDD data is the important user data; DB in volumes covered by nightly dump |
| Restore uses running mutex | Prevents concurrent backup+restore on same restic repo. Reuses existing `m.running` flag |
| Metrics downsampling via SQL | Bucket-based AVG in GROUP BY keeps Chart.js responsive with up to 30 days of data |
| 60s metrics collection interval | Good balance of resolution vs. storage — ~44K rows/month for system metrics |
| /etc/os-release mounted read-only | Container can't read host OS info directly — mount to /host/etc/os-release:ro |