Add structured operational logging at INFO, WARN, and ERROR levels to
every controller module. Standardize custom prefixes ([GEO], [SCHED],
[SYNC]) to use [INFO/WARN/ERROR] [module] format. Fix misleveled logs
(WARN->ERROR for data loss scenarios, WARN->INFO for routine operations).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add detailed [DEBUG] logging to every controller module when
logging.level is set to "debug". Each module with stateful debug
uses SetDebug(bool) wired from main.go. Covers stacks, backup,
cloudflare, integrations, system, monitor, settings, scheduler,
web handlers, storage, metrics, API, selfupdate, and assets.
Also includes the app export/import (.fab bundles) feature from
v0.32.0 and its debug page integration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Concurrency fixes:
- Deep-copy stacks in GetStack/GetStacks to prevent shared state mutation (C04)
- Add per-state mutex to watchdog pathProbeState (C05)
- Guard MetricsCollector.Start() with sync.Once against double-start (C06)
- Hold diskJobMu across entire raw mount operation (C07)
- Add mutex to SetEncryptionKey (C08), MigrateEncryption write lock (H03)
- Use sync.Once for sync.Stop() channel close (H08)
- Set syncing=true before releasing lock in TriggerSync (H09)
- Deep-copy lastDBDump/lastBackup in GetFullStatus (H11)
- Add WaitGroup for stderr goroutine in MigrateDrive (H19)
- Add mutex to SetBackupRunningCheck (M18)
Security fixes:
- Validate Bearer token against Hub API key in CSRF middleware (H16)
- Validate backup paths start with expected prefix in RemoveStack (M12)
- Guard uuid[:8] slice with length check (H20)
- Parse fstab fields exactly for mount target matching (H21)
Bug fixes:
- Use decrypted env vars for compose deploy (C01)
- Log decrypt failures in DecryptMap instead of swallowing (C02)
- Move Deployed=false inside lock in runComposeDeploy (C03)
- Fix activeDrives() to skip disconnected drives (H02)
- Fix Snapshot() stderr extraction from exec.ExitError (H01)
- Check unlockCmd.Run() error in restic (H01)
- Buffer template rendering via bytes.Buffer (H07)
- Thread context.Context through cloudflare client (H10)
- Fix leaf-name collision detection in cross-drive backup (H15)
- Add nil check for crossDriveRunner (H17)
- Use strings.TrimSpace instead of slice on command output (H18)
- Make SaveAppConfig atomic with write-to-tmp+rename (H04)
- Pass encKey on deploy failure SaveAppConfig (H05)
- Fix IPv6 address format in TCP health probe
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1: Deprecate restic as Tier 2 method (rsync only), auto-migrate on startup
Phase 2: Enhanced per-app migration with backup awareness, DB dump copy, auto-cleanup
Phase 3: Full drive migration with decommissioned state, rollback support, wizard UI
Phase 4: Hub report includes decommissioned drive state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug 1 (HIGH): add --exclude _* to rsync --delete so _db/ and _config/
directories are never deleted between backup runs (crossdrive.go)
Bug 2 (MEDIUM): refactor RunDBDumps/RunBackup/RunFullBackup to use
acquireRunning/releaseRunning helpers; extract runDBDumpsInternal and
runBackupInternal so all three public entry points set m.running and
RunFullBackup no longer deadlocks calling the public methods (backup.go)
Bug 3 (MEDIUM): log [WARN] when GetDiskUsage returns nil in
ValidateDestination instead of silently skipping space checks (crossdrive.go)
Bug 4 (MEDIUM): add [WARN] on empty SystemDataPath in NewManager; add
[ERROR] in GetAppDrivePath; guard DumpStackDB against empty/relative paths
(backup.go)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Major refactor of backup and storage paths:
- Per-drive restic repos at <drive>/backups/primary/restic/
- Per-app DB dumps at <drive>/backups/primary/<app>/db-dumps/
- Remove global BackupDir, DBDumpDir, ResticRepo config fields
- Add SystemDataPath config (fallback for apps without HDD)
- New backup/paths.go with pure path computation helpers
- Add GetStackHDDPath to StackDataProvider interface
- Restic methods now accept repoPath as parameter
- Cross-drive backup uses new secondary path structure
- Rename storage/ to appdata/ in scripts and compose templates
- Update protected HDD paths (storage → appdata + backups)
- Simplify backup UI (remove global path displays)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix 1: HDD data backup is now mandatory for all deployed apps.
resolveAppBackupPaths() iterates ListDeployedStacks() directly — no
longer reads GetAppBackupMap() or checks the Enabled flag. DiscoverAppData()
drops backupPrefs parameter; BackupEnabled is set from HasHDDData.
Five dead settings methods removed: IsAppBackupEnabled, SetAppBackup,
GetAppBackupMap, SetAppBackupBulk, GetAppBackupPrefs.
Fix 2: Cross-drive backup now triggers a fresh DB dump (DumpStackDB)
before running. DBDumper interface added to crossdrive.go; Manager
implements it; SetDBDumper wired in main.go. Non-fatal — proceeds with
user data backup even if DB dump fails.
Fix 3: Restore dropdown shows ALL deployed apps (not just HDD+enabled).
restore.go rewritten: always restores config+DB, adds user data if hasHDD.
UI shows restore type banner (full / config+DB / config only) with
color-coded styling. Snapshot API clarified for non-HDD apps.
Fix 4: "Docker kötetek" → "Konfiguráció" — named volumes are not in
the restic backup paths; compose files + app.yaml are what's backed up.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- StackDataProvider interface extended with StopStack/StartStack
- backup.Manager.GetStackHDDMounts() delegates to stackProvider
- RestoreApp() auto-stops app before restic restore, restarts after (even on failure)
- stackAdapter in main.go wires StopStack/StartStack through to stacks.Manager
- GET /api/backup/snapshots?stack={name} filters snapshots by app HDD paths via filterSnapshotsByPaths()
- Restore section simplified: no path list, per-app filtered snapshots, human-friendly timestamp format, single calm warning, empty-result inline message
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Bug fixes:
- GetFullStatus() returns deep copy; CrossDriveSummary/UnconfiguredApps/CrossDriveWarnings
are always nil in the copy so the handler builds them fresh (fixes duplicate-apps bug)
- Replace binary IsMountPoint check with tiered CheckBackupDestination() — path-not-exist,
not-writable, system-drive (warning), disk >90-95% full; shown as warning vs critical
- Remove dead settingsAppBackupHandler / POST /settings/app-backup route (toggle wrote
to settings.json but nothing consumed the flag)
Architecture:
- Unified per-app backup rows: new AppBackupRow struct + buildAppBackupRows() replaces
the two old sections with expandable rows showing all 3 layers per app
- Sequential backup chaining: cross-drive runs immediately after restic (removed
independent cross-drive-daily/cross-drive-weekly scheduler jobs)
- Deploy page: remove "Csak kézi indítás" schedule option; add weekly consistency note
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix backup toggles not appearing (read each app's own HDD_PATH from app.yaml)
- Storage paths registry in settings.json with auto-discovery from deployed apps
- Settings page "Adattárolók" section with disk usage, add/remove/default/schedulable
- Deploy page path field as dropdown of registered storage paths
- Health check storage monitoring (mount point, disk usage alerts)
- Mount-point validation utilities (Linux syscall + cross-platform stubs)
- Controller docker-compose mount changed to /mnt:/mnt:rw for multi-storage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New settings.json persistence layer (internal/settings/settings.go)
- Atomic write (tmp + rename), thread-safe with sync.RWMutex
- Stores password hash overrides and DB validation cache
- Auto-creates on first save, graceful handling if missing
- Auth improvements
- Password resolution priority: settings.json > controller.yaml > none
- Session duration extended to 7 days (was 24h)
- ?next= redirect after session expiry (returns to original page)
- Flash messages on login page (used after password change)
- Conditional logout link (hidden when auth disabled)
- Session invalidation on password change
- New Settings page (/settings)
- Read-only system config display (customer, domain, git, backup, monitoring)
- Password change form with validation (min 8 chars, match check)
- Sidebar "Beállítások" item pinned to bottom above version
- DB validation persistence
- Validation results saved to settings.json after each dump
- Cached data survives container restarts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 4-branch template guard to handle zero-value DumpValidation
(shows "–" instead of misleading "Hiba" when validation never ran)
- Add debug logging to ValidateDump for all code paths
- Add cross-check re-validation in RefreshCache to heal stale
lastDBDump validation state from disk
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix "Helyi mentés" showing "–" after controller restart by synthesizing
LastBackup from snapshot history and LastDBDump from dump files on disk
- New monitoring page (/monitoring) with system info, metrics charts, and
container resource overview
- SQLite metrics store (modernc.org/sqlite, pure Go, no CGO) with 60s
collection interval and 30-day auto-prune
- REST API endpoints: /api/metrics/system, /api/metrics/containers/summary,
/api/metrics/containers/{name}, /api/metrics/sysinfo
- Chart.js 4.4.7 embedded locally for offline environments
- System info provider reads hostname, OS, kernel, CPU, uptime from /proc
- Docker compose updated with /etc/os-release host mount
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Task 1: Protected stacks with .felhom.yml (slug) are now clickable
on both dashboard and stacks pages. "Részletek" button added to
protected stack actions section. Filebrowser .felhom.yml updated
with resources metadata.
Task 2: Backup page now reads from a cached FullBackupStatus that
refreshes every 5 minutes in background + after each backup run.
Page loads instantly instead of blocking on restic/docker subprocesses.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New /backups page with full backup system visibility:
- Status overview cards (local/remote backup, DB count, repo size)
- Schedule section with next-run times and retention policy
- Database table with type, size, validation (table count), status
- Snapshot history table with per-snapshot stats
- Repository info card with paths, integrity status, remote placeholder
- "Mentés most" button with auto-refresh polling
- Empty state when backup not configured
Backend: SnapshotRecord history (ring buffer), DumpValidation,
ListDumpFiles, ListSnapshots, GetFullStatus, restic check tracking.
Server accepts scheduler for next-run time calculation.
Sidebar nav updated with 3rd item, dashboard backup card title clickable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 2 (Monitoring & Health):
- Central job scheduler replacing ad-hoc goroutines (internal/scheduler)
- CPU usage collector via /proc/stat background sampling (internal/system/cpu_linux.go)
- Temperature reading from /sys/class/thermal + /host/sys (Docker mount)
- Load average from /proc/loadavg
- Healthchecks.io-compatible HTTP pinger (internal/monitor/pinger.go)
- System health checks: disk, memory, CPU, temp, Docker, protected containers (internal/monitor/healthcheck.go)
Phase 3 (Backups):
- Database auto-discovery via docker ps + docker inspect (internal/backup/dbdump.go)
- Database dumping via docker exec (pg_dump / mariadb-dump) with atomic writes
- Restic backup integration with auto-password generation (internal/backup/restic.go)
- Backup orchestrator: DB dumps + restic snapshots + weekly prune (internal/backup/backup.go)
- Manual backup trigger via dashboard button and POST /api/backup/run
Dashboard UI:
- CPU usage bar with load average display
- Temperature with colored indicator dot
- Backup status card with last run time, DB count, repo stats
- "Mentés most" button for manual backup trigger
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>