CDC_backupmanager_ynh.md 10 KB

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

-- 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

yunohost backup create --apps <app_id> --name <archive_name>
BACKUP_CORE_ONLY=1 yunohost backup create --apps nextcloud --name <archive_name>
{ "app_id": "nocodb", "core_only": false }

ynh_system

yunohost backup create --system --name <archive_name>
{ "parts": [] }

custom_dir

{
  "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

{ "database": "mabase", "user": "mabase_user" }

postgresql

{ "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 :

{
  "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) :

[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)

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