> ## Documentation Index
> Fetch the complete documentation index at: https://docs.snakysec.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 03 backup strategy

# Stratégie de sauvegarde — 3-2-1 multi-fournisseur souverain FR

## 1. Objet

Décrit la stratégie de sauvegarde appliquée à la plateforme MSSP SnakySec,
conforme au principe industriel **3-2-1** (3 copies, 2 médias, 1 hors-site)
avec une variante renforcée **3-2-1-1-0** (1 copie immutable, 0 erreur lors
du dernier test).

Cette stratégie sert de référence aux scripts d'implémentation
(`scripts/dr/backup/*.sh`) et à la CI de vérification d'intégrité.

## 2. Principe 3-2-1 appliqué

| Règle                           | Implémentation SnakySec                                                                                |
| ------------------------------- | ------------------------------------------------------------------------------------------------------ |
| **3 copies** des données        | (1) prod live VPS OVH + (2) backup OVH Object Storage + (3) backup Scaleway Object Storage Paris       |
| **2 médias** différents         | Block storage local (volumes Docker) + object storage S3-compatible (chiffré client-side)              |
| **1 copie hors-site**           | Les 2 copies object storage sont hors-site (datacenters distincts du VPS prod)                         |
| **+1 immutable** (renforcement) | Versioning + retention lock activés sur les buckets OVH/Scaleway (90j non-modifiable, anti-ransomware) |
| **+0 erreur**                   | Test de restauration mensuel avec PV consigné dans `docs/dr/test-results/`                             |

## 3. Choix multi-fournisseur souverain FR

### 3.1 Justification

Architecture découplée **OVH + Scaleway** plutôt que single-provider :

| Risque couvert                                              | Mitigation                                     |
| ----------------------------------------------------------- | ---------------------------------------------- |
| Datacenter OVH HS (incident type Strasbourg 2021)           | Scaleway Paris reste accessible                |
| Suspension de compte OVH (litige facturation, abus signalé) | Scaleway accessible avec credentials distincts |
| Compromission credentials OVH                               | Scaleway non impacté                           |
| Failure logiciel propriétaire OVH                           | Scaleway tourne sur stack technique différente |
| Faillite ou rachat OVH                                      | Scaleway reste disponible le temps de migrer   |

### 3.2 Pourquoi pas OVH + Backblaze B2 / Wasabi / AWS S3 ?

| Provider                | Souveraineté                             | Tarif (€/GB/mois) | Décision                                                        |
| ----------------------- | ---------------------------------------- | ----------------- | --------------------------------------------------------------- |
| OVH Object Storage      | FR (Roubaix, Gravelines, Strasbourg)     | 0.0119            | **Retenu** primaire                                             |
| Scaleway Object Storage | FR (Paris, Amsterdam)                    | 0.014             | **Retenu** secondaire                                           |
| Backblaze B2            | US (siège), EU Amsterdam disponible      | 0.005             | Rejeté (juridiction US, Cloud Act risk pour clients régulés FR) |
| Wasabi                  | US (siège), EU Paris/Amsterdam/Frankfurt | 0.0068            | Rejeté (idem juridiction)                                       |
| AWS S3                  | US (siège), EU disponible                | 0.0245            | Rejeté (juridiction + tarif)                                    |

**Critère décisif** : posture souverain FR cohérente avec ICP PME France
régulée + narratif ANSSI. Les 0.005-0.007 €/GB économisés sur B2/Wasabi ne
compensent pas le risque commercial "votre prestataire stocke chez les
américains".

**Note importante** : avec chiffrement client-side (restic + pgbackrest
cipher), le contenu est ciphertext même côté provider. Le critère juridique
reste néanmoins valide pour la posture commerciale et la conformité
contractuelle (DPA RGPD).

## 4. Stratégie par actif

### 4.1 PostgreSQL (asset critique, RPO 5min)

**Outil** : pgbackrest avec WAL streaming continu.

| Type de backup        | Schedule                   | Rétention                   | Repos                          |
| --------------------- | -------------------------- | --------------------------- | ------------------------------ |
| Full backup           | Dimanche 02:00 UTC         | 4 semaines (4 fulls)        | OVH (repo1) + Scaleway (repo2) |
| Differential backup   | Lundi-Samedi 03:00 UTC     | 7 jours (rotated avec full) | OVH + Scaleway                 |
| WAL archive (continu) | `archive_command` postgres | 12 archives = \~3 mois      | OVH + Scaleway                 |

**Configuration** : `platform/docker/postgres/pgbackrest.conf`

**Chiffrement** : `repo-cipher-type=aes-256-cbc` avec passphrase depuis
Vault `mssp/data/dr/pgbackrest_cipher_pass`.

**Restore** : cf. [runbooks/01-restore-postgres-pitr.md](./runbooks/01-restore-postgres-pitr.md).

### 4.2 Vault (asset critique, RPO 24h)

**Outil** : `vault operator raft snapshot save` puis push restic chiffré.

| Type de backup | Schedule            | Rétention             | Repos          |
| -------------- | ------------------- | --------------------- | -------------- |
| Snapshot raft  | Quotidien 04:00 UTC | 30 derniers snapshots | OVH + Scaleway |

**Pourquoi RPO 24h acceptable** : Vault contient des secrets stables
(credentials, certs). Les écritures sont rares (rotation annuelle, ajout
nouveau client) et tracées dans `PlatformAuditLog`. Une perte de 24h sur
Vault est récupérable manuellement (re-saisir les secrets clients via UI).

**Chiffrement** : restic chiffre nativement (AES-256-CBC + Poly1305-AES).
Passphrase depuis Vault `mssp/data/dr/restic_password`.

**Note circulaire** : la passphrase restic est stockée dans Vault, qu'on
backup avec restic. Pour briser la dépendance circulaire, la passphrase
restic est **aussi** stockée :

* Dans KeePassXC du DR Owner (S2 share Shamir lui-même protégé)
* Sur papier dans le coffre domicile (séparé des shares Shamir)
* Dans l'enveloppe scellée du notaire (avec les shares S4-S5)

**Restore** : cf. [runbooks/02-restore-vault-from-snapshot.md](./runbooks/02-restore-vault-from-snapshot.md).

### 4.3 Artifacts (asset important, RPO 24h)

**Outil** : restic avec dedupe activé.

| Type de backup       | Schedule            | Rétention          | Repos          |
| -------------------- | ------------------- | ------------------ | -------------- |
| Snapshot incrémental | Quotidien 05:00 UTC | 90 jours glissants | OVH + Scaleway |

**Contenu sauvegardé** :

* `artifacts/audit/` : audits JSON schema 3.0 par client/run
* `artifacts/grc/` : 8 GRC docs DOCX+PDF par client
* `artifacts/exports/` : CSV access-review (régénérables, mais simple à inclure)
* `artifacts/certified/` : PDF certifiés Ed25519 (Phase 2)

**Chiffrement** : restic native (idem Vault).

**Restore** : cf. [runbooks/04-restore-artifacts.md](./runbooks/04-restore-artifacts.md).

### 4.4 DNS zone (asset critique, RPO 30j)

**Outil** : export YAML de la zone DNS OVH via API.

| Type de backup   | Schedule                         | Rétention                   | Stockage                     |
| ---------------- | -------------------------------- | --------------------------- | ---------------------------- |
| Export zone YAML | Mensuel le 1er du mois 06:00 UTC | 12 mois (1 an d'historique) | Inclus dans backup artifacts |

**Pourquoi RPO 30j acceptable** : la zone DNS change rarement (ajout d'un
sous-domaine pour nouveau client tenant, mise à jour SPF/DKIM/DMARC). Une
perte de 30j est récupérable manuellement (re-saisir les records via OVH UI).

### 4.5 Code source

**Outil** : git remote.

**Stratégie** : repos hébergés sur GitLab.com (responsabilité GitLab pour
backup), backup local complet quotidien automatique sur poste de travail
Nicolas (`git fetch --all` + push miroir vers un repo de secours sur Codeberg
ou self-hosted).

**Pas dans le périmètre DR plateforme** : le code source n'est pas un actif
"runtime", c'est un actif de développement. Sa perte n'impacte pas la prod
en cours (image Docker déjà sur registry).

## 5. Schedule global de backups

| Heure UTC           | Tâche                        | Asset                         |
| ------------------- | ---------------------------- | ----------------------------- |
| Continu             | `archive_command` PostgreSQL | WAL Postgres                  |
| 02:00 (Dim)         | pgbackrest full              | PostgreSQL                    |
| 03:00 (Lun-Sam)     | pgbackrest diff              | PostgreSQL                    |
| 04:00 (quotidien)   | vault-snapshot.sh            | Vault                         |
| 05:00 (quotidien)   | artifacts-restic.sh          | Artifacts                     |
| 06:00 (1er du mois) | dns-zone-export.sh           | DNS zone                      |
| 06:30 (quotidien)   | dr-verify.sh                 | Smoke check intégrité backups |

**Orchestration** : container `ofelia` (cron Docker-native) défini dans
`platform/compose/cron.yml`.

**Alertes Sentry** : chaque script logue son résultat (succès/échec/durée)
dans Sentry avec tag `dr.backup.<asset>`. Échec → alerte breadcrumb +
notification email DR Owner.

## 6. Vérification d'intégrité

### 6.1 Smoke check quotidien automatique

Script `scripts/dr/dr-verify.sh` exécuté à 06:30 UTC :

1. Liste les derniers snapshots disponibles sur les 2 repos (OVH + Scaleway)
2. Vérifie que la date du dernier snapshot est \< 26h (sinon backup raté)
3. Pour pgbackrest : `pgbackrest --stanza=mssp check`
4. Pour restic : `restic check --read-data-subset=10%` (10% aléatoire)
5. Si KO → alerte Sentry critique + email immédiat DR Owner

### 6.2 Test de restauration mensuel

Premier samedi du mois, exécuter le runbook critique de la rotation
trimestrielle (cf. [test-schedule.md](./test-schedule.md)) :

* **Q1** (janvier) : restore PostgreSQL PITR sur env de test
* **Q2** (avril) : restore Vault snapshot sur env de test
* **Q3** (juillet) : rotation Shamir + récup enveloppe trustee
* **Q4** (octobre) : exercice incident complet simulé

Procès-verbal consigné dans `docs/dr/test-results/<YYYY-QN>-test.md`.

### 6.3 Job CI nightly

Pipeline GitLab CI `.gitlab-ci.yml` job `dr:verify` :

```yaml theme={null}
dr:verify:
  stage: verify
  schedule: "0 7 * * *"  # 07:00 UTC quotidien
  script:
    - ./scripts/dr/ci-verify-backups.sh
  artifacts:
    reports:
      dotenv: dr-verify-report.env
```

Ce job :

* Pull les credentials S3 depuis Vault via OIDC GitLab
* Liste snapshots OVH + Scaleway
* Vérifie cohérence (même nombre de snapshots récents)
* Pousse métriques vers Sentry custom check

## 7. Procédure de rotation des passphrases

Annuelle, lors du Q3 de chaque année (synchronisé avec rotation Shamir) :

| Passphrase                  | Action                                                                                                         |
| --------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `pgbackrest_cipher_pass`    | Générer nouvelle, ré-encrypt repo (downtime \~1h), update Vault                                                |
| `restic_password`           | `restic key add` puis `restic key remove` ancienne, update Vault + KeePass + papier coffre + enveloppe trustee |
| OVH/Scaleway S3 access keys | Régénérer côté provider, update Vault, supprimer anciennes après confirmation push réussi                      |

## 8. Plan de migration vers Phase 2

Si la posture commerciale évolue (1er client OIV ou demande SecNumCloud
explicite), évolutions à envisager :

| Évolution                           | Justification           | Coût indicatif                      |
| ----------------------------------- | ----------------------- | ----------------------------------- |
| Réplica chaud Postgres sur 2e VPS   | RPO \<1s, RTO \<30min   | +20-40 €/mois VPS                   |
| pgbackrest avec repo3 (3e provider) | Triple redondance       | +1-2 €/mois                         |
| Backup offline air-gapped           | Anti-ransomware extrême | Disque externe + procédure manuelle |
| Audit externe annuel des backups    | Tier 3 maturité         | \~3-5k€/an                          |

## 9. Validation

| Version | Date       | Auteur             | Approbateur        |
| ------- | ---------- | ------------------ | ------------------ |
| 1.0     | 2026-04-26 | Nicolas Schiffgens | Nicolas Schiffgens |
