v0.11.8 — Per-App Cross-Drive Backup (3-2-1 rule)

New feature: backup app data to a secondary storage drive to satisfy
the "different media" requirement of the 3-2-1 backup rule.

- settings.go: CrossDriveBackup struct, AppBackupPrefs.CrossDrive field,
  getter/setter methods, GetOrCreateCrossDrivePassword, preserves
  cross-drive config when toggling nightly backup

- crossdrive.go (new): CrossDriveRunner with rsync and restic backends.
  Validates destination (mount point, writable), prevents source/dest
  overlap, per-app concurrency lock, persists last_run/status/size.

- main.go: wire CrossDriveRunner, register cross-drive-daily (03:30)
  and cross-drive-weekly (04:30 Sundays) scheduler jobs

- router.go: 4 new API endpoints — save config, trigger run, get status,
  run-all. Router now accepts Settings and CrossDriveRunner.

- server.go: Server struct accepts CrossDriveRunner, new web route
  POST /settings/cross-backup/{name}

- handlers.go: deployHandler populates CrossDriveConfig, BackupDestPaths,
  BackupDestWarning, AppBackupEnabled. settingsCrossBackupHandler saves
  config. backupsHandler builds CrossDriveSummary, UnconfiguredApps,
  CrossDriveWarnings for backup page.

- deploy.html: "Biztonsági mentés" card with destination/method/schedule
  dropdowns, last-run status, manual trigger button, flash messages.

- backups.html: "Másolatok másik meghajtóra" section with per-app
  status rows, unconfigured app warnings, "Összes futtatása most" button.

- style.css: margin-bottom fix for .deploy-stale-data, new cross-drive
  card and list styles.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 15:45:31 +01:00
parent d4da3e6ea2
commit 1a8036d055
12 changed files with 1126 additions and 44 deletions
+20
View File
@@ -53,6 +53,21 @@ type SnapshotRecord struct {
HasStats bool `json:"has_stats"` // false for historical entries loaded from restic
}
// CrossDriveSummaryItem holds display data for one app's cross-drive backup.
type CrossDriveSummaryItem struct {
StackName string
DisplayName string
Method string // "rsync" or "restic"
MethodLabel string // "Egyszerű másolat" or "Restic"
DestPath string
DestLabel string // storage path label
Schedule string
ScheduleLabel string // "Naponta" or "Hetente" or "Kézi"
LastStatus string // "ok", "error", "running", ""
LastRunShort string // formatted short time e.g. "03:15"
SizeHuman string
}
// FullBackupStatus contains everything the backup page needs.
type FullBackupStatus struct {
Enabled bool
@@ -88,6 +103,11 @@ type FullBackupStatus struct {
// App data backup
AppDataInfo []AppBackupInfo
// Cross-drive backup summary
CrossDriveSummary []CrossDriveSummaryItem
UnconfiguredApps []CrossDriveSummaryItem // apps with HDD data but no cross-drive config
CrossDriveWarnings []string // destination health warnings
// Flash messages (set by handlers, passed through redirect)
FlashSuccess string
FlashError string