Aller au contenu principal

Plan de Disaster Recovery - Aaperture

Ce document décrit les procédures de sauvegarde et de récupération en cas de sinistre pour l'application Aaperture.

📋 Table des matières

  1. Vue d'ensemble
  2. Stratégie de sauvegarde
  3. Procédures de restauration
  4. Plan de récupération
  5. Tests de restauration
  6. Monitoring et alertes

Vue d'ensemble

Objectifs de récupération

  • RTO (Recovery Time Objective) : 4 heures maximum
  • RPO (Recovery Point Objective) : 24 heures maximum (perte de données acceptée)

Composants critiques

  1. Base de données PostgreSQL : Données utilisateurs, sessions, contacts, devis, factures
  2. Fichiers stockés (Cloudflare R2) : Images, documents, fichiers uploadés
  3. Configuration : Variables d'environnement, secrets
  4. Code applicatif : Code source versionné dans GitLab

Stratégie de sauvegarde

Sauvegardes de base de données

Sauvegardes automatiques

  • Fréquence : Quotidienne à 2h du matin (heure UTC)
  • Type : Sauvegardes complètes avec compression gzip
  • Rétention : 30 jours par défaut (configurable via RETENTION_DAYS)
  • Emplacement : Répertoire local (_backups/ ou BACKUP_DIR)
  • Format : postgres-YYYY-MM-DDTHH-MM-SS.sql.gz

Caractéristiques des sauvegardes

  • ✅ Compression gzip pour réduire l'espace disque
  • ✅ Checksum SHA-256 pour vérification d'intégrité
  • ✅ Logging dans la base de données (backup_logs)
  • ✅ Nettoyage automatique des anciennes sauvegardes
  • ✅ Notifications email en cas de succès/échec

Configuration

Variables d'environnement :

# Répertoire de sauvegarde (par défaut: _backups/)
BACKUP_DIR=/var/backups/aaperture

# Rétention en jours (par défaut: 30)
RETENTION_DAYS=30

# Timeout pour backups en secondes (par défaut: 1800 = 30 minutes)
BACKUP_TIMEOUT=1800

# Email pour notifications (optionnel)
BACKUP_NOTIFICATION_EMAIL=admin@example.com

Note: Le script backup-db.sh applique automatiquement un timeout configurable via BACKUP_TIMEOUT. Si le backup dépasse ce délai, il sera interrompu avec une erreur. Voir TIMEOUT_MANAGEMENT.md pour plus d'informations sur la gestion des timeouts.

Sauvegardes de fichiers (Cloudflare R2)

Les fichiers sont stockés sur Cloudflare R2 qui offre :

  • ✅ Durabilité élevée (99.999999999% - 11 nines)
  • ✅ Réplication automatique
  • ✅ Versioning optionnel
  • ✅ Lifecycle policies pour archivage automatique

Recommandation : Activer le versioning R2 pour les fichiers critiques.

Sauvegardes de configuration

  • ✅ Code source versionné dans GitLab (avec historique complet)
  • ✅ Variables d'environnement documentées dans .env.example
  • ✅ Secrets stockés de manière sécurisée (non versionnés)

Action requise : Créer un dépôt sécurisé pour les secrets de production (ex: HashiCorp Vault, AWS Secrets Manager).

Procédures de restauration

Restauration de la base de données

Prérequis

  1. Accès au serveur de production ou environnement de staging
  2. Fichier de sauvegarde disponible
  3. Accès à la base de données PostgreSQL
  4. Outils nécessaires : psql, gunzip

Étape 1 : Vérifier l'intégrité de la sauvegarde

# Vérifier que le fichier existe et n'est pas vide
ls -lh /path/to/backup/postgres-2024-01-01T02-00-00.sql.gz

# Vérifier le checksum (si disponible dans backup_logs)
sha256sum /path/to/backup/postgres-2024-01-01T02-00-00.sql.gz

Étape 2 : Préparer la base de données

# Se connecter à PostgreSQL
psql -h localhost -U postgres -d postgres

# Créer une nouvelle base de données (si restauration complète)
CREATE DATABASE aaperture_restored;

# OU vider la base existante (ATTENTION : supprime toutes les données)
DROP DATABASE IF EXISTS aaperture;
CREATE DATABASE aaperture;

Étape 3 : Restaurer la sauvegarde

# Option 1 : Décompression et restauration en une commande
gunzip -c /path/to/backup/postgres-2024-01-01T02-00-00.sql.gz | \
psql -h localhost -U postgres -d aaperture

# Option 2 : Décompression puis restauration
gunzip /path/to/backup/postgres-2024-01-01T02-00-00.sql.gz
psql -h localhost -U postgres -d aaperture < postgres-2024-01-01T02-00-00.sql

Étape 4 : Vérifier la restauration

# Vérifier le nombre d'enregistrements dans les tables principales
psql -h localhost -U postgres -d aaperture -c "SELECT COUNT(*) FROM users;"
psql -h localhost -U postgres -d aaperture -c "SELECT COUNT(*) FROM sessions;"
psql -h localhost -U postgres -d aaperture -c "SELECT COUNT(*) FROM contacts;"

# Vérifier la date de dernière sauvegarde
psql -h localhost -U postgres -d aaperture -c \
"SELECT MAX(created_at) FROM backup_logs WHERE status = 'completed';"

Étape 5 : Mettre à jour les migrations (si nécessaire)

# Exécuter les migrations Liquibase pour s'assurer que le schéma est à jour
cd infra
./migrate-improved.sh

Restauration de fichiers (Cloudflare R2)

Les fichiers sur R2 sont automatiquement répliqués. En cas de perte locale :

  1. Les fichiers sont toujours disponibles sur R2
  2. Vérifier l'accès via l'interface Cloudflare ou l'API
  3. Si nécessaire, re-synchroniser depuis R2

Restauration complète de l'application

Scénario : Perte complète du serveur

  1. Provisionner un nouveau serveur

    • Installer Docker et Docker Compose
    • Cloner le dépôt GitLab
    • Configurer les variables d'environnement
  2. Restauration de la base de données

    • Suivre les procédures ci-dessus
    • Restaurer la dernière sauvegarde disponible
  3. Configuration de l'application

    • Copier les fichiers .env depuis le dépôt sécurisé
    • Configurer les connexions (DB, Redis, R2)
    • Vérifier les certificats SSL/TLS
  4. Démarrage de l'application

    cd infra
    docker compose -f docker-compose.prod.yml up -d
  5. Vérification

    • Tester l'accès à l'application
    • Vérifier les fonctionnalités critiques
    • Vérifier les intégrations externes (Google Calendar, Stripe, etc.)

Plan de récupération

Scénarios de sinistre

1. Corruption de la base de données

Symptômes :

  • Erreurs PostgreSQL lors des requêtes
  • Données manquantes ou incohérentes
  • Application inaccessible

Actions :

  1. Arrêter l'application immédiatement
  2. Identifier la dernière sauvegarde valide
  3. Restaurer la sauvegarde (voir procédures ci-dessus)
  4. Vérifier l'intégrité des données
  5. Redémarrer l'application
  6. Notifier les utilisateurs si nécessaire

Temps estimé : 1-2 heures

2. Perte de fichiers

Symptômes :

  • Images/documents manquants dans l'application
  • Erreurs 404 pour les fichiers

Actions :

  1. Vérifier l'état de Cloudflare R2
  2. Si R2 est intact : re-synchroniser les fichiers
  3. Si R2 est compromis : restaurer depuis backup R2 (si versioning activé)
  4. Vérifier l'accès aux fichiers restaurés

Temps estimé : 30 minutes - 2 heures

3. Panne du serveur

Symptômes :

  • Application inaccessible
  • Pas de réponse du serveur
  • Timeouts

Actions :

  1. Diagnostiquer la cause (hardware, réseau, etc.)
  2. Si récupération impossible rapidement : provisionner nouveau serveur
  3. Restaurer la base de données
  4. Reconfigurer l'application
  5. Redémarrer les services
  6. Mettre à jour le DNS si nécessaire

Temps estimé : 2-4 heures

4. Attaque de sécurité

Symptômes :

  • Activité suspecte dans les logs
  • Données modifiées sans autorisation
  • Accès non autorisé

Actions :

  1. Isoler immédiatement : Arrêter l'application, bloquer l'accès réseau
  2. Analyser l'étendue de la compromission
  3. Notifier les autorités compétentes si nécessaire
  4. Restaurer depuis une sauvegarde antérieure à l'attaque
  5. Appliquer les correctifs de sécurité
  6. Réinitialiser tous les mots de passe et tokens
  7. Auditer les logs pour identifier la source
  8. Redémarrer l'application avec monitoring renforcé

Temps estimé : 4-8 heures

Contacts d'urgence

  • Administrateur système : [À compléter]
  • Développeur principal : [À compléter]
  • Support Cloudflare : [À compléter]
  • Support hébergeur : [À compléter]

Tests de restauration

Tests réguliers recommandés

  • Mensuel : Test de restauration sur environnement de staging
  • Trimestriel : Test de restauration complète (DR drill)
  • Après chaque changement majeur : Vérifier que les sauvegardes fonctionnent

Procédure de test

  1. Préparer l'environnement de test

    # Créer une base de données de test
    createdb aaperture_test
  2. Restaurer une sauvegarde récente

    gunzip -c /path/to/backup/postgres-YYYY-MM-DDTHH-MM-SS.sql.gz | \
    psql -h localhost -U postgres -d aaperture_test
  3. Vérifier l'intégrité

    • Compter les enregistrements dans les tables principales
    • Vérifier les relations (clés étrangères)
    • Tester quelques requêtes critiques
  4. Documenter les résultats

    • Date du test
    • Sauvegarde testée
    • Résultats (succès/échec)
    • Problèmes identifiés
    • Actions correctives

Checklist de test

  • Sauvegarde restaurée avec succès
  • Toutes les tables présentes
  • Données cohérentes (pas de corruption)
  • Relations entre tables intactes
  • Migrations appliquées correctement
  • Application fonctionnelle après restauration
  • Performance acceptable

Monitoring et alertes

Monitoring des sauvegardes

Timeout des backups : Les backups sont automatiquement interrompus si ils dépassent le délai configuré via BACKUP_TIMEOUT (défaut: 30 minutes). Surveillez les logs pour détecter les timeouts fréquents qui pourraient indiquer un problème de performance ou de taille de base de données.

Monitoring des sauvegardes

Le système de backup envoie automatiquement :

  • Email de succès : Après chaque backup réussi (si BACKUP_NOTIFICATION_EMAIL configuré)
  • Email d'alerte : En cas d'échec de backup
  • Logs dans la base : Tous les backups sont enregistrés dans backup_logs

Métriques à surveiller

  1. Fréquence des sauvegardes

    • Vérifier qu'une sauvegarde est créée quotidiennement
    • Alert si aucune sauvegarde depuis 25 heures
  2. Taux de succès

    • Surveiller le statut des backups (completed vs failed)
    • Alert si taux d'échec > 10%
  3. Taille des sauvegardes

    • Surveiller la taille des fichiers de backup
    • Alert si taille anormalement petite (possible corruption)
    • Alert si taille anormalement grande (possible problème)
  4. Durée des backups

    • Surveiller duration_ms dans backup_logs
    • Alert si durée > 1 heure (possible problème de performance)
  5. Espace disque

    • Surveiller l'espace disponible dans BACKUP_DIR
    • Alert si espace < 20%

Requêtes SQL utiles

-- Dernière sauvegarde réussie
SELECT * FROM backup_logs
WHERE status = 'completed'
ORDER BY created_at DESC
LIMIT 1;

-- Sauvegardes échouées récentes
SELECT * FROM backup_logs
WHERE status = 'failed'
AND created_at > NOW() - INTERVAL '7 days'
ORDER BY created_at DESC;

-- Statistiques des backups
SELECT
status,
COUNT(*) as count,
AVG(duration_ms) as avg_duration_ms,
MAX(created_at) as last_backup
FROM backup_logs
GROUP BY status;

-- Taille moyenne des backups
SELECT
AVG(
CASE
WHEN backup_size LIKE '%G' THEN CAST(REPLACE(backup_size, 'G', '') AS FLOAT) * 1024 * 1024 * 1024
WHEN backup_size LIKE '%M' THEN CAST(REPLACE(backup_size, 'M', '') AS FLOAT) * 1024 * 1024
WHEN backup_size LIKE '%K' THEN CAST(REPLACE(backup_size, 'K', '') AS FLOAT) * 1024
ELSE CAST(REPLACE(backup_size, 'B', '') AS FLOAT)
END
) as avg_size_bytes
FROM backup_logs
WHERE status = 'completed' AND backup_size IS NOT NULL;

Améliorations futures

Sauvegardes incrémentielles

  • Implémenter WAL archiving pour point-in-time recovery
  • Réduire la fenêtre de perte de données (RPO < 1 heure)

Sauvegardes distantes

  • Automatiser la copie des backups vers un emplacement distant (S3, autre serveur)
  • Implémenter la rétention multi-niveaux (quotidien, hebdomadaire, mensuel)

Tests automatisés

  • Automatiser les tests de restauration dans CI/CD
  • Alertes automatiques si test de restauration échoue

Documentation

  • Créer des runbooks détaillés pour chaque scénario
  • Documenter les procédures de restauration spécifiques par composant

Révision

Ce document doit être révisé :

  • Mensuellement : Vérifier que les procédures sont toujours à jour
  • Après chaque incident : Mettre à jour avec les leçons apprises
  • Après chaque changement majeur : Adapter les procédures si nécessaire

Dernière révision : [Date] Prochaine révision prévue : [Date + 1 mois]