Some checks failed
Deploy to Production / Build and Deploy (push) Has been cancelled
320 lines
10 KiB
Markdown
320 lines
10 KiB
Markdown
# 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 | 0–5s | ~1 min | Autorestart + WAL |
|
||
| Corruption DB partielle | 0–6h | ~5 min | Restore depuis NAS |
|
||
| Serveur .151 mort | 0–6h | **~25 min** | Restore NAS sur .98 + NPM auto |
|
||
| Erreur humaine (DROP) | 0–6h | ~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 : 20–25 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
|
||
```
|