← Tous les guidesAutomatisation des flux

Exécuter un serveur n8n privé que votre équipe sait vraiment restaurer

Déployez n8n sur un Droplet DigitalOcean, limitez les accès, sauvegardez ses données chiffrées dans un compartiment Spaces privé et prouvez une restauration avant qu’une panne ne devienne une urgence.

Définir la reprise avant le premier workflow

n8n n’est pas seulement un outil visuel d’automatisation. Il stocke les définitions de workflow, les identifiants chiffrés avec la clé de l’instance, les données d’exécution et la configuration qui indique où les retours d’appel doivent arriver. Une capture de l’éditeur n’est pas une sauvegarde. Une reprise réussie signifie qu’un nouveau serveur démarre avec la même clé de chiffrement, charge un workflow choisi et exécute un test inoffensif sans reconnecter chaque service.

Ce guide utilise l’application n8n en un clic de DigitalOcean sur un Droplet et un compartiment Spaces privé pour les sauvegardes chiffrées. Cette installation n’a pas de basculement automatique. N’ajoutez pas de dossiers clients, de clés API de production ou d’actions financières à un workflow avant d’avoir testé sa gestion des erreurs habituelles et cette procédure de reprise.

  • Un domaine géré par l’équipe, comme n8n.example.com, et l’accès à ses enregistrements DNS.
  • Un compte DigitalOcean qui peut créer un Droplet, un pare-feu, un compartiment Spaces et une clé Spaces limitée.
  • Un administrateur Linux qui sait utiliser SSH et peut conserver une clé de récupération hors ligne.
  • Un Droplet de test séparé ou une fenêtre de maintenance prévue pour le test de restauration.

Déployer l’image n8n, puis terminer la limite d’accès

L’application Marketplace déploie un Droplet avec la version stable actuelle de n8n et demande de faire pointer un enregistrement DNS A vers ce serveur avant de terminer la configuration. Utilisez une clé SSH pour le compte d’administration. N’activez pas un mot de passe SSH simplement pour rendre la première connexion plus facile.

Créez un pare-feu cloud avant d’inviter une autre personne. Autorisez TCP 80 et 443 pour le service web. Autorisez TCP 22 seulement depuis la sortie de votre VPN ou une adresse IP d’administration fixe. Activez la supervision et les sauvegardes du Droplet, mais considérez-les comme une couche distincte. La sauvegarde de ce guide protège les données et la configuration n8n sous une forme transportable.

Noter le dossier Compose déployé avant de le modifier
ssh ADMIN_USER@YOUR_DROPLET_IP
cd /opt/n8n-docker-caddy
sudo docker compose ps
sudo docker compose config --services
sudo docker volume ls
sudo ls -la

Garder stables l’adresse de retour et la clé de chiffrement

Terminez la configuration initiale sur votre domaine HTTPS, pas en gardant l’adresse IP du serveur dans des favoris. Dans le dossier de déploiement, examinez les fichiers Compose et le fichier d’environnement générés avant de les modifier. Définissez l’hôte public, le protocole et l’URL de webhook sur l’adresse HTTPS définitive avec les noms de variables documentés par la version n8n installée. Redémarrez la pile Compose seulement après avoir enregistré une copie protégée de la configuration actuelle.

Dans la disposition Docker et Caddy standard, le volume de données n8n contient la base SQLite et son matériel de chiffrement. L’archive de ce volume est le registre de reprise des identifiants. Si vous définissez N8N_ENCRYPTION_KEY hors de ce volume, conservez aussi l’archive de configuration protégée. Renouveler une clé est une tâche de maintenance volontaire, pas une étape de dépannage. Une sauvegarde sans la clé correspondante peut afficher des identifiants qu’elle ne peut pas utiliser.

  • Conservez les secrets dans l’environnement du serveur ou un gestionnaire de secrets protégé, jamais dans une note de workflow ni un dépôt Git.
  • Désignez un responsable pour chaque identifiant de production et retirez les identifiants qu’aucun workflow n’utilise.
  • Configurez la purge des exécutions avant que l’archive dépasse la fenêtre de sauvegarde ou le budget de stockage approuvé.

Créer un compartiment privé et une clé réservée à la sauvegarde

Créez un compartiment Spaces privé, par exemple n8n-recovery-your-team, dans une région choisie délibérément. N’activez ni listing public ni CDN. Activez le versionnage, puis créez une règle de cycle de vie qui conserve les archives principales pendant une durée approuvée par l’équipe. Quatre-vingt-dix jours sont un bon premier choix sans objectif de reprise défini. Créez ensuite une clé Spaces séparée et limitée à ce compartiment. Les clés limitées DigitalOcean proposent Read ou Read/Write/Delete. La tâche d’envoi exige sa propre clé Read/Write/Delete, car il n’existe pas de clé plus limitée en écriture seule. Conservez cette clé dans un fichier lisible par root sur le Droplet, avec le mode 600. Gardez aussi la clé publique du destinataire age ici. Conservez la clé privée correspondante hors du Droplet, par exemple dans un gestionnaire de mots de passe d’équipe avec un accès de reprise.

La sauvegarde reste illisible dans Spaces sans l’identité age hors ligne. Cela limite les dégâts si une clé Spaces fuit, mais cela signifie aussi qu’il faut vérifier que la personne de reprise peut utiliser cette identité avant de considérer la tâche comme fiable.

Installer les outils et protéger leur configuration
sudo apt-get update
sudo apt-get install -y awscli age
sudo install -d -m 700 /etc/n8n-recovery
sudo nano /etc/n8n-recovery/spaces.env
# Ajoutez AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY, puis enregistrez.
sudo chmod 600 /etc/n8n-recovery/spaces.env
sudo nano /etc/n8n-recovery/age-recipient.txt
# Ajoutez un destinataire public age1..., puis enregistrez.
sudo chmod 600 /etc/n8n-recovery/age-recipient.txt
Premier test

Vérifier ce flux avant de l’étendre

Entrée
Choisissez une paire récente d’archives chiffrées du volume et de configuration, un Droplet de test vide et l’identité de récupération conservée hors du serveur de production.
Mise en place
Déchiffrez la paire correspondante sur la machine de test, restaurez-la dans un nouveau volume de données n8n, puis démarrez la même version de n8n avec la configuration sauvegardée.
Résultat attendu
Un administrateur peut se connecter, ouvrir un workflow choisi et effectuer un test manuel inoffensif sans reconnecter son identifiant stocké.
Arrêter si
Arrêtez si les archives n’ont pas le même horodatage, si la clé de chiffrement manque, si la cible est le Droplet de production, si le pare-feu de test autorise encore le trafic sortant avant la désactivation des workflows ou si un identifiant récupéré apparaît dans un journal ou une capture.
Étape suivante
Consignez la date et le résultat de la restauration, renouvelez tout identifiant exposé pendant le test et détruisez l’environnement temporaire.

Sauvegarder le vrai volume persistant, pas seulement le fichier Compose

La disposition Compose de l’application en un clic peut changer avec le temps. Ne copiez pas le nom d’un volume depuis cet article. Utilisez docker volume ls et la configuration Compose relevée plus haut pour identifier le volume qui contient les données n8n. Ce guide couvre la disposition Marketplace Docker et Caddy avec des données n8n persistantes dans un volume. Si vous la remplacez volontairement par PostgreSQL, utilisez la procédure documentée d’export et de restauration du fournisseur de base, et testez-la comme un plan de reprise séparé.

Le script ci-dessous arrête brièvement la pile Compose, archive le volume n8n nommé et la configuration de déploiement, chiffre les deux avec votre destinataire public age, puis envoie les fichiers chiffrés. Définissez VOLUME_NAME seulement après avoir inspecté votre serveur. Le script refuse volontairement de le deviner. Il construit un manifeste de configuration à partir des fichiers réellement présents, inclut la configuration Caddy lorsqu’elle existe et échoue s’il ne trouve pas de fichier Compose. Exécutez-le une fois à la main avant de le planifier.

/usr/local/sbin/backup-n8n-to-spaces
#!/usr/bin/env bash
set -euo pipefail
umask 077

APP_DIR=/opt/n8n-docker-caddy
VOLUME_NAME=REPLACE_WITH_THE_N8N_DATA_VOLUME
BUCKET=YOUR_PRIVATE_BUCKET
REGION=YOUR_SPACES_REGION
PREFIX=n8n
BACKUP_DIR=/var/backups/n8n

case "$VOLUME_NAME" in
  REPLACE_*) echo "Set VOLUME_NAME after docker volume ls" >&2; exit 1 ;;
esac

set -a
. /etc/n8n-recovery/spaces.env
set +a
export AWS_DEFAULT_REGION=us-east-1
install -d -m 700 "$BACKUP_DIR"
STAMP=$(date -u +%Y-%m-%dT%H-%M-%SZ)
VOLUME_ARCHIVE="$BACKUP_DIR/n8n-volume-$STAMP.tar.gz"
CONFIG_ARCHIVE="$BACKUP_DIR/n8n-config-$STAMP.tar.gz"
RECIPIENT=$(cat /etc/n8n-recovery/age-recipient.txt)

cd "$APP_DIR"
CONFIG_INPUTS=()
for path in .env compose.yml docker-compose.yml Caddyfile caddy_config local_files; do
  [[ -e "$path" ]] && CONFIG_INPUTS+=("$path")
done
if [[ ! -f compose.yml && ! -f docker-compose.yml ]]; then
  echo "No Compose file found in $APP_DIR" >&2
  exit 1
fi

sudo docker compose stop
trap "sudo docker compose start" EXIT
sudo docker run --rm -v "$VOLUME_NAME":/data:ro -v "$BACKUP_DIR":/backup alpine \
  sh -c "tar -C /data -czf /backup/$(basename "$VOLUME_ARCHIVE") ."
sudo tar -C "$APP_DIR" -czf "$CONFIG_ARCHIVE" "${CONFIG_INPUTS[@]}"
sudo docker compose start
trap - EXIT

age -r "$RECIPIENT" -o "$VOLUME_ARCHIVE.age" "$VOLUME_ARCHIVE"
age -r "$RECIPIENT" -o "$CONFIG_ARCHIVE.age" "$CONFIG_ARCHIVE"
aws s3 cp "$VOLUME_ARCHIVE.age" "s3://$BUCKET/$PREFIX/" --endpoint-url "https://$REGION.digitaloceanspaces.com" --only-show-errors
aws s3 cp "$CONFIG_ARCHIVE.age" "s3://$BUCKET/$PREFIX/" --endpoint-url "https://$REGION.digitaloceanspaces.com" --only-show-errors
rm -f "$VOLUME_ARCHIVE" "$CONFIG_ARCHIVE" "$VOLUME_ARCHIVE.age" "$CONFIG_ARCHIVE.age"

Planifier la tâche et rendre un échec visible

Une sauvegarde qui échoue sans bruit est pire que l’absence de sauvegarde parce qu’elle donne une fausse confiance. Commencez avec une exécution quotidienne et un journal, puis reliez les échecs au système d’alerte que votre équipe regarde déjà. Choisissez la fréquence selon l’état d’automatisation que vous pouvez perdre. Pour un workflow qui crée des dossiers clients toutes les quelques minutes, une exécution quotidienne n’est probablement pas suffisante.

Toutes les quelques semaines, listez le préfixe du compartiment et comparez les deux archives les plus récentes avec le planning. Les archives du volume et de la configuration doivent avoir le même horodatage. Examinez une paire manquante avant la prochaine modification habituelle du serveur.

Exécuter à 03:23 UTC et garder un journal local
23 3 * * * root /usr/local/sbin/backup-n8n-to-spaces >> /var/log/n8n-recovery.log 2>&1
Confirmer que la dernière paire d’archives chiffrées existe
set -a
. /etc/n8n-recovery/spaces.env
set +a
aws s3 ls s3://YOUR_PRIVATE_BUCKET/n8n/ --endpoint-url https://YOUR_SPACES_REGION.digitaloceanspaces.com | tail -4

Restaurer dans un environnement de test isolé avant d’en avoir besoin

Un test de restauration ne doit ni écraser le Droplet de production ni contacter les systèmes de production. Créez un Droplet Linux temporaire avec un pare-feu cloud séparé. Utilisez un sous-domaine de test dédié, pas le nom d’hôte de production. Pendant l’émission du certificat, autorisez TCP 80 et 443 ainsi que le trafic sortant nécessaire à Caddy, mais démarrez seulement le service de proxy inverse. Limitez ensuite HTTPS à l’adresse IP de l’administrateur de reprise et bloquez le trafic sortant avant de démarrer n8n. Cela évite les e-mails, paiements, écritures CRM et appels webhook en double pendant le démarrage de l’instance récupérée.

Installez awscli, age, Docker Engine et le module Docker Compose sur le Droplet de test. Utilisez une clé Read limitée au compartiment et distincte de la clé d’envoi de production. Installez la même version d’image n8n, créez un volume de données nommé et vide, puis récupérez une archive de volume et une archive de configuration ayant le même horodatage. Utilisez l’identité privée age détenue par la personne de reprise seulement sur la machine de test. Ne la copiez pas sur le serveur de production. Extrayez l’archive de configuration dans un nouveau dossier Compose et restaurez l’archive chiffrée du volume dans le nouveau volume vide. Vérifiez l’étiquette d’image, l’URL publique et le traitement de la clé de chiffrement avant de démarrer n8n. Connectez-vous via le pare-feu limité à l’administrateur, désactivez tous les workflows, puis lancez un test manuel de nœud Set. Détruisez le Droplet de test ou retirez les identifiants récupérés quand vous avez terminé.

Télécharger, vérifier et charger une sauvegarde sur la machine de test
set -euo pipefail
TARGET_ENV=test
[[ "$TARGET_ENV" = test ]] || { echo "Refusing a production restore" >&2; exit 1; }
sudo apt-get update && sudo apt-get install -y awscli age docker.io docker-compose-plugin
sudo install -d -m 700 /etc/n8n-recovery
sudo nano /etc/n8n-recovery/restore-spaces.env
# Add a separate bucket-limited Read key, then chmod 600 that file.
set -a && . /etc/n8n-recovery/restore-spaces.env && set +a
STAMP=YYYY-MM-DDTHH-MM-SSZ
BUCKET=YOUR_PRIVATE_BUCKET
REGION=YOUR_SPACES_REGION
RESTORE_DIR=/srv/n8n-restore
RESTORE_VOLUME=n8n_restore_data
COMPOSE_FILE=docker-compose.yml
PRODUCTION_HOST=n8n.example.com
TEST_HOST=n8n-restore.example.com
umask 077
install -d -m 700 "$RESTORE_DIR" && cd "$RESTORE_DIR"

aws s3 cp "s3://$BUCKET/n8n/n8n-volume-$STAMP.tar.gz.age" . --endpoint-url "https://$REGION.digitaloceanspaces.com"
aws s3 cp "s3://$BUCKET/n8n/n8n-config-$STAMP.tar.gz.age" . --endpoint-url "https://$REGION.digitaloceanspaces.com"
test -s "n8n-volume-$STAMP.tar.gz.age" && test -s "n8n-config-$STAMP.tar.gz.age"
age -d -i /secure-path/n8n-recovery-key.txt -o n8n-volume.tar.gz "n8n-volume-$STAMP.tar.gz.age"
age -d -i /secure-path/n8n-recovery-key.txt -o n8n-config.tar.gz "n8n-config-$STAMP.tar.gz.age"
tar -xzf n8n-config.tar.gz -C "$RESTORE_DIR"
test -f "$COMPOSE_FILE"
tar -tzf n8n-volume.tar.gz | head -40
# Change both n8n and Caddy from the production hostname to the temporary test hostname.
grep -R "$PRODUCTION_HOST" .env Caddyfile
sed -i "s/$PRODUCTION_HOST/$TEST_HOST/g" .env Caddyfile
grep -E "N8N_HOST|WEBHOOK_URL|$TEST_HOST" .env Caddyfile
# With temporary 80/443 and outbound access, issue the certificate without starting n8n.
sudo docker compose -f "$COMPOSE_FILE" up -d caddy
# Now restrict HTTPS to the recovery IP and deny outbound traffic in the test firewall.
sudo docker volume create "$RESTORE_VOLUME"
sudo docker run --rm -v "$RESTORE_VOLUME":/data -v "$RESTORE_DIR":/backup:ro alpine \
  sh -c "tar -C /data -xzf /backup/n8n-volume.tar.gz"
cat > compose.recovery.yml <<EOF
volumes:
  n8n_data:
    name: $RESTORE_VOLUME
EOF
# This override is for the standard n8n_data key. Verify it and the pinned image before startup:
sudo docker compose -f "$COMPOSE_FILE" -f compose.recovery.yml config | grep -E "image:|$RESTORE_VOLUME"
# Start only after the test firewall denies outbound traffic:
sudo docker compose -f "$COMPOSE_FILE" -f compose.recovery.yml up -d

Savoir quand cette petite installation ne suffit plus

Dépassez le Droplet unique lorsque vous avez besoin d’un objectif de délai de reprise documenté, de plusieurs opérateurs qui modifient des workflows, d’un grand volume d’exécutions ou d’un workflow dont l’arrêt peut créer un problème matériel pour un client ou une opération financière. À ce stade, utilisez une base de données gérée lorsque c’est adapté, testez les sauvegardes de base séparément, gérez les secrets hors du Droplet et notez qui peut approuver une reprise.

N’utilisez pas un workflow n8n comme unique moyen de sauvegarder n8n. Le travail de sauvegarde doit rester hors de l’application qu’il protège. Cette séparation simple permet de récupérer le service lorsque c’est le service de workflow qui a échoué.