# Cahier des charges — `backupmanager_ynh` **Version 4.0 — Finale | 2026-05-08** ## 1. Vision générale Application YunoHost centralisant toutes les sauvegardes d'un serveur, s'appuyant au maximum sur les outils YunoHost natifs, extensible en écosystème fédéré multi-instances. **Périmètre :** Apps YNH · Système YNH · Répertoires custom · MySQL · PostgreSQL ``` ┌──────────────┐ API ┌──────────────┐ API ┌──────────────┐ │ Instance A │◄─────►│ Instance B │◄─────►│ Instance C │ │ (maître) │ │ (nœud) │ │ (nœud) │ └──────────────┘ └──────────────┘ └──────────────┘ N'importe quelle instance peut être "maître" ``` --- ## 2. Décisions clés | Sujet | Décision | |---|---| | Langage | Python 3 + Flask | | Scheduler | APScheduler + SQLite | | DB | SQLite + SQLAlchemy | | Frontend | Jinja2 + TailwindCSS CDN | | Proxy/Service | Nginx + systemd YunoHost natifs | | Archives | `/home/yunohost.backup/archives/` | | Nommage | `jerry_nocodb_20260508.tar` | | Auth dashboard | SSO YunoHost — admins uniquement | | Auth API | `/api` ouvert SSOwat + token `X-BackupManager-Key` | | Transfert | HTTP chunked (défaut) + SSH/rsync (optionnel) | | Restauration | Complète : fichiers + user système + systemd + DB | --- ## 3. Structure du dépôt ``` backupmanager_ynh/ ├── manifest.toml ├── scripts/ │ ├── _common.sh │ ├── install / remove / backup / restore / upgrade ├── conf/ │ ├── nginx.conf │ ├── systemd.service │ └── app.conf.j2 ├── sources/ │ ├── app.py # Flask routes + API REST │ ├── scheduler.py # APScheduler │ ├── db.py # SQLAlchemy │ ├── retention.py # Moteur count/daily/gfs │ ├── jobs/ │ │ ├── ynh_backup.py # yunohost backup create │ │ ├── custom_dir.py # tar + rsync chemins libres │ │ ├── db_dump.py # mysqldump / pg_dump │ │ └── transfer.py # rsync SSH / SFTP │ ├── federation/ │ │ ├── api.py # Endpoints REST │ │ ├── client.py # Appels instances distantes │ │ └── sync.py # Sync état réseau │ └── templates/ │ ├── base.html │ ├── dashboard_local.html │ ├── dashboard_network.html │ ├── job_form.html │ └── job_history.html └── doc/ ``` --- ## 4. Modèle de données SQLite ```sql -- Jobs de sauvegarde CREATE TABLE jobs ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, type TEXT NOT NULL, -- ynh_app|ynh_system|custom_dir|mysql|postgresql config_json TEXT, cron_expr TEXT NOT NULL, -- ex: "0 3 * * 1" retention_mode TEXT NOT NULL, -- count|daily|gfs retention_value INTEGER NOT NULL, enabled BOOLEAN DEFAULT 1, core_only BOOLEAN DEFAULT 0, created_at DATETIME, updated_at DATETIME ); -- Historique des exécutions CREATE TABLE runs ( id INTEGER PRIMARY KEY, job_id INTEGER REFERENCES jobs(id), started_at DATETIME, finished_at DATETIME, status TEXT, -- running|success|error log_text TEXT, archive_name TEXT, size_bytes INTEGER ); -- Instances distantes enregistrées CREATE TABLE remote_instances ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, -- ex: "tom" url TEXT NOT NULL, -- https://tom.domaine.fr api_key TEXT NOT NULL, last_seen DATETIME, status TEXT, -- online|offline|error created_at DATETIME ); -- Cache états distants CREATE TABLE remote_runs ( id INTEGER PRIMARY KEY, instance_id INTEGER REFERENCES remote_instances(id), job_name TEXT, last_run_at DATETIME, last_status TEXT, archive_count INTEGER, last_size_bytes INTEGER ); -- Transferts chunked en cours CREATE TABLE uploads ( upload_id TEXT PRIMARY KEY, -- uuid4 filename TEXT, total_size INTEGER, chunk_size INTEGER, chunks_received INTEGER DEFAULT 0, checksum TEXT, -- SHA256 started_at DATETIME, status TEXT -- pending|in_progress|complete|error ); ``` --- ## 5. Types de jobs ### `ynh_app` ```bash yunohost backup create --apps --name BACKUP_CORE_ONLY=1 yunohost backup create --apps nextcloud --name ``` ```json { "app_id": "nocodb", "core_only": false } ``` ### `ynh_system` ```bash yunohost backup create --system --name ``` ```json { "parts": [] } ``` ### `custom_dir` ```json { "source_path": "/opt/hermes-agent", "excludes": ["cache/", "logs/", "*.tmp"], "restore": { "system_user": { "name": "hermes-agent", "home": "/opt/hermes-agent", "shell": "/bin/false" }, "systemd_service": { "name": "hermes-agent", "service_file": "/opt/hermes-agent/hermes-agent.service" }, "permissions": { "owner": "hermes-agent:hermes-agent", "mode": "750" }, "post_restore_commands": ["systemctl restart hermes-agent"] } } ``` **Format archive compatible YunoHost :** ``` jerry_hermes-agent_20260508.tar ├── backup.csv # requis YNH ├── backup_info.json # métadonnées BackupManager └── data/custom/opt/hermes-agent/... jerry_hermes-agent_20260508.info.json # SÉPARÉ hors tar, requis YNH ``` ### `mysql` ```json { "database": "mabase", "user": "mabase_user" } ``` ### `postgresql` ```json { "database": "mabase", "user": "postgres" } ``` --- ## 6. Rétention ### Mode `count` ``` → Garde les N dernières archives → Supprime les plus anciennes ``` ### Mode `daily` — fenêtre glissante ``` retention_value: 7 → 1 archive par jour sur les 7 derniers jours → Fenêtre glissante J-1 à J-7 → Toute archive > J-7 supprimée ``` ### Mode `gfs` *(Phase 4)* ``` daily: 7 / weekly: 4 / monthly: 3 ``` --- ## 7. Nommage des archives **Format :** `{instance}_{app}_{YYYYMMDD}.tar` ``` jerry_nocodb_20260508.tar jerry_nextcloud_20260508.tar jerry_system_20260508.tar jerry_hermes-agent_20260508.tar jerry_mysql_mabase_20260508.tar ``` **`backup_info.json` embarqué dans le tar :** ```json { "instance_name": "jerry", "instance_url": "https://jerry.mondomaine.fr", "app": "nocodb", "type": "ynh_app", "created_at": "2026-05-08T03:00:00", "backupmanager_version": "1.0.0", "yunohost_version": "12.1.17" } ``` --- ## 8. Intégration YunoHost | Outil YNH | Usage | |---|---| | `yunohost backup create` | Jobs ynh_app et ynh_system | | `yunohost backup restore` | Restauration webadmin | | `yunohost app list --output-as json` | Formulaire job | | `/home/yunohost.backup/archives/` | Toutes les archives | | Nginx + systemd + SSOwat + Let's Encrypt | Infra app | **SSOwat (`manifest.toml`) :** ```toml [resources.permissions.main] url = "/" allowed = "admins" [resources.permissions.api] url = "/api" allowed = "visitors" # sécurisé par token Flask auth_header = false protected = true ``` --- ## 9. API REST Tous les endpoints protégés par `X-BackupManager-Key`. ``` GET /api/v1/health GET /api/v1/jobs GET /api/v1/jobs//runs POST /api/v1/jobs//run GET /api/v1/archives GET /api/v1/archives//info DELETE /api/v1/archives/ POST /api/v1/archives//transfer POST /api/v1/archives/upload/start POST /api/v1/archives/upload//chunk/ POST /api/v1/archives/upload//finish DELETE /api/v1/archives/upload/ POST /api/v1/archives//restore # Phase 3 GET /api/v1/archives//restore/status # Phase 3 ``` --- ## 10. Transfert inter-instances ### HTTP Chunked (défaut) ``` Chunks : 50 MB | Reprise : upload_id SQLite | Vérif : SHA256 | Transport : HTTPS ``` ### SSH/rsync (optionnel, activable par instance) ```bash ssh-keygen -t ed25519 -f $data_dir/keys/backupmanager_rsa -N "" -C "backupmanager@jerry" rsync -az -e "ssh -i $key -p $port" archive.tar archive.info.json user@host:/home/yunohost.backup/archives/ ``` ### Sélection automatique | Situation | Mode | |---|---| | SSH non configuré | HTTP chunked | | SSH + archive < 2 GB | HTTP chunked | | SSH + archive > 2 GB | rsync auto | | Override manuel | Au choix | --- ## 11. Restauration assistée | Action | Dashboard BM | Webadmin YNH | |---|---|---| | App YNH | ✅ (via YNH) | ✅ natif | | Système YNH | ✅ (via YNH) | ✅ natif | | Fichiers custom_dir | ✅ complet | ✅ partiel | | User système | ✅ `useradd` | ❌ | | Service systemd | ✅ `systemctl` | ❌ | | Permissions | ✅ `chown/chmod` | ❌ | | Post-restore commands | ✅ | ❌ | | MySQL / PostgreSQL | ✅ | ❌ | | Port firewall | ✅ `yunohost firewall` | ❌ | | Instance distante | ✅ Phase 3 | ❌ | --- ## 12. Sécurité | Élément | Mesure | |---|---| | Dashboard | SSO YunoHost admins | | Token API | `secrets.token_hex(32)`, hashé bcrypt | | Clé SSH | ed25519, `$data_dir/keys/`, permissions `600` | | Credentials DB | Jamais en clair, config protégée | | Logs | Sans credentials | | Inter-instances | HTTPS obligatoire | --- ## 13. Phases de développement ### Phase 1 — MVP local - [ ] manifest.toml, install, remove, nginx, systemd - [ ] Flask + SQLite + APScheduler - [ ] Jobs ynh_app et ynh_system - [ ] Rétention count et daily - [ ] Dashboard local (jobs + historique + Run now) ### Phase 2 — Périmètre complet - [ ] Jobs custom_dir (exclusions + format YNH compatible) - [ ] Jobs mysql et postgresql - [ ] Restauration complète custom_dir + DB - [ ] Destinations rsync SSH / SFTP - [ ] Notifications email ### Phase 3 — Fédération - [ ] API REST complète - [ ] Enregistrement instances distantes - [ ] Dashboard vue réseau - [ ] Transfert HTTP chunked + SSH/rsync optionnel - [ ] Restauration distante ### Phase 4 — Finitions - [ ] Rétention gfs - [ ] Export/import config JSON - [ ] Script backup/restore de l'app pour YNH - [ ] Tests automatisés --- *backupmanager_ynh — CDC v4.0 — 2026-05-08*