Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018BAUeCFpDkRD6tU5wGsc1C
257 lines
8.0 KiB
Markdown
257 lines
8.0 KiB
Markdown
# 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)**
|