Introduction
Les applications Node.js détiennent souvent des données critiques dans des fichiers, des bases de données et en mémoire. La perte de ces données peut entraîner des temps d'arrêt, des pertes de revenus et de la frustration chez les utilisateurs. Une stratégie de sauvegarde et de restauration robuste est essentielle pour tout déploiement de Node.js en production.
Ce guide présente une approche pratique pour sauvegarder et restaurer des applications Node.js. Nous couvrons l'inventaire de l'environnement, les chemins de configuration sûrs, la vérification, les modes de défaillance et une liste de contrôle opérationnelle. À la fin, vous aurez un plan clair et étape par étape pour protéger les données de votre application Node.js.
Nous nous concentrons sur une configuration Node.js typique : un serveur Linux exécutant un processus Node.js, utilisant un système de fichiers local pour les fichiers de l'application et une base de données (par exemple MongoDB ou PostgreSQL) pour les données persistantes. Les exemples utilisent des outils simples et largement disponibles comme tar, pg_dump et des scripts Node.js.
Inventaire de la version et de l'environnement
Avant de mettre en œuvre toute stratégie de sauvegarde, documentez votre environnement. Cela permet de garantir que les sauvegardes sont complètes et restaurables. Un inventaire clair aide également lors de la réponse aux incidents, lorsque vous devez savoir exactement quoi restaurer et comment.
Hôte et système d'exploitation : Notez le système d'exploitation et sa version du serveur. Exemple : Ubuntu 22.04 LTS.
Version de Node.js et paquets globaux : Utilisez node --version pour vérifier la version de Node.js. Enregistrez les paquets installés globalement avec npm list -g --depth=0.
Détails de l'application : Identifiez le répertoire de l'application (par exemple, /var/www/myapp), l'utilisateur exécutant le processus Node.js (par exemple, nodeuser) et le gestionnaire de processus (par exemple, systemd, PM2). Ces informations sont cruciales pour les permissions correctes et le redémarrage du service lors de la restauration.
Base de données et autres services : Enregistrez le type de base de données, la version, la chaîne de connexion (sans informations d'identification si possible) et tout service externe comme Redis ou Elasticsearch. Par exemple : PostgreSQL 14.8, hôte db.internal, port 5432.
Fichiers de configuration : Listez tous les fichiers de configuration spécifiques à l'environnement, tels que .env, config.json ou config/production.json. Ceux-ci doivent être inclus dans les sauvegardes. Notez leurs chemins et les secrets qu'ils contiennent (mots de passe, clés API).
Prérequis pour les outils de sauvegarde : Assurez-vous que les utilitaires standard sont installés : tar, gzip, rsync et des outils spécifiques aux bases de données comme pg_dump ou mongodump. Vérifiez les versions pour éviter les surprises de compatibilité : tar --version, pg_dump --version.
Exemple de commande d'inventaire :
node --version && npm --version && systemctl status myapp --no-pager
Sortie attendue (les versions peuvent varier) :
v18.17.1
9.6.7
● myapp.service - My Node.js App
Loaded: loaded (/etc/systemd/system/myapp.service; enabled)
Active: active (running) since Tue 2025-03-25 10:00:00 UTC; 2h ago
Conservez cet inventaire dans un document sous contrôle de version (par exemple, backup-inventory.md) et mettez-le à jour chaque fois que l'environnement change.
Chemin de configuration sûr
Commencez par une sauvegarde pilote étroite et mesurable, facile à inspecter localement. Cela réduit les risques et renforce la confiance. Une sauvegarde pilote couvre uniquement les données essentielles de l'application, pas tout le serveur, et peut être restaurée et validée rapidement.
Choisir l'étendue de la sauvegarde : Pour le premier pilote, sauvegardez uniquement le répertoire de l'application et la base de données, pas tout le serveur. Cela maintient la taille de la sauvegarde gérable et simplifie la validation.
Créez un script de sauvegarde qui utilise tar pour les fichiers et un outil de vidage de base de données. Le script doit être idempotent et sûr à exécuter de manière répétée.
Exemple de script backup.sh :
#!/bin/bash
# Script de sauvegarde pour l'application Node.js
set -e
APP_DIR="/var/www/myapp"
BACKUP_ROOT="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_ROOT/myapp_$DATE"
mkdir -p "$BACKUP_DIR"
# 1. Sauvegarder les fichiers de l'application
tar -czf "$BACKUP_DIR/app_files.tar.gz" -C "$APP_DIR" .
# 2. Sauvegarder la base de données PostgreSQL (exemple)
PGPASSWORD="$DB_PASSWORD" pg_dump -U "$DB_USER" -h "$DB_HOST" "$DB_NAME" > "$BACKUP_DIR/db_dump.sql"
# 3. Créer un manifeste
cat > "$BACKUP_DIR/manifest.txt" <<EOF
Sauvegarde créée : $DATE
Version de Node.js : $(node --version)
Sauvegarde des fichiers : app_files.tar.gz
Sauvegarde de la base de données : db_dump.sql
EOF
echo "Sauvegarde terminée : $BACKUP_DIR"
Exécutez le script en tant qu'utilisateur disposant des permissions appropriées (souvent root ou l'utilisateur de l'application). Exemple d'exécution et de sortie :
sudo ./backup.sh
Sauvegarde terminée : /backups/myapp_20250325_120000
Vérifiez le contenu de la sauvegarde localement avant de vous y fier. Listez les fichiers dans l'archive tar et vérifiez l'en-tête du vidage de la base de données.
tar -tzf /backups/myapp_20250325_120000/app_files.tar.gz | head -5
head -10 /backups/myapp_20250325_120000/db_dump.sql
Sortie attendue (exemple) :
package.json
server.js
config/
config/production.json
.env
--
-- PostgreSQL database dump
--
Planifiez des sauvegardes automatiques en utilisant cron. Ajoutez une ligne à /etc/crontab ou utilisez crontab -e :
0 2 * * * root /usr/local/bin/backup.sh >> /var/log/myapp_backup.log 2>&1
Cela exécute la sauvegarde quotidiennement à 2h00. Assurez-vous que le fichier journal est rotatif pour éviter de remplir l'espace disque.
Pour MongoDB, utilisez mongodump au lieu de pg_dump. Exemple :
mongodump --uri="mongodb://$DB_USER:$DB_PASSWORD@$DB_HOST:27017/$DB_NAME" --out="$BACKUP_DIR/mongodump"
Pour les grandes bases de données, envisagez des sauvegardes incrémentielles ou utilisez pg_dump --format=custom pour la compression et la restauration parallèle.
Vérification et diagnostics
Les sauvegardes ne sont utiles que si elles peuvent être restaurées. Testez régulièrement la restauration dans un environnement de préproduction. Cette section couvre la création d'un script de restauration, son exécution et la validation de l'application restaurée.
Créez un script de restauration qui effectue d'abord une simulation (dry run). Une simulation extrait les fichiers vers un emplacement temporaire et n'affecte pas la production.
Exemple de script de restauration restore.sh :
#!/bin/bash
# Script de restauration pour l'application Node.js
set -e
BACKUP_DIR="$1"
RESTORE_APP_DIR="/tmp/restore_test/app"
RESTORE_DB_NAME="myapp_restore_test"
# Extraire les fichiers
tar -xzf "$BACKUP_DIR/app_files.tar.gz" -C "$RESTORE_APP_DIR"
# Restaurer la base de données (exemple PostgreSQL)
PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -d postgres -c "DROP DATABASE IF EXISTS $RESTORE_DB_NAME;"
PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -d postgres -c "CREATE DATABASE $RESTORE_DB_NAME;"
PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -d "$RESTORE_DB_NAME" < "$BACKUP_DIR/db_dump.sql"
echo "Test de restauration terminé. Vérifiez l'application et la base de données."
Exécutez le test de restauration et vérifiez que l'application Node.js démarre correctement avec les données restaurées. Utilisez un environnement de préproduction séparé ou un port non standard pour éviter les conflits.
Contrôles de validation :
- Comparez les nombres de fichiers et les tailles entre la sauvegarde et l'original.
- Exécutez l'application Node.js en utilisant les fichiers et la base de données restaurés dans un environnement de test.
- Vérifiez par sondage les enregistrements de la base de données ou exécutez des contrôles de santé spécifiques à l'application.
Exemples de commandes de validation :
# Compter les fichiers dans la sauvegarde par rapport à l'original
find /var/www/myapp -type f | wc -l
tar -tzf /backups/myapp_20250325_120000/app_files.tar.gz | wc -l
# Vérifier le nombre d'enregistrements dans la base de données
PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -d "$RESTORE_DB_NAME" -c "SELECT count(*) FROM users;"
Les sorties doivent être cohérentes. Si le nombre de fichiers diffère, recherchez les fichiers manquants. Si le nombre d'enregistrements de la base de données diffère, vérifiez les erreurs de vidage.
Pour un test plus approfondi, démarrez l'application Node.js avec les fichiers restaurés et pointez-la vers la base de données restaurée. Exemple :
cd /tmp/restore_test/app
NODE_ENV=test DB_HOST=localhost DB_NAME=myapp_restore_test node server.js
Surveillez les journaux de démarrage et exécutez un test de fumée (par exemple, curl http://localhost:3000/health).
Enregistrez les résultats de vérification pour suivre la santé des sauvegardes au fil du temps. Créez une entrée de journal simple ou utilisez un outil de surveillance. Exemple :
echo "$(date) Test de restauration réussi" >> /var/log/myapp_restore_test.log
Automatisez les tests de restauration mensuellement ou après des changements importants.
Modes de défaillance et récupération
Les sauvegardes peuvent échouer silencieusement et les restaurations peuvent être incomplètes. Préparez-vous aux modes de défaillance courants. Comprendre ceux-ci vous aide à renforcer la résilience et à réagir rapidement.
Modes de défaillance courants :
- Le script de sauvegarde échoue en raison d'un espace disque insuffisant.
- Le vidage de la base de données échoue en raison de problèmes de connexion ou de permissions.
- Les fichiers de sauvegarde sont corrompus.
- La restauration échoue en raison de divergences de versions.
- L'état en mémoire n'est pas capturé, entraînant une perte de données.
- Le processus de sauvegarde s'exécute mais se termine avec un statut non nul, et cron n'alerte pas.
- Des erreurs de chiffrement ou de compression rendent les sauvegardes illisibles.
Stratégies de récupération et de retour en arrière :
- Conservez plusieurs générations de sauvegardes (par exemple, quotidiennes pendant 7 jours, hebdomadaires pendant 4 semaines).
- Stockez les sauvegardes hors site ou dans un emplacement séparé, de préférence dans une zone de disponibilité ou un fournisseur cloud différent.
- Ayez un processus documenté pour revenir à une sauvegarde précédente.
- Pour les applications Node.js, envisagez d'utiliser un gestionnaire de processus comme PM2 ou systemd pour redémarrer rapidement avec le code précédent si un nouveau déploiement échoue.
Exemple de procédure de retour en arrière :
- Arrêtez l'application actuelle.
- Restaurez les fichiers à partir de la dernière bonne sauvegarde connue.
- Restaurez la base de données si nécessaire.
- Démarrez l'application et vérifiez.
Test de la récupération après défaillance : Simulez une défaillance en supprimant un fichier et en le restaurant à partir de la sauvegarde. Enregistrez le temps de récupération. Cette pratique garantit que votre équipe connaît les étapes et peut respecter les objectifs de temps de récupération (RTO).
État en mémoire : Si votre application repose sur des caches ou des sessions en mémoire, assurez-vous qu'ils peuvent être reconstruits après la restauration. Par exemple, si vous utilisez Redis, sauvegardez les données Redis séparément en utilisant redis-cli save et copiez le fichier RDB. Exemple :
redis-cli save
cp /var/lib/redis/dump.rdb /backups/myapp_$DATE/redis.rdb
Alternativement, traitez l'état en mémoire comme éphémère et assurez-vous que votre application peut le reconstruire à partir de la base de données après le redémarrage.
Gestion des échecs de sauvegarde : Configurez des alertes pour les échecs de tâche de sauvegarde. Dans cron, redirigez les erreurs vers un journal séparé et surveillez-le. Par exemple, modifiez la ligne cron :
0 2 * * * root /usr/local/bin/backup.sh > /var/log/myapp_backup.log 2> /var/log/myapp_backup_error.log || echo "Sauvegarde échouée" | mail -s "Échec de sauvegarde" [email protected]
Mettez en œuvre une politique de rétention. Exemple de script pour supprimer les anciennes sauvegardes :
#!/bin/bash
# Supprimer les sauvegardes de plus de 7 jours
find /backups -maxdepth 1 -type d -name "myapp_*" -mtime +7 -exec rm -rf {} \;
Pour le stockage hors site, utilisez rsync pour copier les sauvegardes vers un serveur distant ou un stockage cloud. Exemple :
rsync -avz /backups/ user@backup-server:/remote-backups/
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour garantir que votre processus de sauvegarde et de restauration reste efficace.
| Tâche | Fréquence | Responsable |
|---|---|---|
| Exécuter une sauvegarde complète | Quotidienne | Ops/Dév |
| Vérifier l'intégrité de la sauvegarde (lister les fichiers, vérifier le vidage) | Hebdomadaire | Ops/Dév |
| Tester la restauration en préproduction | Mensuelle | Équipe de développement |
| Rotation et purge des anciennes sauvegardes | Hebdomadaire | Ops/Dév |
| Mettre à jour la documentation lors des changements d'environnement | À chaque changement | Équipe de développement |
| Examiner les journaux de sauvegarde pour détecter les erreurs | Quotidienne | Ops/Dév |
| Tester le plan de reprise après sinistre | Trimestrielle | Toute l'équipe |
| Vérifier la réplication des sauvegardes hors site | Quotidienne | Ops/Dév |
Automatisez là où c'est possible en utilisant des tâches cron ou des pipelines planifiés.
Surveillez les métriques de sauvegarde telles que la durée, la taille et le succès/échec. Utilisez un journal simple ou un système de surveillance comme Prometheus avec un exportateur personnalisé.
Gardez le processus de restauration simple et documenté afin que tout membre de l'équipe puisse l'exécuter sous pression. Conservez une copie imprimée du manuel d'exploitation dans un endroit sûr.
Conclusion
Une stratégie de sauvegarde et de restauration solide est essentielle pour les applications Node.js. Commencez par une sauvegarde petite et vérifiable, automatisez-la et testez régulièrement la restauration. Documentez votre environnement, utilisez des outils simples et surveillez les échecs. En suivant ce guide, vous pouvez minimiser la perte de données et les temps d'arrêt.
Prochaines étapes :
- Créez un inventaire de votre environnement Node.js.
- Implémentez le script de sauvegarde pour votre application et votre base de données.
- Planifiez des sauvegardes et des vérifications régulières.
- Effectuez un test de restauration complet dans un environnement de préproduction.
- Documentez et pratiquez les procédures de retour en arrière.
N'oubliez pas que les sauvegardes ne valent que par votre capacité à les restaurer. Testez régulièrement.