瀏覽代碼

docs: ajout du cahier des charges v4.0 dans doc/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cédric Hansen 1 天之前
父節點
當前提交
08758fefa8
共有 1 個文件被更改,包括 379 次插入0 次删除
  1. 379 0
      doc/CDC_backupmanager_ynh.md

+ 379 - 0
doc/CDC_backupmanager_ynh.md

@@ -0,0 +1,379 @@
+# 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 <app_id> --name <archive_name>
+BACKUP_CORE_ONLY=1 yunohost backup create --apps nextcloud --name <archive_name>
+```
+```json
+{ "app_id": "nocodb", "core_only": false }
+```
+
+### `ynh_system`
+```bash
+yunohost backup create --system --name <archive_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/<id>/runs
+POST /api/v1/jobs/<id>/run
+GET  /api/v1/archives
+GET  /api/v1/archives/<name>/info
+DELETE /api/v1/archives/<name>
+POST /api/v1/archives/<name>/transfer
+POST /api/v1/archives/upload/start
+POST /api/v1/archives/upload/<id>/chunk/<n>
+POST /api/v1/archives/upload/<id>/finish
+DELETE /api/v1/archives/upload/<id>
+POST /api/v1/archives/<name>/restore          # Phase 3
+GET  /api/v1/archives/<name>/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*