Initial commit
This commit is contained in:
158
SPEC.md
Normal file
158
SPEC.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# 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/<run_id>` 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/<run_id>`; 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_id>
|
||||
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/<run_id>` e `--info=progress2`.
|
||||
- `current/` contiene lo stato attivo; `.history/<run_id>` 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.
|
||||
Reference in New Issue
Block a user