Dans cet article
Modifier un paramètre de base de données ne suffit pas pour migrer. Conservez un point de récupération vérifié, transférez les données de l’application, puis validez la nouvelle base avant de retirer l’ancienne.
Pour le cluster restauré Standard Edition, téléchargez son propre certificat d’autorité et remplacez le chemin dans l’exemple psql -W. L’option -W demande le mot de passe sans l’inscrire dans la commande. verify-full vérifie le certificat et le nom d’hôte. Consultez les instructions DigitalOcean, la vérification TLS PostgreSQL et les paramètres de base n8n. Relevez la version installée de n8n et le digest de l’image avant la migration. Vérifiez export:entities, import:entities et la désactivation des workflows dans l’aide du Server CLI de cette version ; ne présentez pas ces commandes comme testées sur une autre version.
Les commandes ci-dessous ciblent le Server CLI n8n 2.x. Vérifiez --version et unpublish:workflow --help dans l’image enregistrée avant de poursuivre. La référence Server CLI décrit l’export/import d’entités et unpublish:workflow --all ; update:workflow est déprécié depuis la version 2.0. Si l’image est plus ancienne ou ne propose pas une commande, arrêtez-vous et adaptez la procédure à son aide, sans mise à niveau pendant la récupération. Aucun environnement n8n installé n’a été exécuté pendant cette revue.
Décider si cette migration est nécessaire
SQLite convient à une installation n8n peu sollicitée. Passez à PostgreSQL quand plusieurs personnes administrent les workflows, que l’historique d’exécution compte ou qu’une panne a un coût réel. Il place les données n8n hors du Droplet. Il ne rend pas un workflow risqué plus sûr et ne remplace pas un plan de reprise.
Une base PostgreSQL vide peut laisser n8n démarrer sans vos workflows, identifiants ni historiques. Prévoyez une fenêtre de maintenance, gardez la clé de chiffrement n8n et ne touchez pas aux données SQLite avant l’acceptation de la bascule.
Vous avez besoin d’un accès administrateur DigitalOcean, d’un accès SSH au Droplet Linux qui exécute n8n et d’un endroit séparé pour tester une restauration. Un Droplet est le serveur virtuel. Une source approuvée est une règle réseau qui autorise un serveur ou une adresse d’administration à se connecter à la base.
- Une archive de récupération testée et la clé de chiffrement n8n correspondante.
- Une fenêtre de maintenance qui suspend les webhooks entrants et les tâches planifiées de production.
- Une personne désignée pour vérifier les identifiants et approuver la bascule finale.
Créer un point de récupération avant de modifier la base
Commencez avec une sauvegarde que vous savez restaurer. Notez la version n8n, l’étiquette d’image Compose, l’URL publique, l’emplacement de la clé de chiffrement, le nom du volume et l’horodatage de la dernière sauvegarde. Lisez une archive chiffrée dans l’environnement de récupération isolé du guide n8n privé. Gardez la même version n8n pour la migration. Ne combinez pas ce changement avec une mise à niveau n8n.
Si vous utilisez l’application n8n Marketplace du guide de récupération compagnon, le dossier de déploiement est généralement /opt/n8n-docker-caddy. Sinon, trouvez le fichier Compose avant de modifier quoi que ce soit. Le nom de service renvoyé par docker compose config --services remplace n8n dans les commandes suivantes.
Ouvrez un shell root sur le Droplet avec l'action ci-dessous avant les commandes. Conservez ce terminal pendant la migration et remplacez N8N_APP_DIR si votre chemin diffère.
sudo -i
sudo find /opt /srv /home -maxdepth 4 -type f \( -name compose.yml -o -name docker-compose.yml \) -print
N8N_APP_DIR=/opt/n8n-docker-caddy
cd "$N8N_APP_DIR"
sudo docker compose config --services
Créer une base PostgreSQL avec des accès limités
Créez d’abord le cluster. Ne modifiez pas n8n à ce stade. Ce guide utilise un cluster PostgreSQL Standard Edition, car ses paramètres de connexion comprennent un certificat CA que n8n peut monter. Si vous choisissez Advanced Edition, arrêtez-vous ici et adaptez TLS à son magasin de certificats système au lieu de recopier les étapes du fichier CA ci-dessous.
Revenez ensuite au terminal SSH du Droplet n8n. Définissez les chemins locaux réels du volume et de l'archive dans migration.env. La commande utilise un sous-shell pour garder votre terminal dans le dossier de déploiement. Vérifiez pwd avant l'export.
- Dans votre projet DigitalOcean, ouvrez Databases et cliquez sur Create Database. Vous pouvez aussi choisir Create, puis Managed Database. Sur Create Database Cluster, choisissez PostgreSQL et une version. Le moteur reste fixe. Une mise à niveau majeure prise en charge reste possible après les contrôles de compatibilité et la préparation de la reprise.
- Choisissez la même région que le Droplet n8n. Sélectionnez le plan et le stockage adaptés à la charge actuelle, saisissez n8n-postgres comme nom de cluster, choisissez le projet qui contient n8n, puis cliquez sur Create Database Cluster. Attendez que l’état du cluster affiche Online.
- Ouvrez le nouveau cluster, puis sélectionnez Users & Databases. Dans Databases, saisissez n8n dans Add new database et cliquez sur Save. Dans Users, saisissez n8n_app dans Add new user et cliquez sur Save. Utilisez n8n_app pour n8n. Réservez doadmin à l’administration et à la récupération.
- Sélectionnez Network Access, cliquez sur Add Trusted Sources, choisissez Quick select Droplets, puis sélectionnez le Droplet n8n. Cliquez sur Add Trusted Sources. Pour un contrôle ponctuel en ligne de commande, ajoutez votre adresse IPv4 actuelle depuis cette même fenêtre. Retirez-la après le contrôle. N’ajoutez pas 0.0.0.0/0.
- Retournez à Overview et ouvrez Connection Details. Copiez l’hôte, le port, le nom de la base, le nom d’utilisateur n8n_app et le mot de passe dans un gestionnaire de mots de passe. Téléchargez le certificat CA et copiez-le plus tard sur le Droplet n8n. Ne mettez aucune de ces valeurs dans Git, des notes de workflow ou des captures d’écran.
(
cd /root
git clone https://github.com/TylorMayfield/n8n-digitalocean-postgres-migration.git
cd n8n-digitalocean-postgres-migration
install -m 600 migration.env.example migration.env
)
sudo nano /root/n8n-digitalocean-postgres-migration/migration.env
sudo /root/n8n-digitalocean-postgres-migration/scripts/preflight.sh /root/n8n-digitalocean-postgres-migration/migration.env
cd "$N8N_APP_DIR"
pwd
Valider le rôle applicatif cible avant l’interruption
Gardez SQLite actif tant que ce contrôle n’est pas validé. Créer n8n et n8n_app, ou réussir le contrôle local du compagnon, ne prouve pas que ce rôle peut initialiser PostgreSQL. Définissez avec l’administrateur la propriété de la base dédiée et du schéma persistant. Pour le schéma public utilisé ci-dessous, le rôle réel n8n_app doit avoir les droits minimaux pour créer et modifier ses objets applicatifs et lire/écrire leurs données. Une connexion réussie, SELECT now() ou un test de table temporaire ne suffit pas ; les droits de schéma varient selon la version PostgreSQL et l’historique du cluster.
Avant la maintenance, répétez sur une cible jetable vide du même fournisseur et de la même version PostgreSQL, avec n8n_app et le chemin TLS/réseau prévu depuis l’hôte n8n. Vérifiez les opérations nécessaires de création, modification et accès aux données dans le schéma persistant avec des objets jetables aux noms uniques, un contrôle de collision et une annulation de transaction ou un nettoyage explicite ; confirmez qu’aucun objet de test ne reste. Ajoutez un contrôle négatif démontrant que l’absence du droit de création dans le schéma arrête la répétition. Répétez ensuite l’initialisation/import n8n avec l’image figée ; une sonde SQL seule ne valide pas l’import.
Cet article ne fournit pas de SQL d’attribution de droits ou de test validé pour votre fournisseur. Faites d’abord relire et tester cette séquence de moindre privilège par l’administrateur, puis validez la cible réelle vide avant d’arrêter SQLite. Si ce contrôle manque ou échoue, arrêtez la migration ici. N’utilisez pas doadmin comme identité d’exécution n8n et n’accordez pas de droits larges à PUBLIC ou à tout le cluster pour réussir le test. Consultez les droits des rôles DigitalOcean et les droits des schémas PostgreSQL.
Effectuer une bascule planifiée
Bloquez les requêtes entrantes et désactivez les tâches planifiées avant cette séquence. Laissez n8n actif pour lire son UID et son GID ; le script l’arrête ensuite avant l’export. Gardez la même image et la même clé de chiffrement. Attendez un export réussi avant de changer la base.
Avant la fenêtre de maintenance, choisissez le sort de l’historique d’exécution. La référence Server CLI précise que l’export d’entités exclut par défaut les tables de données de cet historique.
- Migrer l’historique : utilisez l’export ci-dessous seulement si l’aide de l’image exacte enregistrée prend en charge
--includeExecutionHistoryDataTables=true. Prévoyez davantage d’espace disque et de temps pour l’export/import ; les données d’exécution peuvent être volumineuses et sensibles. Répétez d’abord la procédure sur une copie isolée avec la même image figée. - Archiver l’historique dans SQLite : omettez cette option uniquement après avoir consigné que les anciennes exécutions ne figureront pas dans PostgreSQL. Conservez et testez l’archive de récupération SQLite selon la politique convenue de conservation et d’accès. Ne présentez pas ce choix comme une migration de l’historique.
Vérifiez l’image en cours avant la bascule. Si l’option manque ou si sa syntaxe diffère, arrêtez-vous et adaptez la procédure à cette version ; ne faites pas de mise à niveau pour faire fonctionner l’exemple.
sudo docker compose exec -T n8n n8n --version
sudo docker compose exec -T n8n n8n export:entities --help
Cette option inclut les tables d’historique de la base ; elle ne constitue pas une sauvegarde complète. Préservez séparément la clé de chiffrement correspondante, la configuration et tout stockage de fichiers binaires ou d’exécutions sur le système de fichiers ou un service externe. Le guide de sauvegarde n8n décrit ce périmètre plus large. Cette procédure n’a pas été testée en exécution avec votre image figée.
Avant l’export, une fois les écritures de production suspendues et les exécutions en cours terminées, relevez les nombres de lignes des tables sources concernées et les identifiants d’une ancienne exécution réussie et d’une ancienne exécution échouée. Incluez des données d’entrée/sortie représentatives et une pièce jointe binaire si votre mode de stockage en utilise. Gardez ces relevés privés.
Le fichier .env se trouve à côté du fichier Compose. Il contient les valeurs que Compose transmet au conteneur n8n. Ajoutez-y les valeurs PostgreSQL. Ajoutez ensuite les entrées environment correspondantes et le montage en lecture seule du certificat CA au service n8n dans compose.yml ou docker-compose.yml. Un fichier .env seul ne donne pas de nouvelles variables à un conteneur en cours d’exécution si le fichier Compose ne les référence pas.
cd "$N8N_APP_DIR"
set -euo pipefail
sudo apt-get update
sudo apt-get install -y unzip
if [[ -f compose.yml ]]; then COMPOSE_FILE=compose.yml; elif [[ -f docker-compose.yml ]]; then COMPOSE_FILE=docker-compose.yml; else echo 'No Compose file'; exit 1; fi
sudo cp .env .env.sqlite-backup
sudo chmod 600 .env .env.sqlite-backup
sudo cp "$COMPOSE_FILE" "$COMPOSE_FILE.sqlite-backup"
N8N_UID=$(sudo docker compose exec -T n8n id -u)
N8N_GID=$(sudo docker compose exec -T n8n id -g)
sudo install -d -o "$N8N_UID" -g "$N8N_GID" -m 700 migration-entities
sudo install -d -m 700 secrets
sudo tee compose.migration.yml > /dev/null <<'YAML'
services:
n8n:
volumes:
- ./migration-entities:/migration
YAML
sudo docker compose stop n8n
sudo docker compose -f "$COMPOSE_FILE" -f compose.migration.yml run --rm --no-deps n8n export:entities --outputDir=/migration --includeExecutionHistoryDataTables=true
sudo test -s migration-entities/entities.zip
sudo unzip -t migration-entities/entities.zip
# Continue only after export exits successfully and the directory contains the exported entities.
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=YOUR_CLUSTER_HOST
DB_POSTGRESDB_PORT=YOUR_CLUSTER_PORT
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n_app
DB_POSTGRESDB_PASSWORD=YOUR_N8N_APP_PASSWORD
DB_POSTGRESDB_SCHEMA=public
DB_POSTGRESDB_SSL_ENABLED=true
DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED=true
DB_POSTGRESDB_SSL_CA_FILE=/run/secrets/do-postgres-ca.crt
# Exécutez ensuite sudo nano $COMPOSE_FILE. Dans le service n8n existant, ajoutez ces entrées sans supprimer ses variables ou volumes actuels.
services:
n8n:
environment:
DB_TYPE: ${DB_TYPE}
DB_POSTGRESDB_HOST: ${DB_POSTGRESDB_HOST}
DB_POSTGRESDB_PORT: ${DB_POSTGRESDB_PORT}
DB_POSTGRESDB_DATABASE: ${DB_POSTGRESDB_DATABASE}
DB_POSTGRESDB_USER: ${DB_POSTGRESDB_USER}
DB_POSTGRESDB_PASSWORD: ${DB_POSTGRESDB_PASSWORD}
DB_POSTGRESDB_SCHEMA: ${DB_POSTGRESDB_SCHEMA}
DB_POSTGRESDB_SSL_ENABLED: ${DB_POSTGRESDB_SSL_ENABLED}
DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED: ${DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED}
DB_POSTGRESDB_SSL_CA_FILE: ${DB_POSTGRESDB_SSL_CA_FILE}
volumes:
- ./secrets/do-postgres-ca.crt:/run/secrets/do-postgres-ca.crt:ro
set -euo pipefail
# Save the DigitalOcean CA certificate as secrets/do-postgres-ca.crt first.
sudo chmod 644 secrets/do-postgres-ca.crt
# The CA is public verification material; keep database passwords in protected .env.
sudo docker compose -f "$COMPOSE_FILE" -f compose.migration.yml run --rm --no-deps n8n import:entities --inputDir=/migration
# Disable imported schedules/webhooks before the first application start.
sudo docker compose -f "$COMPOSE_FILE" run --rm --no-deps n8n unpublish:workflow --all
sudo docker compose -f "$COMPOSE_FILE" up -d
Prouver le résultat avant de rouvrir le trafic de production
Si vous avez choisi de migrer l’historique, comparez ces nombres dans PostgreSQL avant que le test manuel ne crée de nouvelles lignes. Ouvrez les anciennes exécutions relevées et vérifiez leur état, leurs données et les pièces jointes binaires applicables. Des nombres de lignes identiques ne prouvent pas à eux seuls que les données sont utilisables. Pour le choix d’archivage, vérifiez ces exécutions dans une restauration isolée de l’archive SQLite et consignez leur absence volontaire de PostgreSQL. Ne rouvrez pas le trafic de production si le résultat de conservation choisi n’est pas vérifié.
Connectez-vous en administrateur. Ouvrez un workflow connu, déchiffrez un identifiant connu et terminez une exécution manuelle inoffensive. Gardez les workflows de production désactivés jusqu’à la fin des contrôles. Si un identifiant ne se déchiffre pas, restaurez l’ancien service. Ne réinitialisez pas les identifiants pendant l’enquête.
Conservez l’archive de récupération originale jusqu’à l’acceptation de tous les contrôles par la personne responsable de la bascule. Répétez le retour arrière dans l’environnement de récupération isolé, avec les entrées toujours bloquées, et vérifiez l’accès aux anciennes exécutions relevées et à leurs données.
Testez ensuite la récupération de la base depuis le panneau de contrôle. Ouvrez Databases, sélectionnez le cluster n8n, choisissez Actions, puis Restore from backup. Choisissez un point récent, donnez un nom de test au cluster restauré et sélectionnez Restore to New Cluster. Quand il est online, ajoutez seulement votre adresse d’administration dans Network Access, copiez ses nouveaux paramètres de connexion et effectuez un contrôle psql en lecture seule. Cela prouve le point de récupération de la base, pas que chaque workflow est sûr.
# Sur le Droplet n8n, vérifiez le service en cours et son journal de démarrage.
sudo docker compose ps
sudo docker compose logs --tail=100 n8n
# Sur une machine d’administration avec le client PostgreSQL installé, utilisez les nouveaux paramètres du cluster restauré.
PGSSLMODE=verify-full \
PGSSLROOTCERT="/path/to/restored-cluster-ca.crt" \
psql -W -h RESTORED_CLUSTER_HOST -p RESTORED_CLUSTER_PORT -U n8n_app -d n8n \
-c 'select current_database(), current_user, now();'
# Ouvrez ensuite un workflow, déchiffrez un identifiant et lancez un test manuel inoffensif. Consignez le résultat.
Revenir à SQLite avant de reprendre le trafic
Utilisez ce retour uniquement tant que le trafic de production est suspendu et qu'aucune nouvelle donnée n'a été acceptée dans PostgreSQL. Il rétablit les fichiers préservés et le volume SQLite original. Gardez les entrées réseau bloquées pendant la vérification. Si vous avez déjà repris les écritures, arrêtez-vous et préparez une réconciliation; ce retour perdrait les nouvelles données.
cd "$N8N_APP_DIR"
sudo docker compose -f "$COMPOSE_FILE" stop n8n
sudo test -f .env.sqlite-backup
sudo test -f "$COMPOSE_FILE.sqlite-backup"
sudo cp .env.sqlite-backup .env
sudo cp "$COMPOSE_FILE.sqlite-backup" "$COMPOSE_FILE"
sudo docker compose -f "$COMPOSE_FILE" run --rm --no-deps n8n unpublish:workflow --all
sudo docker compose -f "$COMPOSE_FILE" up -d n8n
sudo docker compose -f "$COMPOSE_FILE" ps
Savoir ce que PostgreSQL géré ne couvre pas
PostgreSQL géré exécute la base et fournit des sauvegardes ainsi qu’une récupération de l’infrastructure. Vous gardez la responsabilité des accès, de la logique des workflows, des identifiants et de la décision d’exécuter un workflow après récupération. Revoyez cette répartition après le premier test de restauration, pas pendant une panne.
Si n8n traite des données clients importantes ou des actions irréversibles, documentez un objectif de délai de reprise et une perte de données acceptable. La base fait maintenant partie d’un système d’exploitation, pas d’une simple mise à niveau.
Questions fréquentes
Puis-je passer de SQLite à PostgreSQL dans n8n sans interruption ?
Prévoyez une fenêtre de maintenance. Une bascule sûre suspend les nouvelles exécutions, préserve les données SQLite, exporte et importe les entités n8n avec le Server CLI installé et vérifie les identifiants avant la reprise de la production.
Une sauvegarde PostgreSQL gérée remplace-t-elle les sauvegardes n8n ?
Non. Elle protège le service de base et aide à récupérer la base. Gardez aussi dans le plan la clé de chiffrement n8n, la configuration de déploiement et un test de récupération applicative isolé.
Pourquoi déclarer le Droplet n8n comme source approuvée au lieu d’ouvrir la base publiquement ?
Une règle de source approuvée limite les connexions possibles à la base. Limitez-la au serveur applicatif et à un accès administrateur temporaire, puis retirez cet accès après la validation.