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

320 lines
10 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.
# 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
```bash
# 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`
```bash
# ── 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.id``TELEGRAM_CHAT_ID`
---
### Étape 4 : Configurer SSH sans mot de passe vers le NAS
```bash
# 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
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
bash scripts/verify-backups.sh
```
---
### Étape 7 : Tester le failover NPM (sans rien changer)
```bash
bash scripts/npm-failover.sh --dry-run --target-ip 192.168.1.98
```
---
### Étape 8 : Activer les crons
```bash
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`
```bash
# 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
```bash
# 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
```