deamon-vault/infra/backup-strategy-2026-04-18.md
2026-04-18 21:31:23 +02:00

337 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Stratégie de backup DAEMON
type: infra
created: 2026-04-18
updated: 2026-04-18
owner: jerem
status: draft-en-cours-de-déploiement
tags:
- infra
- backup
- kopia
- security
related:
- "[[infra/vps-config-2026-04-17]]"
- "[[_adn/soul]]"
---
# Stratégie de backup DAEMON — 2026-04-18
> **État** : plan validé, déploiement en cours. NAS en attente de validation par Fab.
---
## 🎯 Objectif
Protéger les données critiques de l'écosystème DAEMON (vault Obsidian, data Notion, configs infrastructure) contre :
- Panne matérielle VPS
- Corruption / suppression accidentelle
- Compromission sécurité (ransomware, intrusion)
- Perte compte iCloud / Google
- Faillite / coupure d'un fournisseur
Règle appliquée : **3-2-1** (3 copies, 2 médias différents, 1 offsite minimum). En réalité on vise **3-3-2** : 3 destinations de backup, 3 médias distincts, 2 offsites.
---
## 📊 Ce qui est backupé (par criticité)
### Tier 1 — catastrophique si perdu (backup quotidien)
| Source | Contenu | Pourquoi critique |
|---|---|---|
| `/home/jerem/vault/` | Vault Obsidian (cerveau DAEMON) | Contient toute la mémoire, les règles, l'historique |
| `/home/jerem/notion-backup/` | Export Notion quotidien en Markdown | Clients, projets, habitudes, journaling |
### Tier 2 — reinstallable mais douloureux (backup hebdomadaire le dimanche)
| Source | Contenu |
|---|---|
| `/home/jerem/.openclaw/` | Config OpenClaw, credentials Google/Gmail |
| `/home/jerem/daemon-infra/` | Scripts, systemd units, config nginx/wireguard |
| `/etc/systemd/system/` | Services systemd |
| `/etc/nginx/` | Config reverse proxy |
| `/etc/wireguard/` | Tunnel VPN |
### Tier 3 — pas backupé
- Logs OpenClaw
- Caches, sessions
- Dossiers `/tmp/`, `/var/cache/`
- Anything ephemeral
### Non backupé volontairement
- **Doppler** : MFA activé, régénération possible en 4h. Risque accepté.
- **Bot tokens Slack/WhatsApp** : stockés dans Doppler, idem ci-dessus.
---
## 🗺️ Topologie
```
/home/jerem/vault (live VPS)
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
Kopia local Kopia NAS ami (WebDAV) Kopia Google Drive
/var/backups/ nasprodfab.duckdns gdrive jerem
7 jours rétention 5 ans rétention 5 ans rétention
│ │ │
└── restore rapide └── offsite physique └── offsite cloud
```
**Pas d'offsite** : Kopia local (même machine que la source).
**Offsite physique** : NAS Ugreen de Fab.
**Offsite cloud** : Google Drive (compte jerem, 5TB).
---
## 🔒 Sécurité
### Chiffrement
- **Côté client, avant transit** : Kopia AES-256-GCM
- Le NAS de Fab voit uniquement des blobs chiffrés illisibles
- Google Drive idem
### Gestion de la passphrase Kopia
La passphrase de chiffrement est stockée à **3 endroits** :
1. **VPS** : `/root/.kopia-password` (mode `600`, root-only)
2. **Bitwarden** : entrée "Kopia DAEMON backup passphrase"
3. **Papier** : dans le coffre physique de Jerem
**Si VPS détruit + Bitwarden perdu → backups restaurables via la copie papier.**
**Si tous les 3 sont perdus → backups illisibles. Risque accepté : probabilité extrêmement faible.**
### Secrets NAS (WebDAV)
Stockés dans **Doppler** `daemon-infra/prd` :
- `NAS_WEBDAV_URL`
- `NAS_WEBDAV_USER`
- `NAS_WEBDAV_PASS`
Injectés dans l'environnement Kopia au moment du backup par le script de démarrage, jamais écrits en clair sur disque.
### Secrets Google Drive
Utilise l'OAuth Google déjà configuré pour Calendar/Gmail. Refresh token dans Doppler : `GOOGLE_REFRESH_TOKEN`.
---
## ⏰ Planning
| Quand | Quoi | Où |
|---|---|---|
| Chaque nuit à **3h00 Paris** (heure VPS fixe, ne change jamais en voyage) | Snapshot Kopia Tier 1 + 2 | Local VPS + NAS + gdrive |
| Chaque dimanche **3h30** | Snapshot Tier 2 seul si rien de Tier 1 n'a tourné | Idem |
| Chaque lundi **4h00** | **Test de restore automatique** (extraction d'un snapshot random vers `/tmp`, comparaison hash) | Local |
**Pourquoi 3h Paris fixe** : le backup tourne sur le VPS (pas sur le Mac), donc l'heure physique de Jerem importe peu. 3h Paris = toujours pendant une période de faible activité chez lui, peu importe le fuseau.
---
## 📦 Rétention GFS (Grandfather-Father-Son)
Kopia applique automatiquement :
| Horizon | Snapshots gardés |
|---|---|
| 7 derniers jours | Tous (1 par jour) |
| 4 dernières semaines | 1 par semaine |
| 12 derniers mois | 1 par mois |
| 5 dernières années | 1 par an |
**Total théorique** : ~28 snapshots actifs à n'importe quel instant.
**Taille réelle** : grâce à la déduplication Kopia (chunks unique stockés une seule fois), ~150-300 MB pour le repo complet, pas 28× la taille du vault.
---
## 🔄 Pipeline de backup (nightly 3h)
```
┌──────────────────────────────────────────────────────────────┐
│ 0. Pull secrets Doppler (NAS_*, GOOGLE_*) │
│ │
│ 1. Notion export │
│ ├─ notion-export → /home/jerem/notion-backup/*.md │
│ ├─ git commit + push (repo Gitea dédié) │
│ ├─ SI ÉCHEC : alerte Slack + continue (export J-1 dispo) │
│ └─ ping Kuma push monitor "notion-export-ok" │
│ │
│ 2. Kopia snapshot local │
│ └─ sources : vault, notion-backup, daemon-infra, │
│ .openclaw, /etc/* (hebdo seulement) │
│ │
│ 3. Kopia sync vers NAS ami (WebDAV) │
│ └─ SI ÉCHEC (NAS offline) : alerte + continue │
│ │
│ 4. Kopia sync vers Google Drive │
│ └─ SI ÉCHEC : alerte + continue │
│ │
│ 5. Kopia maintenance (GFS prune, compaction) │
│ │
│ 6. Ping Kuma "daemon-backup-ok" │
└──────────────────────────────────────────────────────────────┘
```
**Philosophie** : jamais d'arrêt brutal. Une étape qui rate alerte et laisse les autres continuer.
---
## 🚨 Monitoring et alertes
### Uptime Kuma Push Monitors
| Monitor | Seuil | Action si KO |
|---|---|---|
| `daemon-backup-ok` | Pas de ping en 25h | Alerte Slack (normal) |
| `notion-export-ok` | Pas de ping en 25h | J1 Slack normal · J2 Slack urgent + email · J3 appel téléphonique |
| `kopia-local-integrity` | Check intégrité hebdo | Slack urgent |
| `restore-test-ok` | Test restore hebdo | Slack normal si échec, urgent si 2× consécutif |
### Cascade d'escalade (conforme [[_adn/soul]] section 2)
| Palier | Canal | Niveau Kuma |
|---|---|---|
| Échec J1 | Slack DM | Normal |
| Échec J2 | Slack all devices ring + email | Urgent |
| Échec J3 | Appel téléphonique + tout ce qui précède | Très urgent |
---
## 🖥️ Interface Kopia UI
- **URL** : `https://kopia.daemon.jeremunlimited.com`
- **Auth** : basic auth + token header (pattern identique à Control UI OpenClaw)
- **Headers** : `X-Robots-Tag: noindex`
- **Accès** : public HTTPS ou LAN via WireGuard
- **Permissions** : lecture + restore uniquement (création snapshots bloquée en UI, seul le cron peut créer)
Utilisations :
- Voir les snapshots passés et leur taille
- Restaurer un fichier en 2 clics
- Vérifier l'intégrité d'un snapshot
- Monitorer l'espace disque des repos
---
## 🛠️ Commandes utiles (CLI)
```bash
# Lister les snapshots locaux
kopia snapshot list
# Restaurer la dernière version du vault
kopia snapshot restore latest /tmp/restore-vault
# Restaurer un fichier spécifique d'un snapshot donné
kopia snapshot restore <snapshot-id>/path/to/file /tmp/restored-file
# Vérifier l'intégrité
kopia snapshot verify
# Voir l'espace utilisé
kopia content stats
# Purger manuellement (suit la policy GFS)
kopia policy set --keep-latest 7 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-annual 5
# Forcer un backup immédiat
sudo systemctl start daemon-backup.service
```
---
## 📝 Plan de restauration (runbook)
### Scénario 1 : j'ai supprimé un fichier du vault
1. Ouvrir l'UI Kopia
2. Naviguer dans le dernier snapshot → `vault/`
3. Clic droit sur le fichier → Restore → `/home/jerem/vault/`
4. `git add` + commit dans le vault
### Scénario 2 : le VPS est HS, il faut tout reconstruire
1. Déployer un nouveau VPS (Hetzner, même config)
2. Installer Kopia
3. Restaurer la passphrase depuis Bitwarden (ou papier)
4. Connecter Kopia au repo Google Drive (plus rapide que NAS distant)
```bash
kopia repository connect gdrive \
--folder-id $FOLDER_ID \
--credentials-file /path/to/oauth.json
```
5. `kopia snapshot restore latest --target /`
6. Reconfigurer secrets (régénérer OAuth Google, Doppler tokens)
7. Relancer systemd : `systemctl start openclaw`
**Temps cible de restauration complète** : < 4h (avec config nginx + wireguard + openclaw à reconfigurer).
### Scénario 3 : compromission sécurité, besoin de rollback
1. Identifier la date de compromission depuis les logs
2. Restaurer le snapshot de la veille (avant compromission)
3. `kopia snapshot restore <snapshot-pre-compromission> --target /home/jerem/`
4. Rotation de tous les secrets (Doppler regenerate)
5. Invalider tous les OAuth Google / Slack / Notion tokens
6. Recréer depuis zéro les tokens
---
## 📐 Dimensionnement estimé
| Donnée | Taille actuelle | Taille dans 5 ans (×10) |
|---|---|---|
| Vault Obsidian | ~10 Mo | ~100 Mo |
| Notion export mirror | ~50 Mo | ~500 Mo |
| daemon-infra | ~5 Mo | ~50 Mo |
| .openclaw config | ~2 Mo | ~20 Mo |
| /etc/* (tier 2) | ~10 Mo | ~10 Mo (stable) |
| **Total source** | **~77 Mo** | **~680 Mo** |
| **Total repo Kopia (28 snapshots + dedup + compression)** | **~200 Mo** | **~1.5 Go** |
**Quota à demander à Fab** : 10 Go (avec marge confortable).
**Usage Google Drive** : 10 Go sur 5 TB (0.2 %).
**Usage VPS local** : ~200 Mo (7 jours de rétention, largement acceptable).
---
## ❓ Points en attente
- [ ] **Validation Fab** : autorisation de créer un dossier `Jerem Unlimited Backup DAEMON` sur le NAS + quota
- [ ] **Passphrase Kopia** : à générer et à stocker dans Bitwarden + papier
- [ ] **Secrets NAS dans Doppler** : `NAS_WEBDAV_URL`, `NAS_WEBDAV_USER`, `NAS_WEBDAV_PASS`
- [ ] **Tests de restore** : valider le scénario complet sur un VPS blank (exercice trimestriel)
---
## 📚 Alternatives considérées (historique)
| Option | Rejetée car |
|---|---|
| **Obsidian Sync officiel** | Payant, vendor lock-in, ne couvre pas Notion |
| **Backblaze B2** | Jerem a le NAS ami gratuit, pas besoin de cloud payant |
| **iCloud pour backup serveur** | Pas d'API serveur native, besoin d'un Mac allumé |
| **Restic** (vs Kopia) | Pas d'UI web Jerem préfère avoir le visuel |
| **Borg** (vs Kopia) | Pas de backend WebDAV natif, moins polyvalent |
| **Notion → incremental seulement** | Aucun outil mature, complexité de code non justifiée vu que Kopia dedupe déjà |
---
## 🔗 Références
- [Kopia documentation](https://kopia.io/docs/)
- [Règle 3-2-1 (US-CERT)](https://www.cisa.gov/sites/default/files/publications/data_backup_options.pdf)
- [SOUL.md section alertes](/_adn/soul.md#2-règles-cardinales-non-negociables)
- Doc config VPS : [[infra/vps-config-2026-04-17]]
---
*Document vivant, à mettre à jour à chaque évolution de la stratégie.*