# 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/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 ` | Restauration complète | **Urgence** | | `npm-failover.sh --target-ip ` | Bascule NPM vers une IP | Appelé automatiquement | | `npm-failover.sh --dry-run --target-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 ```