# Backup Orchestrator (Windows Client + Proxmox Server) ## Sommario esecutivo - Client Windows PySide6 con selezione cartelle, log/progresso e switch di schedulazione chiama API FastAPI sul server. - Server Proxmox esegue un job che, tramite SSH verso l’helper OpenSSH del client, avvia un `rsync` pull verso `/srv/backup/current`, mantenendo una history di 20 versioni. - Infrastruttura hardening: HTTPS, SSH, least privilege, logging strutturato, retention/lock e opzioni per compressione e task scheduling. ## Requisiti principali ### Funzionali 1. Il client permette di taggare 1+ cartelle per backup e abilita il bottone “Esegui” solo quando la selezione è valida. 2. Il pulsante invia credenziali SSH (utente/password) e percorsi al backend FastAPI. 3. Il server connette via SSH al client e lancia `rsync` con `--backup --backup-dir=/srv/backup/.history/` e senza `--delete` (pull incrementale). 4. Non si propagano cancellazioni lato client; i file eliminati restano disponibili in `/current` o nello storico. 5. Mantiene fino a 20 esecuzioni storiche per file sovrascritti, archiviando le versioni anteriori. 6. Interfaccia GUI mostra log in tempo reale, barra di progresso, e notifica finale “Backup completato” o dettagli errore. 7. Configurazione locale (es. `config.json`) risiede accanto all’eseguibile e supporta profili, credenziali, toggle Task Scheduler (per l’on/off di `schtasks`). 8. Il client può attivare/disattivare uno scheduler che richiama l’API server in autonomia. ### Non funzionali - Affidabilità: i job sono idempotenti e ripetibili, evitando corruzione dello stato se rilanciati. - Performance: trasferimento differenziale (`rsync` con `-a --info=progress2 --compress` opzionale, `--partial`) e compressione configurabile. - Manutenibilità: separazione GUI, orchestratore e runner `rsync`/logging. - Sicurezza LAN: autenticazione token su API, canali HTTPS/SSH, criteri di privilegio ridotti, protezione credenziali (DPAPI o prompt ad ogni esecuzione), log/rotazioni. ## Architettura proposta ### Componenti critici - **Client GUI (PySide6)**: gestisce profili, selezione cartelle, switch Task Scheduler e visualizzazione del log/polling di stato; comunica via HTTPS con token JWT. - **Configurazione locale (`config.json`)**: profili, cartelle, endpoint API, preferenze di compressione, flag scheduler. - **Windows OpenSSH Server (`sshd`) + `rsync.exe` portable**: riceve connessioni SSH dal server e invoca `rsync --server` per eseguire i transfer. - **Orchestrator API (FastAPI + Uvicorn)**: espone `/auth/login`, `/profiles`, `/backup/start`, `/backup/status/{job_id}`, `/backup/log/{job_id}`, `/health`. - **Job Runner (systemd o servizio)**: serializza job, acquisisce lock per non sovrapporsi, gestisce il comando SSH/rsync, archivia log e progressi in DB, aggiorna stato API. - **Metadata Store (SQLite/Postgres)**: conservazione job, log, stato, retention history. - **Backup Storage**: `/srv/backup/current` e `/srv/backup/.history/`; possibilità di snapshot ZFS opzionale. ### Interazioni chiave ```mermaid componentDiagram component "Windows Client GUI\n(PySide6)" as GUI component "Local Config\n(config.json)" as CFG component "Windows OpenSSH Server\n(sshd)" as SSHD component "Rsync Binary\n(rsync.exe portable)" as RSYNCW component "Backup Orchestrator API\n(FastAPI + Uvicorn)" as API component "Job Runner\n(systemd service)" as RUNNER component "Metadata Store\n(SQLite/Postgres)" as DB component "Backup Storage\n/current + /.history" as STORE GUI --> CFG : read/write GUI --> API : HTTPS (LAN)\nStart/Status API --> DB : store jobs/log API --> RUNNER : enqueue/trigger RUNNER --> SSHD : SSH connect (pull) SSHD --> RSYNCW : remote rsync command RUNNER --> STORE : write backup data ``` ### Flusso operativo (quando l’utente preme “Esegui”) ```mermaid sequenceDiagram participant U as Utente participant GUI as Client GUI (Win) participant API as Orchestrator API (Server) participant RUN as Job Runner (Server) participant SSH as SSH (Win sshd) participant STO as Storage (Server) U->>GUI: Seleziona cartelle GUI->>GUI: Valida cartelle (>=1) e abilita "Esegui" U->>GUI: Click "Esegui" GUI->>API: POST /backup/start (profilo, cartelle, credenziali) API->>API: Crea job_id + stato QUEUED API->>RUN: Avvia job(job_id) RUN->>SSH: ssh user@client "rsync --server ..." SSH->>RUN: Stream stdout/stderr (progress/log) RUN->>STO: Scrive su /current + versioni su /.history/ RUN->>API: Aggiorna stato COMPLETED/FAILED + summary GUI->>API: GET /backup/status/{job_id} (poll/stream) API->>GUI: stato + progress + log GUI->>U: "Backup completato" (o errore) ``` ### Deployment ```mermaid deploymentDiagram node "LAN" { node "PC Windows 11 (Client)" { artifact "BackupClient.exe\n(PySide6 packaged)" as EXE artifact "config.json" as CJSON node "Windows Feature" { artifact "OpenSSH Server (sshd)" as WSSHD } artifact "rsync.exe portable" as WRSYNC } node "Proxmox Host" { node "VM Debian (Backup Server)" { artifact "backup-orchestrator\n(FastAPI)" as SAPI artifact "job-runner\n(systemd)" as SJR artifact "rsync" as SRSYNC artifact "db (sqlite/postgres)" as SDB artifact "/srv/backup/...\n(current/.history)" as SST } } } EXE --> SAPI : HTTPS 443 (LAN) SJR --> WSSHD : SSH 22 (LAN) SJR --> SST : local filesystem ``` ``` ## API e sicurezza - **Autenticazione**: `/auth/login` restituisce JWT con scadenza, rate limit + lockout. - **Profiling**: `/profiles` CRUD (nome, cartelle, scheduling). - **Backup**: `/backup/start` richiama job(principale), `GET /backup/status/{job_id}`, `GET /backup/log/{job_id}`. - **Health**: `/health` (autenticata o solo LAN) restituisce stato/versione. ### Protezioni - HTTPS con cert self-signed o CA locale. - Token scaduti/e refresh. - Validazione path (no path traversal, esistenza cartelle); permetti solo cartelle allow-list. - SSH dai soli IP server e utente `backupsvc` con shell limitata e permessi su `/srv/backup`. - Log strutturati (JSON), rotazione via `logrotate`, niente password nei log. ## Retention e rsync - Ogni esecuzione crea un `run_id`, `rsync` esegue `--backup --backup-dir=/srv/backup/.history/` e `--info=progress2`. - `current/` contiene lo stato attivo; `.history/` conserva vecchie versioni per i file diversificati. - Un task di cleanup mantiene solo le ultime 20 esecuzioni, cancellando `.history` più vecchie. ## Strategia scheduling e configurazione - Client: switch Task Scheduler che attiva/disattiva una `schtasks` che lancia `BackupClient.exe --auto` (o simile) con token. - Config facoltativa per credenziali salvate (nemmeno nel file in chiaro) tramite Windows DPAPI, ma l’uso di prompt password ogni job rimane default. - API: job queue con lock, `systemd` service per runner; `rsync` timeout/retry configurabili. ## Fasi di implementazione e stime 1. **Setup server** (0.5–1 giorno): Debian su Proxmox, storage dedicato `/srv/backup`, user/permessi, `rsync`, OpenSSH client e service. 2. **Orchestrator FastAPI + runner** (1.5–2.5 giorni): API start/status/log, gestione DB (SQLite default, Postgres opzione), job queue, retention automatica. 3. **Client PySide6** (2–4 giorni): GUI selezione cartelle/profili, log/progress, switch Task Scheduler, config.json, packaging PyInstaller. 4. **Integrazione Windows** (1–2 giorni): script abilitazione OpenSSH/rsync, firewall rules, test permessi lunghi. 5. **Hardening + QA** (1–2 giorni): logging, rate limit, E2E manuali/schedulati, threat modeling leggero. ## Checklist sicurezza e operatività - SSH solo da server, firewall Windows limitato ad IP del backup server. - Password SSH non loggata, prompt per ogni job (DPAPI opzionale). - HTTPS interno con cert gestione. - Validazione input (allowlist, no path traversal, sanitizzazione). - User Linux dedicato `backupsvc`, directory `700`, log `640`. - Lock job per evitare duplicati, timeout `rsync`. ## Deliverable attesi - Repo server: FastAPI + runner, script provisioning, doc installazione, test base. - Repo client: PySide6 GUI, config schema, Task Scheduler script, rsync portable bundle. - Documentazione: manuale utente, runbook admin, threat model + checklist. - Pipeline CI: lint/test/build/release. ## Note aggiuntive - Password SSH passata al server solo in memoria per job; non persistita nel DB. - Il bottone sul client rimane il trigger UX, ma la copia vera è un pull orchestrato dal server grazie all’SSH.