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

# 04 restore artifacts

# Runbook 04 — Restauration artifacts (audits JSON, GRC docs, exports)

## 1. Quand activer ce runbook

| Scénario                                                                     | Activer ?                                                             |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| Volume `archive-data` ou `reports-data` corrompu                             | **OUI**                                                               |
| Suppression accidentelle d'un dossier `artifacts/grc/<client>/`              | **OUI** ciblé sur ce client                                           |
| Reconstruction VPS depuis zéro                                               | **OUI** (étape §5.7 du runbook 03)                                    |
| Migration vers une autre infra                                               | OUI mode contrôlé                                                     |
| Un seul client demande restauration d'un rapport effacé par erreur côté MSSP | **OUI** restauration partielle (snapshot specifique + path inclusion) |

## 2. Objectifs

* **RPO atteint** : 24 heures (snapshots restic quotidiens 05:00 UTC)
* **RTO cible** : 4 heures pour restauration totale, 30 min pour restauration partielle
* **WRT cible** : 30 minutes (vérification exhaustive des fichiers critiques)

## 3. Prérequis

* Accès SSH au VPS production
* Vault opérationnel et unsealed
* DR AppRole creds présentes
* **Restic password** (KeePass + papier coffre)
* Au moins un des deux repos S3 accessible (OVH ou Scaleway)
* Volumes Docker `reports-data` et `archive-data` créés

## 4. Stratégies selon le scénario

### 4.1 Restauration totale

Restorer tout `artifacts/` au dernier snapshot disponible.

### 4.2 Restauration partielle (un client / une période)

Restorer uniquement les chemins concernés. Plus rapide, moins risqué.

### 4.3 Restauration point-in-time (à un snapshot précis)

Choisir un snapshot ID spécifique plutôt que `latest` (utile si la corruption
date d'avant le dernier snapshot).

## 5. Procédure de restauration totale

### 5.1 Identifier le snapshot cible

```bash theme={null}
make dr-shell

# Liste des snapshots OVH (primaire)
AWS_ACCESS_KEY_ID="$(vault kv get -field=ovh_s3_access_key mssp/dr)" \
AWS_SECRET_ACCESS_KEY="$(vault kv get -field=ovh_s3_secret_key mssp/dr)" \
RESTIC_REPOSITORY="s3:s3.gra.io.cloud.ovh.net/mssp-backup-ovh/artifacts" \
RESTIC_PASSWORD="$(vault kv get -field=restic_password mssp/dr)" \
restic snapshots --tag artifacts
```

Identifier le snapshot ID (8 caractères hex) à restaurer. Par défaut, le
script `artifacts-restore.sh` prend le `latest`.

### 5.2 Stop application + worker (artifacts en lecture par next-app)

```bash theme={null}
cd /opt/mssp/app/platform
make app-down
docker compose -f compose/_common.yml -f compose/app.prod.yml stop \
  worker-chain worker-digest worker-retention worker-scheduler \
  worker-import worker-deadline worker-regression worker-permission-expiry
```

### 5.3 Sauvegarde de l'état actuel (si corruption partielle)

```bash theme={null}
ssh mssp@vps.snakysec.com
sudo tar czf /opt/mssp/snapshots/artifacts-pre-restore-$(date +%Y%m%dT%H%M%SZ).tar.gz \
  -C /var/lib/docker/volumes/platform_archive-data/_data . \
  -C /var/lib/docker/volumes/platform_reports-data/_data .
```

### 5.4 Vider les volumes (si restauration totale)

```bash theme={null}
docker run --rm \
  -v platform_archive-data:/archive \
  -v platform_reports-data:/reports \
  alpine sh -c "rm -rf /archive/* /archive/.[!.]* /reports/* /reports/.[!.]* 2>/dev/null || true"
```

### 5.5 Lancer le restore via dr-runner

```bash theme={null}
make dr-shell
/dr/restore/artifacts-restore.sh
```

Le script `artifacts-restore.sh` (cf. §5.6 du script) :

1. Lit credentials depuis Vault DR
2. Restorer depuis OVH par défaut (fallback Scaleway via `--repo=scaleway`)
3. Restore vers `/artifacts` (mounté sur les volumes archive-data + reports-data)
4. Verify intégrité après restore

Durée typique : 30 min - 1h selon volume (\~50 GB).

### 5.6 Validation post-restore

```bash theme={null}
# Compter les fichiers restaurés
docker exec mssp-dr-runner find /artifacts -type f | wc -l

# Vérifier qu'on a au moins un sample par catégorie
docker exec mssp-dr-runner ls /artifacts/audit/ | head
docker exec mssp-dr-runner ls /artifacts/grc/ | head
docker exec mssp-dr-runner ls /artifacts/dns-zones/ | head
```

### 5.7 Redémarrage application

```bash theme={null}
exit  # sortir du dr-runner
make app-up
docker compose -f compose/_common.yml -f compose/app.prod.yml up -d \
  worker-chain worker-digest worker-retention worker-scheduler \
  worker-import worker-deadline worker-regression worker-permission-expiry
sleep 30
curl -sI https://snakysec.com/api/health
```

## 6. Procédure de restauration partielle

### 6.1 Cas client X demande son rapport GRC supprimé par erreur

```bash theme={null}
make dr-shell

# Inclure UNIQUEMENT le path du client concerné
/dr/restore/artifacts-restore.sh \
  --include="/artifacts/grc/<client-slug>/**" \
  --target-dir="/artifacts/restore-tmp"

# Vérifier les fichiers restaurés
ls -la /artifacts/restore-tmp/grc/<client-slug>/

# Si OK, déplacer vers la destination réelle
mv /artifacts/restore-tmp/grc/<client-slug>/ /artifacts/grc/

# Cleanup
rm -rf /artifacts/restore-tmp
```

### 6.2 Cas restauration d'un audit spécifique (mois N)

```bash theme={null}
make dr-shell

# Identifier le snapshot couvrant la période
restic snapshots --tag artifacts --json | jq '.[] | select(.time > "2026-03-01")' | head -3

# Restore le run-id concerné
/dr/restore/artifacts-restore.sh \
  --snapshot=<snapshot-id> \
  --include="/artifacts/audit/<client-slug>/<run-id>/**"
```

## 7. Procédure de restauration point-in-time

```bash theme={null}
make dr-shell

# Liste avec timestamp pour repérer le snapshot avant la corruption
restic snapshots --tag artifacts

# Restore depuis un ID précis
/dr/restore/artifacts-restore.sh --snapshot=a1b2c3d4
```

## 8. Communication client

Pour restauration partielle d'un seul client :

```
Objet : SnakySec — Restauration de votre rapport [titre]

Suite à votre signalement, nous avons restauré le rapport [titre] depuis
notre sauvegarde du [date snapshot].

Le fichier est à nouveau disponible dans votre portail :
https://snakysec.com/clients/[slug]/reports/[id]

Aucune autre donnée n'a été impactée. Si vous identifiez d'autres anomalies,
contactez-nous immédiatement.
```

Pour restauration totale (incident significatif), aligner sur runbook 01 §8.

## 9. Erreurs courantes et solutions

| Erreur                                                             | Cause                                               | Solution                                                                           |
| ------------------------------------------------------------------ | --------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `restic: Fatal: unable to open repository at...`                   | Bucket inaccessible (OVH down ou keys invalides)    | Try `--repo=scaleway`                                                              |
| `restic: ignoring error for /artifacts/...: read-only file system` | Volume monté ro                                     | Verifier compose/dr.yml — `/artifacts` doit être rw pour restore                   |
| Restore OK mais next-app voit fichiers absents                     | Permissions UID mismatch (restic restore sous root) | `chown -R 1000:1000 /artifacts/*` (ajuster UID au runtime app)                     |
| Snapshot vide (0 fichier restauré)                                 | Mauvais tag ou path d'inclusion                     | Lister snapshot content : `restic ls <snapshot-id>`                                |
| `restic: Fatal: snapshot is locked`                                | Backup en cours en parallèle                        | Attendre + retry ou `restic unlock` (si on est sûr qu'aucune écriture concurrente) |

## 10. Validation du runbook

Testé annuellement (Q1, mêmes phase que Postgres PITR car couplé dans
l'exercice). Restauration partielle testée mensuellement via test client
random (samedi 1er du mois).

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