xpeditis2.0/docs/mise-en-prod/14-runbook-go-live.md
David b22f4e0b74 docs: procedure de mise en production pas a pas
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018BAUeCFpDkRD6tU5wGsc1C
2026-09-07 21:40:50 +02:00

257 lines
8.0 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.

# 14 — Runbook de mise en ligne
Le déroulé du dernier jour et de l'ouverture. **Imprimez-le ou gardez-le ouvert
à côté de vous** — ce n'est pas le moment de chercher une commande dans un
autre fichier.
---
## Choisir le moment
| Bon moment | Mauvais moment |
|---|---|
| **Mardi ou mercredi matin**, 9 h–10 h | Vendredi, quel que soit l'argument |
| Vous êtes disponible les 48 h suivantes | La veille de vos congés |
| Aucune migration lourde en attente | Pendant une maintenance Hetzner annoncée |
Mardi matin laisse trois jours ouvrés pour découvrir et corriger ce qui n'a pas
été anticipé.
---
## J-1 : répétition générale
### 1. Contrôle complet (30 min)
```bash
export KUBECONFIG=~/.kube/xpeditis-prod.yaml
cd infra/prod
DB_PUBLIC_IP=<ip_db> make preflight
```
**Aucun point bloquant ne doit subsister.** Consignez les avertissements dans un
registre des risques daté, avec pour chacun une décision explicite : accepté,
ou corrigé avant l'ouverture.
### 2. Parcours fonctionnels de bout en bout (1 h)
À faire **dans un navigateur, comme un vrai client**, pas en `curl`.
```
[ ] Inscription d'un nouveau compte
[ ] Réception de l'e-mail de validation (vérifier : boîte principale, pas spam)
[ ] Validation, puis connexion
[ ] Recherche de tarifs → au moins un résultat s'affiche
[ ] Création d'une réservation
[ ] Réception de l'e-mail de confirmation
[ ] Génération et téléchargement d'un PDF
[ ] Lien magique transporteur : réception, ouverture, acceptation
[ ] Souscription à un abonnement en mode Live (petit montant, puis remboursement)
[ ] Réception du webhook Stripe (Dashboard Stripe → Webhooks → Tentatives)
[ ] Notification temps réel visible dans l'interface
[ ] Déconnexion, mot de passe oublié, réinitialisation
[ ] Espace d'administration accessible avec votre compte ADMIN
[ ] Import d'une grille tarifaire CSV
[ ] Navigation sur mobile
```
> **Le test Stripe en mode Live est indispensable.** Les clés de test et de
> production ont des comportements différents, et le secret de webhook n'est pas
> le même. Une souscription à 1 €, immédiatement remboursée, vaut mieux que la
> découverte du problème par le premier client.
> **La notification temps réel** peut ne pas arriver : c'est attendu avec deux
> replicas. Voir [15 § Points de vigilance](./15-exploitation-incidents.md#points-de-vigilance-connus).
### 3. Répétition du retour arrière (20 min)
Exercez-vous pendant que l'enjeu est nul.
```bash
# Déployer sciemment une version antérieure
kubectl -n xpeditis-prod set image deploy/xpeditis-backend \
backend=rg.fr-par.scw.cloud/weworkstudio/xpeditis-backend:prod-<sha_precedent>
kubectl -n xpeditis-prod rollout status deploy/xpeditis-backend
# Puis revenir
make rollback
bash scripts/smoke-test.sh
```
**Chronométrez.** C'est votre temps de retour réel.
### 4. Sauvegarde manuelle (10 min)
```bash
ssh deploy@<db_ip> 'sudo systemctl start xpeditis-backup.service'
ssh deploy@<db_ip> 'sudo journalctl -u xpeditis-backup -n 30 --no-pager'
```
Notez l'horodatage : c'est votre point de retour du jour J.
### 5. Décision go / no-go
| Critère | Bloquant ? |
|---|---|
| `preflight-check.sh` sans point bloquant | **oui** |
| Test PITR réussi ([12](./12-sauvegardes-restauration.md)) | **oui** |
| Clé SMTP Brevo compromise révoquée | **oui** |
| Comptes de démonstration neutralisés (401) | **oui** |
| Un seul ADMIN actif | **oui** |
| Parcours d'inscription et de réservation fonctionnels | **oui** |
| Paiement Stripe testé en Live | **oui** |
| Alerte de test reçue sur Discord | **oui** |
| Supervision externe active | **oui** |
| Retour arrière répété | **oui** |
| SSL Labs ≥ A | non — corriger sous 7 j |
| Notifications temps réel fiables | non — dégradation connue |
| Sentry connecté | non |
**Un seul « oui » en échec = report.** Reporter d'une semaine coûte infiniment
moins cher que d'ouvrir avec un administrateur au mot de passe public.
---
## J0 : ouverture
### T-30 min
```bash
export KUBECONFIG=~/.kube/xpeditis-prod.yaml
cd infra/prod
make status # tous les pods Running, certificats Ready
make smoke # tout au vert
# Sauvegarde de dernière minute
ssh deploy@<db_ip> 'sudo systemctl start xpeditis-backup.service'
```
Ouvrez et gardez sous les yeux :
- Grafana : `https://grafana.xpeditis.com`
- Le canal Discord `#alertes`
- Le tableau de bord Stripe
- Un terminal avec `make -C infra/prod logs`
### T-0 : rendre public
Si vous aviez restreint l'accès pendant la préparation (règle Cloudflare,
liste d'IP), retirez-la maintenant.
```bash
# Vérification finale, depuis un réseau extérieur (partage de connexion mobile)
curl -sI https://xpeditis.com/ | head -1
curl -sI https://app.xpeditis.com/ | head -1
curl -s https://api.xpeditis.com/api/v1/health | jq
```
Publiez : site vitrine, réseaux sociaux, e-mail aux premiers clients.
### T+15 min
```bash
make smoke
kubectl -n xpeditis-prod get pods
kubectl -n xpeditis-prod top pods 2>/dev/null || true
```
Dans Grafana :
- taux d'erreur 5xx — doit rester à 0 ;
- latence P95 — sous 1 s ;
- mémoire des pods — stable, pas de croissance continue.
### T+1 h, T+4 h, puis fin de journée
Les mêmes contrôles. Ce que vous cherchez :
| Signal | Interprétation |
|---|---|
| Mémoire du backend en croissance continue | Fuite mémoire → surveiller, redémarrer si besoin |
| Erreurs 401 en rafale | Problème de cookie (`COOKIE_DOMAIN`) ou de CORS |
| Requêtes PostgreSQL lentes | Index manquant sur une table qui grossit |
| Connexions PostgreSQL en hausse | Pool non libéré |
| Espace disque en baisse rapide | Journaux ou WAL — vérifier que l'archivage fonctionne |
---
## Si ça tourne mal
### Le site est cassé pour tout le monde
```bash
make -C infra/prod rollback
make -C infra/prod smoke
```
Si le retour arrière ne suffit pas : voir
[15 § Le site est hors ligne](./15-exploitation-incidents.md#le-site-est-hors-ligne).
### Il faut refermer temporairement
Cloudflare → Security → Settings → **Under Attack Mode**.
Les visiteurs passent par une page d'interstitiel ; vos IP restent autorisées.
C'est réversible en un clic, contrairement à une modification de firewall.
### Perte ou corruption de données
Ne rien faire d'autre, et suivre
[12 § Restauration](./12-sauvegardes-restauration.md#5-restauration).
Chaque écriture supplémentaire complique la remise en état.
---
## J+1 à J+7
### Chaque jour
```bash
make -C infra/prod status
```
```
[ ] Aucune alerte non traitée sur Discord
[ ] Sauvegarde de la nuit réussie (battement de cœur vert)
[ ] Taux d'erreur stable
[ ] Aucun pod redémarré sans raison
[ ] Aucun paiement en échec inexpliqué côté Stripe
```
### J+7 : bilan
```
[ ] Vérification hebdomadaire de restauration passée (dimanche 04h00)
[ ] Consommation réelle vs dimensionnement — le CPX41 est-il bien calibré ?
[ ] Coût réel vs prévision (Xpeditis_Previsions_Couts.xlsx)
[ ] Registre des risques relu : les avertissements acceptés sont-ils traités ?
[ ] Retours utilisateurs : quelque chose casse-t-il de façon récurrente ?
[ ] HSTS : passer de 1 mois à 12 mois + preload si tout est stable
```
---
## Contacts et accès en urgence
À remplir et à garder **hors du dépôt** (gestionnaire de mots de passe, ou
papier dans un tiroir) :
```
Hetzner Cloud console.hetzner.cloud compte : ____________
Hetzner Robot robot.hetzner.com (Storage Box)
Cloudflare dash.cloudflare.com compte : ____________
Registrar ____________
Scaleway console.scaleway.com
Stripe dashboard.stripe.com
Brevo app.brevo.com
GitHub github.com/____________
SSH admin ssh -i ~/.ssh/xpeditis_prod deploy@<app_ip>
SSH base ssh -i ~/.ssh/xpeditis_prod deploy@<db_ip>
Kubeconfig ~/.kube/xpeditis-prod.yaml
Clé age ~/.config/sops/age/keys.txt (+ copie hors ligne : ________)
Clé de secours emplacement physique : ____________
```
---
→ **Suite : [15 — Exploitation et incidents](./15-exploitation-incidents.md)**