Installer n8n avec Docker Compose sur un VPS

10 min de lecture·Matthieu|

Installez n8n 2.x avec Docker Compose et PostgreSQL sur un VPS. Configuration prête pour la production dès le départ : versions figées, sauvegarde de la clé de chiffrement, health checks et limites de ressources.

Ce guide installe n8n 2.12.3 avec Docker Compose et PostgreSQL sur un VPS. Vous aurez une instance n8n fonctionnelle en 15 minutes environ. La configuration utilise des paramètres de production dès le départ : versions d'images figées, identifiants chiffrés, port lié à localhost uniquement, health checks sur les deux conteneurs et limites de ressources Docker. Pas de reverse proxy ni de SSL ici. Cela est couvert dans .

De quoi ai-je besoin avant d'installer n8n ?

Il vous faut un VPS sous Debian 12 ou Ubuntu 24.04 avec au moins 4 Go de RAM. Docker et Docker Compose (le plugin docker compose, pas l'ancien binaire docker-compose) doivent être installés. Si Docker n'est pas encore en place, suivez d'abord Docker Compose pour déploiements multi-services sur VPS.

Vérifiez que Docker Compose est disponible :

docker compose version

Sortie attendue :

Docker Compose version v2.x.x

Si cette commande échoue avec docker: 'compose' is not a docker command, vous avez l'ancien binaire standalone. Installez le plugin Docker Compose depuis le dépôt officiel Docker.

Vous avez aussi besoin d'un utilisateur non-root avec accès sudo. Toutes les commandes de ce guide s'exécutent avec cet utilisateur, pas en root.

Pourquoi utiliser PostgreSQL plutôt que SQLite pour n8n ?

PostgreSQL gère les connexions concurrentes, prend en charge le WAL pour la récupération après crash et fonctionne avec pg_dump pour les sauvegardes à chaud pendant que n8n tourne. SQLite verrouille l'intégralité du fichier de base de données à chaque écriture. Lors d'exécutions concurrentes de webhooks, cela provoque des timeouts et de la corruption de données. Il est impossible de sauvegarder une base SQLite en toute sécurité pendant que n8n tourne sans risquer une copie corrompue. Pour tout ce qui dépasse les tests en local, PostgreSQL est le bon choix.

Fonctionnalité SQLite PostgreSQL
Écritures concurrentes Verrou mono-écriture MVCC complet
Sauvegardes à chaud Risqué en cours d'exécution pg_dump à tout moment
Récupération après crash Rejeu manuel du journal Rejeu automatique du WAL
Montée en charge Processus unique Pool de connexions
Variable d'env n8n DB_TYPE=sqlite DB_TYPE=postgresdb

Comment installer n8n avec Docker Compose sur un VPS ?

Créez un répertoire projet, écrivez un fichier .env avec vos secrets, écrivez le docker-compose.yml, démarrez la stack et vérifiez que tout est sain. Chaque étape inclut une vérification.

Créer le répertoire du projet

mkdir -p ~/n8n && cd ~/n8n

Créer le fichier .env

Tous les secrets vont dans un fichier .env. Ne codez jamais les mots de passe ou les clés en dur dans docker-compose.yml.

Générez un mot de passe de base de données robuste et la clé de chiffrement n8n :

echo "POSTGRES_PASSWORD=$(openssl rand -base64 32)" >> .env
echo "N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env

Ajoutez maintenant les variables restantes :

cat >> .env << 'EOF'
# PostgreSQL
POSTGRES_USER=n8n
POSTGRES_DB=n8n

# n8n
N8N_VERSION=2.12.3
N8N_HOST=localhost
N8N_PORT=5678
N8N_PROTOCOL=http
N8N_DIAGNOSTICS_ENABLED=false
GENERIC_TIMEZONE=UTC
EOF

Verrouillez les permissions du fichier. Seul votre utilisateur doit pouvoir le lire :

chmod 600 .env

Vérification :

ls -la .env

Vous devriez voir -rw-------. Aucun autre utilisateur sur le serveur ne peut lire votre mot de passe de base de données ni votre clé de chiffrement.

Comment générer et sauvegarder la clé de chiffrement n8n ?

La N8N_ENCRYPTION_KEY a été générée ci-dessus avec openssl rand -hex 32. Cela produit une clé aléatoire de 32 octets (64 caractères hexadécimaux). n8n utilise cette clé pour chiffrer tous les identifiants que vous stockez : clés API, tokens OAuth, mots de passe de bases de données dans les workflows. Si vous perdez cette clé, tous les identifiants stockés deviennent définitivement illisibles. Il n'existe aucun mécanisme de récupération.

Sauvegardez la clé de chiffrement maintenant. Copiez-la dans un gestionnaire de mots de passe ou un coffre-fort hors ligne :

grep N8N_ENCRYPTION_KEY .env

Stockez le résultat dans un endroit sûr en dehors de ce serveur. Faites-le avant d'ajouter votre premier identifiant dans n8n.

Référence des variables d'environnement

Variable Rôle Exemple de valeur
POSTGRES_USER Nom du superutilisateur PostgreSQL n8n
POSTGRES_PASSWORD Mot de passe du superutilisateur PostgreSQL (généré, 32+ caractères)
POSTGRES_DB Nom de la base de données n8n
N8N_VERSION Tag d'image n8n figé 2.12.3
N8N_ENCRYPTION_KEY Chiffre les identifiants stockés (généré, 64 caractères hex)
N8N_HOST Hôte pour l'interface n8n localhost
N8N_PORT Port pour l'interface n8n 5678
N8N_PROTOCOL HTTP ou HTTPS http
N8N_DIAGNOSTICS_ENABLED Envoi de télémétrie à n8n false
GENERIC_TIMEZONE Fuseau horaire pour les déclencheurs cron UTC

Écrire le docker-compose.yml

cat > docker-compose.yml << 'COMPOSE'
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "1.0"
    security_opt:
      - no-new-privileges:true
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  n8n:
    image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
    restart: unless-stopped
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_PORT: 5432
      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
      DB_POSTGRESDB_USER: ${POSTGRES_USER}
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_HOST: ${N8N_HOST}
      N8N_PORT: ${N8N_PORT}
      N8N_PROTOCOL: ${N8N_PROTOCOL}
      N8N_DIAGNOSTICS_ENABLED: ${N8N_DIAGNOSTICS_ENABLED}
      GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
    ports:
      - "127.0.0.1:5678:5678"
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: "2.0"
    security_opt:
      - no-new-privileges:true
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

volumes:
  postgres_data:
  n8n_data:
COMPOSE

Quelques points à noter dans ce fichier :

Pas de clé version:. Docker Compose V2 l'ignore. Tous les tutoriels concurrents incluent encore version: '3.7' ou version: '3.8'. La spécification Compose a déprécié ce champ. L'inclure produit un avertissement sur les versions actuelles de Docker.

Port lié à 127.0.0.1. La ligne "127.0.0.1:5678:5678" restreint n8n à localhost. C'est une exigence de sécurité, pas une préférence. Les mappings de ports Docker contournent entièrement iptables et les règles UFW. Si vous écrivez 5678:5678 sans le préfixe 127.0.0.1, n8n est accessible depuis internet même si votre pare-feu bloque le port 5678. Un reverse proxy sur la même machine transférera le trafic vers localhost:5678 une fois configuré.

security_opt: no-new-privileges:true empêche les processus à l'intérieur du conteneur d'acquérir des privilèges supplémentaires via les binaires setuid ou setgid. C'est une mesure de défense en profondeur contre les attaques d'évasion de conteneur.

Rotation des logs. Le bloc logging limite le log JSON de chaque conteneur à 3 fichiers de 10 Mo chacun (30 Mo max par service). Sans cela, les logs Docker grossissent jusqu'à remplir votre disque. Sur un VPS avec un stockage limité, c'est important.

Health checks sur les deux services. PostgreSQL utilise pg_isready. n8n utilise son endpoint /healthz. La condition depends_on garantit que n8n ne démarre qu'après que PostgreSQL a passé son health check.

Limites de ressources. PostgreSQL obtient 512 Mo de RAM et 1 CPU. n8n obtient 2 Go de RAM et 2 CPUs. Ces valeurs fonctionnent bien sur un VPS de 4 à 8 Go. Ajustez selon la taille de votre serveur et la complexité de vos workflows.

Volumes nommés. postgres_data et n8n_data sont des volumes nommés gérés par Docker. Docker gère automatiquement la propriété et les permissions à l'intérieur du volume. Pas besoin de créer des répertoires sur l'hôte ni de corriger les permissions manuellement.

restart: unless-stopped au lieu de restart: always. Les deux redémarrent après un crash, mais unless-stopped respecte les commandes manuelles docker compose stop. Avec restart: always, un conteneur arrêté manuellement redémarre si le daemon Docker redémarre (par exemple après une mise à jour système).

Démarrer la stack

cd ~/n8n
docker compose up -d

Suivez les logs pendant le premier démarrage :

docker compose logs -f

Attendez de voir n8n afficher une ligne contenant n8n ready on. Appuyez sur Ctrl+C pour quitter le visualiseur de logs.

Vérifier l'installation

Vérifiez que les deux conteneurs tournent et sont sains :

docker compose ps

Sortie attendue :

NAME       IMAGE                                  ...  STATUS                    PORTS
n8n-n8n-1       docker.n8n.io/n8nio/n8n:2.12.3   ...  Up X minutes (healthy)    127.0.0.1:5678->5678/tcp
n8n-postgres-1  postgres:16-alpine                ...  Up X minutes (healthy)

Ouvrez l'oeil : les deux conteneurs affichent (healthy) dans la colonne STATUS. Cela confirme que les health checks passent. Si vous voyez (health: starting), attendez 30 secondes et vérifiez à nouveau.

Testez l'API n8n depuis le serveur :

curl -s http://localhost:5678/healthz

Sortie attendue :

{"status":"ok"}

Vérifiez que le port n'écoute que sur localhost, pas sur toutes les interfaces :

ss -tlnp | grep 5678

Vous devriez voir 127.0.0.1:5678 dans la sortie. Si vous voyez 0.0.0.0:5678, votre binding de port est incorrect. Arrêtez la stack, corrigez la ligne ports dans docker-compose.yml et redémarrez.

Comment créer le compte propriétaire n8n ?

Ouvrez un tunnel SSH depuis votre machine locale pour accéder à n8n via votre navigateur :

ssh -L 5678:127.0.0.1:5678 your-user@your-server-ip

Ouvrez ensuite http://localhost:5678 dans votre navigateur. n8n affiche un écran de configuration au premier accès. Créez votre compte propriétaire avec un mot de passe robuste. Ce compte dispose d'un accès administrateur complet à n8n.

Après avoir créé le compte, fermez le tunnel SSH. Ne laissez pas le port 5678 tunnelisé plus longtemps que nécessaire. Mettez en place un reverse proxy avec SSL pour l'accès régulier. Voir .

Comment vérifier que n8n fonctionne correctement ?

Après avoir créé votre compte et fermé le tunnel SSH, lancez une dernière série de vérifications depuis le serveur.

Vérifiez la santé des conteneurs :

docker compose ps --format "table {{.Name}}\t{{.Status}}"

Les deux services doivent afficher (healthy).

Vérifiez les logs n8n pour des erreurs :

docker compose logs n8n --tail 20

Cherchez les lignes ERROR. Un démarrage propre affiche les messages de migration de base de données suivis de n8n ready on.

Vérifiez les logs PostgreSQL :

docker compose logs postgres --tail 10

Vous devriez voir database system is ready to accept connections.

Vérifiez l'utilisation disque de vos volumes Docker :

docker system df -v | grep -E "n8n|postgres"

Cela vous indique l'espace utilisé par n8n et PostgreSQL. Vérifiez régulièrement sur les instances VPS avec un stockage limité.

Un problème ?

Le conteneur s'arrête immédiatement. Vérifiez les logs avec docker compose logs n8n. Causes fréquentes : fichier .env manquant, mauvais mot de passe PostgreSQL, ou la clé de chiffrement contient des caractères spéciaux qui cassent l'expansion shell. Régénérez votre .env si nécessaire.

Erreurs de permission. Le conteneur n8n tourne sous l'UID 1000. Si vous passez des volumes nommés aux bind mounts, assurez-vous que le répertoire hôte appartient à l'UID 1000 : sudo chown -R 1000:1000 ./n8n_data.

Health check en échec. n8n a besoin de 20 à 30 secondes pour démarrer lors du premier lancement pendant qu'il exécute les migrations de base de données. Si les health checks échouent, vérifiez docker compose logs n8n pour des erreurs de migration. Le paramètre start_period: 30s donne du temps à n8n avant que les health checks ne commencent.

Impossible de se connecter à n8n. Le port est lié à localhost. Vous ne pouvez pas y accéder depuis une autre machine sans tunnel SSH ou reverse proxy. C'est intentionnel.

Clé de chiffrement perdue. Si vous avez perdu N8N_ENCRYPTION_KEY et que n8n a stocké des identifiants, ces identifiants sont perdus. Il n'y a aucune récupération possible. C'est pourquoi l'étape de sauvegarde existe.

Que faire après l'installation de n8n ?

Cette installation vous donne une instance n8n fonctionnelle accessible uniquement depuis le serveur lui-même. Pour une utilisation en production, trois éléments supplémentaires sont nécessaires :

  1. Reverse proxy avec SSL. Configurez Nginx ou Caddy devant n8n avec un certificat TLS. Cela vous donne un accès HTTPS avec un nom de domaine. Voir .

  2. Sauvegardes. Planifiez des sauvegardes automatisées de la base PostgreSQL et de la clé de chiffrement n8n. Voir .

  3. Mises à jour. Pour mettre à jour n8n, changez N8N_VERSION dans .env vers la nouvelle version, puis lancez docker compose up -d. Docker télécharge la nouvelle image et recrée le conteneur. Lisez toujours les notes de version n8n avant de mettre à jour.

Pour le guide parent couvrant les options d'automatisation de workflows sur VPS, voir .

Pour les fondamentaux de Docker Compose et la gestion de plusieurs services, voir Docker Compose pour déploiements multi-services sur VPS.


Copyright 2026 Virtua.Cloud. Tous droits réservés. Ce contenu est une création originale de l'équipe Virtua.Cloud. Toute reproduction, republication ou redistribution sans autorisation écrite est interdite.

Prêt à essayer ?

Déployez votre serveur en quelques secondes. Linux, Windows ou FreeBSD.

Voir les offres VPS