# 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= 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- 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@ 'sudo systemctl start xpeditis-backup.service' ssh deploy@ '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@ '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@ SSH base ssh -i ~/.ssh/xpeditis_prod deploy@ 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)**