Files
office_translator/DISASTER_RECOVERY.md
sepehr 3f980ad537
Some checks failed
Deploy to Production / Build and Deploy (push) Has been cancelled
feat: add NAS backup, verification, and DR scripts
2026-06-07 11:12:01 +02:00

10 KiB
Raw Blame History

Disaster Recovery — Wordly.art

Guide opérationnel complet


Architecture

         [ Internet ]
              │
              ▼ (80/443)
 ┌────────────────────────────────────┐
 │  NPM dédié : 192.168.1.184        │  ← STABLE (ne tombe pas)
 │  Interface admin : :81            │
 └────────────┬───────────────────────┘
              │  Forward Hostname → IP du serveur actif
              ▼
 ┌────────────────────────────────────┐
 │  Serveur APP : 192.168.1.151      │  ← PEUT CRASHER
 │  Docker: postgres, redis,          │
 │          backend:8001, frontend:3000│
 └────────────┬───────────────────────┘
              │ rsync SSH toutes les 6h (cron)
              ▼
 ┌────────────────────────────────────────────────┐
 │  NAS Synology : 192.168.1.146                  │  ← SOURCE DE VÉRITÉ
 │  Chemin réel  : /volume1/backups/wordly        │
 │  Accès        : SSH key (wordly-backup@nas)    │
 │  Pas de montage CIFS — rsync direct            │
 └────────────┬───────────────────────────────────┘
              │ (en cas de crash de .151)
              ▼
 ┌────────────────────────────────────┐
 │  Serveur SECOURS : 192.168.1.98   │  ← Docker déjà installé
 │  Restaure via rsync SSH depuis NAS│
 │  → NPM redirigé automatiquement   │
 └────────────────────────────────────┘

Pourquoi rsync SSH et pas CIFS/SMB ?

  • Pas de montage à gérer, pas de /etc/fstab à configurer
  • Fonctionne même si le NAS redémarre (pas de montage stale)
  • Chemin exact /volume1/backups/wordly utilisable directement
  • SSH chiffré, clé sans mot de passe pour l'automatisation

RPO / RTO

Scénario Données perdues max Temps de remise en route Procédure
Container crashe 0 ~30s Autorestart Docker
Process PostgreSQL crashe 05s ~1 min Autorestart + WAL
Corruption DB partielle 06h ~5 min Restore depuis NAS
Serveur .151 mort 06h ~25 min Restore NAS sur .98 + NPM auto
Erreur humaine (DROP) 06h ~5 min Restore snapshot précédent

Ce qui est sauvegardé

Composant Sauvegardé Fréquence
PostgreSQL pg_dump Toutes les 6h
.env (secrets, clés API, Stripe...) Dans chaque archive DR
docker-compose.yml Dans chaque archive DR
Dossier docker/ (configs) Dans chaque archive DR
Redis Cache — sessions perdues à la restore (reconnexion users)
Config NPM NPM sur .184 (stable). Seul Forward Host change via API.
Métriques Prometheus Non critique, repart de zéro

1. SETUP INITIAL (une seule fois sur .151)

Étape 1 : Créer le compte sur le NAS Synology

Connectez-vous à l'interface DSM : http://192.168.1.146:5000

1a. Créer l'utilisateur dédié

DSM → Panneau de configuration → Utilisateurs et groupes → Créer
  Nom d'utilisateur : wordly-backup
  Mot de passe      : [choisissez un mot de passe fort]
  ☑ L'utilisateur ne peut pas changer son mot de passe
  → Suivant
  
Permissions sur les dossiers partagés :
  backups → ☑ Lecture/Écriture
  → Suivant → Terminer

1b. Activer SSH sur le NAS

DSM → Panneau de configuration → Terminal et SNMP
  ☑ Activer le service SSH
  Port : 22 (ou autre si vous avez changé)
  → Appliquer

1c. Créer le dossier wordly sur le NAS

# Depuis votre poste (ou n'importe quelle machine sur le réseau) :
ssh admin@192.168.1.146
mkdir -p /volume1/backups/wordly/snapshots
mkdir -p /volume1/backups/wordly/scripts
chown -R wordly-backup:users /volume1/backups/wordly
exit

Étape 2 : Configurer les variables dans .env sur .151

# ── NAS SSH ───────────────────────────────────
NAS_HOST=192.168.1.146
NAS_USER=wordly-backup
NAS_PATH=/volume1/backups/wordly
NAS_SSH_PORT=22
NAS_SSH_KEY=/root/.ssh/wordly_nas_key

# ── Alertes Telegram ──────────────────────────
TELEGRAM_BOT_TOKEN=       # Voir section "Créer un bot Telegram" ci-dessous
TELEGRAM_CHAT_ID=         # Votre chat ID personnel

# ── NPM Failover API ──────────────────────────
NPM_API_URL=http://192.168.1.184:81/api
NPM_ADMIN_EMAIL=admin@wordly.art
NPM_ADMIN_PASSWORD=VotreMotDePasseNPM
NPM_PROXY_HOST_DOMAIN=wordly.art

# ── Rétention ────────────────────────────────
DAILY_RETENTION=7
WEEKLY_RETENTION=4
MONTHLY_RETENTION=6
DR_RETENTION_DAYS=30

Étape 3 : Créer un bot Telegram (5 minutes)

  1. Ouvrir Telegram → chercher @BotFather
  2. Envoyer /newbot
  3. Nom : Wordly Monitoring / Username : wordly_monitor_bot
  4. Copier le token → TELEGRAM_BOT_TOKEN
  5. Envoyer un message à votre bot
  6. Aller sur https://api.telegram.org/bot<TOKEN>/getUpdates
  7. Copier le chat.idTELEGRAM_CHAT_ID

Étape 4 : Configurer SSH sans mot de passe vers le NAS

# Sur le serveur .151 (en root)
sudo bash scripts/setup-nas.sh

Ce script :

  • Génère une clé SSH dédiée : /root/.ssh/wordly_nas_key
  • La copie sur le NAS (mot de passe demandé une seule fois)
  • Teste la connexion sans mot de passe
  • Crée la structure de dossiers sur le NAS
  • Configure ~/.ssh/config avec l'alias wordly-nas
  • Copie les scripts sur le NAS (disponibles depuis .98 pour la restauration)

Étape 5 : Tester le premier backup

bash scripts/backup-to-nas.sh --full

# Vérifier que l'archive est bien arrivée sur le NAS
bash scripts/backup-to-nas.sh --list

Étape 6 : Tester la vérification automatique

bash scripts/verify-backups.sh

Étape 7 : Tester le failover NPM (sans rien changer)

bash scripts/npm-failover.sh --dry-run --target-ip 192.168.1.98

Étape 8 : Activer les crons

bash scripts/install-crontab.sh
crontab -l   # Vérifier

2. VÉRIFICATION QUOTIDIENNE (automatique)

0  */6 * * *  backup-to-nas.sh   → Snapshot DB + archive → NAS via rsync SSH
30 */6 * * *  verify-backups.sh  → 8 vérifications + alerte Telegram si erreur

3. RESTAURATION D'URGENCE (quand .151 est mort)

Durée estimée : 2025 minutes

Sur le serveur de secours 192.168.1.98

# 1. Installer les prérequis (Docker déjà installé)
apt-get install -y rsync jq

# 2. Récupérer la clé SSH depuis le NAS (ou depuis une autre source sécurisée)
#    Option A : copier la clé depuis un endroit sûr (gestionnaire de mots de passe, etc.)
mkdir -p /root/.ssh && chmod 700 /root/.ssh
# collez le contenu de /root/.ssh/wordly_nas_key ici
nano /root/.ssh/wordly_nas_key
chmod 600 /root/.ssh/wordly_nas_key

# 3. Tester la connexion NAS
ssh -i /root/.ssh/wordly_nas_key wordly-backup@192.168.1.146 "echo OK"

# 4. Voir les archives disponibles
ssh -i /root/.ssh/wordly_nas_key wordly-backup@192.168.1.146 \
  "ls -lht /volume1/backups/wordly/snapshots/ | head -10"

# 5. Télécharger la dernière archive depuis le NAS
rsync -az \
  -e "ssh -i /root/.ssh/wordly_nas_key" \
  wordly-backup@192.168.1.146:/volume1/backups/wordly/snapshots/wordly_dr_TIMESTAMP.tar.gz \
  /tmp/

# 6. Télécharger les scripts de restauration depuis le NAS
rsync -az \
  -e "ssh -i /root/.ssh/wordly_nas_key" \
  wordly-backup@192.168.1.146:/volume1/backups/wordly/scripts/ \
  /opt/wordly/scripts/

# 7. Lancer la restauration complète
bash /opt/wordly/scripts/disaster-recovery.sh \
  --restore /tmp/wordly_dr_TIMESTAMP.tar.gz

Le script fait automatiquement :

  1. Extrait .env, docker-compose.yml, configs Docker
  2. Lance tous les containers Docker
  3. Attend que PostgreSQL soit healthy
  4. Restaure le dump SQL
  5. Health check sur http://localhost:8001/health (max 180s)
  6. Si OK → appelle NPM API → bascule le trafic vers 192.168.1.98
  7. Alerte Telegram : " Wordly.art DR COMPLET"

Si NPM failover automatique échoue (dernier recours) :

http://192.168.1.184:81 → Proxy Hosts → wordly.art → Edit
  Forward Hostname : 192.168.1.98
  → Save
# Changement immédiat, 0 redémarrage nécessaire

4. CONSERVATION DE LA CLÉ SSH NAS

Important

La clé /root/.ssh/wordly_nas_key est critique pour la restauration depuis .98. Conservez-la dans au minimum 2 endroits sécurisés :

  • Gestionnaire de mots de passe (Bitwarden, 1Password, etc.)
  • Coffre-fort KeePass chiffré sur un support physique

Sans cette clé, vous ne pouvez pas accéder aux archives sur le NAS depuis .98.


5. SCRIPTS DE RÉFÉRENCE

Script Usage Déclenchement
setup-nas.sh Configure SSH → NAS, génère clé, copie scripts Once (root requis)
backup-to-nas.sh pg_dump + archive DR → NAS via rsync SSH Cron toutes les 6h
backup-to-nas.sh --list Lister les archives disponibles sur le NAS Manuel
verify-backups.sh 8 checks intégrité + Telegram Cron toutes les 6h+30m
disaster-recovery.sh --backup Archive DR → NAS Inclus dans backup-to-nas
disaster-recovery.sh --restore <archive> Restauration complète Urgence
npm-failover.sh --target-ip <IP> Bascule NPM vers une IP Appelé automatiquement
npm-failover.sh --dry-run --target-ip <IP> Test sans modifier NPM Test initial
install-crontab.sh Installe les crons Once

6. LOGS

# Logs backup (sur .151)
tail -f /var/log/wordly-backup.log

# Logs vérification (sur .151)
tail -f /var/log/wordly-verify.log

# Logs Docker (sur le serveur actif)
docker compose logs -f backend
docker compose logs -f postgres