n8n sur un VPS : sans limite d'exécutions

L'édition communautaire de n8n ne compte pas les exécutions : la limite, c'est votre machine. Nous l'avons mesurée sur une Nano, avec un vrai flux webhook, calcul et requête HTTP, puis couvert la sauvegarde de la clé de chiffrement, les mises à jour et ce que permet la licence.

Trois nœuds reliés en chaîne, un webhook, un calcul et une requête HTTP, avec une file d'appels qui arrive par la gauche

n8n relie vos outils entre eux : un formulaire qui crée une fiche client, une commande qui part vers la comptabilité, une alerte qui arrive dans un salon de discussion. Les formules hébergées par n8n se paient au nombre d'exécutions par mois (2 500 sur la plus petite, d'après sa page de tarifs en novembre 2026). L'édition communautaire, elle, ne compte rien : sur votre propre serveur, la seule limite est la machine.

Nous avons mesuré cette limite à Montréal : notre image n8n, une installation à la main avec Docker Compose, un vrai flux (webhook, calcul, requête HTTP) et des milliers d'appels. Puis la sauvegarde, les mises à jour et la licence.

1. Quelle formule choisir

Au repos, n8n occupait 373 Mo de mémoire et Caddy une vingtaine ; sous charge, n8n n'a jamais dépassé 1 023 Mo. Une Nano (1 vCPU, 2 Go) suffit pour démarrer, sans plantage observé.

Le processeur limite avant la mémoire (section 5). Nous n'avons pas testé de flux qui traitent des fichiers (PDF, images, gros exports CSV) : pour ceux-là, prévoyez plus de mémoire. Pour un essai, prenez une Nano à l'heure (0,018 CAD) et détruisez-la ensuite.

2. Déployer avec notre image n8n

Le catalogue propose une image n8n, disponible dès la Nano. C'est une Ubuntu 24.04 avec Docker, où n8n tourne derrière Caddy. Chaque VM reçoit un nom de domaine (de la forme vm-xxxxxxxx.ffxf.zone) : au premier démarrage, Caddy obtient un certificat Let's Encrypt pour ce nom, et n8n répond en HTTPS sur https://domaine-de-votre-vm. Dans notre essai, le certificat était en place moins de deux minutes après la commande. Tout se trouve dans /opt/n8n : compose.yml, .env et Caddyfile. L'utilisateur SSH est ubuntu.

Deux choses à faire tout de suite. D'abord, créez le compte propriétaire immédiatement : la première personne qui remplit l'écran d'accueil devient propriétaire de l'instance. Les certificats sont publiés dans des journaux publics, et un robot d'analyse a visité notre VM une seconde après l'émission du sien.

Ensuite, mettez n8n à jour. L'image contient la version tirée au moment de sa construction : lors de notre essai, la 2.35.3, alors que la version stable du jour était la 2.46.4. Nous l'avons refaite depuis, mais l'écart revient à chaque nouvelle version de n8n. Le fichier suit l'étiquette latest, donc il suffit de tirer la nouvelle image :

bash
cd /opt/n8n
sudo docker compose pull
sudo docker compose up -d
sudo docker compose exec n8n n8n --version

Pour votre propre domaine, faites pointer ses enregistrements A et AAAA vers la machine, remplacez le nom de la VM dans le Caddyfile et dans WEBHOOK_URL (fichier .env), puis relancez avec sudo docker compose up -d.

3. Installer à la main avec Docker Compose

L'installation manuelle vous laisse choisir la version et fixer la clé de chiffrement vous-même. Nous l'avons faite sur une Nano avec l'image Docker du catalogue (voir Docker sur un VPS pour partir d'une Ubuntu nue). Remplacez DOMAIN par le nom de votre VM ou votre domaine :

bash
sudo mkdir -p /opt/n8n && cd /opt/n8n
DOMAIN=vm-xxxxxxxx.ffxf.zone
printf 'DOMAIN=%s\nN8N_ENCRYPTION_KEY=%s\n' "$DOMAIN" "$(openssl rand -hex 32)" | sudo tee .env >/dev/null
sudo chmod 600 .env
printf '%s {\n\treverse_proxy n8n:5678\n}\n' "$DOMAIN" | sudo tee Caddyfile

Puis le fichier compose.yml :

yaml
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:2.46.4
    restart: unless-stopped
    environment:
      - N8N_HOST=${DOMAIN}
      - N8N_PROTOCOL=https
      - N8N_PROXY_HOPS=1
      - WEBHOOK_URL=https://${DOMAIN}/
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - GENERIC_TIMEZONE=America/Toronto
      - TZ=America/Toronto
      - EXECUTIONS_DATA_MAX_AGE=168
      - EXECUTIONS_DATA_PRUNE_MAX_COUNT=20000
    volumes:
      - n8n_data:/home/node/.n8n
  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
volumes:
  n8n_data:
  caddy_data:
bash
sudo docker compose up -d

Téléchargement et premier démarrage : 1 min 10 s sur la Nano. Les réglages notables :

  • WEBHOOK_URL : sans elle, n8n affiche des adresses de webhook en http://localhost:5678, inutilisables de l'extérieur.
  • N8N_PROXY_HOPS=1 : n8n lit la vraie adresse du client derrière Caddy.
  • GENERIC_TIMEZONE : le fuseau des déclencheurs planifiés. Sans lui, un flux prévu « tous les jours à 8 h » part à l'heure de New York, le défaut de n8n.
  • EXECUTIONS_DATA_MAX_AGE et EXECUTIONS_DATA_PRUNE_MAX_COUNT : par défaut, n8n garde l'historique 14 jours et 10 000 entrées ; ici, 7 jours et 20 000. Avec SQLite, l'espace libéré est réutilisé mais pas rendu au disque.

Caddy obtient le certificat seul si les ports 80 et 443 sont ouverts. Avec Nginx (voir notre guide Nginx et HTTPS), transmettez les en-têtes Upgrade et Connection : l'éditeur utilise une connexion WebSocket.

4. Un flux de test : webhook, calcul, requête HTTP

Le flux compte quatre nœuds :

  • Webhook : reçoit un POST sur /webhook/commande et répond avec la sortie du dernier nœud ;
  • Calcul (nœud Code) : additionne les lignes de la commande et nettoie l'adresse du client ;
  • Envoi (nœud HTTP Request) : transmet le résultat en JSON à un récepteur HTTPS sur une autre VM ;
  • Réponse (nœud Code) : renvoie le calcul et confirme l'envoi.

Le code du nœud Calcul :

bash
const b = $input.first().json.body;
const lignes = b.lignes || [];
const total = lignes.reduce((s, l) => s + l.qte * l.prix, 0);
return [{ json: {
  commande: b.id,
  client: String(b.client || '').trim().toLowerCase(),
  nb_lignes: lignes.length,
  total: Math.round(total * 100) / 100,
  recu_le: new Date().toISOString(),
} }];

Pour le vérifier :

bash
curl -s -X POST https://vm-xxxxxxxx.ffxf.zone/webhook/commande \
  -H 'Content-Type: application/json' \
  -d '{"id":"C-1042","client":"  Marie@Exemple.ca ","lignes":[{"qte":2,"prix":12.5},{"qte":1,"prix":30}]}'
bash
{"commande":"C-1042","client":"marie@exemple.ca","nb_lignes":2,"total":55,"recu_le":"2026-11-03T15:32:04.199Z","transmis":true}

Aller-retour complet, appel HTTPS sortant compris : 0,16 s en médiane sur 100 appels envoyés un à la fois.

5. Au repos et sous 1 000 appels

Les appels partaient d'une autre VM du même centre de données, avec hey ; mémoire et processeur étaient relevés chaque seconde sur la machine n8n.

bash
hey -n 1000 -c 10 -m POST -T application/json -D body.json \
  https://vm-xxxxxxxx.ffxf.zone/webhook/commande

Les 3 100 appels ont tous reçu une réponse 200, sans erreur ni redémarrage. Mais le débit plafonne autour de 5 exécutions par seconde : pendant la charge, le vCPU était occupé à plus de 80 %, presque entièrement par le processus principal de n8n. Envoyer plus d'appels à la fois ne va pas plus vite, cela allonge la file : à 50 simultanés, chaque appel attendait 9 à 12 secondes.

Un flux réduit au seul webhook, qui répond tout de suite, plafonne à 6,8 exécutions par seconde ; webhook et nœud Code sans requête HTTP, à 8,5 (300 appels, 10 simultanés). Couper l'enregistrement des exécutions réussies (EXECUTIONS_DATA_SAVE_ON_SUCCESS=none) n'a rien changé de mesurable. Le coût tient surtout à n8n lui-même, à chaque exécution, quel que soit le flux.

À 5 par seconde, une Nano encaisse en théorie 18 000 exécutions à l'heure, bien plus que ce que demandent la plupart des automatisations d'une PME. Elle convient mal, en revanche, à un webhook public qui reçoit des rafales : les appels s'empilent et un expéditeur pressé finira par abandonner. Nous n'avons pas pu mesurer la Starter : comme le processus principal fait presque tout le travail, ne comptez pas sur un second vCPU pour doubler le débit avant de l'avoir vérifié. Pour monter en charge, n8n documente le mode file d'attente, inclus dans l'édition communautaire, avec des workers séparés.

Côté disque, le dossier de données pesait 53 Mo après environ 3 000 exécutions enregistrées, journaux d'événements compris.

6. Sauvegardes et clé de chiffrement

Tout l'état de n8n vit dans le volume monté sur /home/node/.n8n : la base SQLite (flux, utilisateurs, historique), et le fichier config qui contient la clé de chiffrement. n8n chiffre vos identifiants (jetons d'API, mots de passe) avec cette clé avant de les écrire dans la base. Une base sans sa clé ne sert plus à rien pour les identifiants.

Avec notre image, la variable N8N_ENCRYPTION_KEY n'est pas définie : n8n a généré la clé au premier démarrage et l'a rangée dans config, à l'intérieur du volume. Avec l'installation manuelle ci-dessus, la clé est aussi dans /opt/n8n/.env. Gardez-en une copie ailleurs que sur le serveur, dans un gestionnaire de mots de passe par exemple.

La documentation de n8n demande d'arrêter n8n avant de copier le dossier quand on utilise SQLite. Sur la Nano, l'arrêt, l'archive et le redémarrage ont pris 5,7 s :

bash
cd /opt/n8n
sudo docker compose stop n8n
sudo docker run --rm -v n8n_n8n_data:/data:ro -v /opt/n8n:/backup alpine \
  tar czf /backup/n8n-$(date +%F).tar.gz -C /data .
sudo docker compose start n8n

Copiez ensuite l'archive (3,3 Mo dans notre cas) et le fichier .env hors de la machine. Nous avons restauré cette archive sur l'autre VM : le flux était publié, le webhook répondait et l'identifiant de test se lisait. Pour restaurer :

bash
sudo docker compose stop n8n
sudo docker run --rm -v n8n_n8n_data:/data -v /chemin/archive:/backup alpine \
  sh -c "rm -rf /data/* && tar xzf /backup/n8n-AAAA-MM-JJ.tar.gz -C /data"
sudo docker compose start n8n

Le piège : si N8N_ENCRYPTION_KEY est définie et ne correspond pas à la clé du fichier config restauré, n8n refuse de démarrer et redémarre en boucle avec ce message :

bash
Error: Mismatching encryption keys. The encryption key in the settings file /home/node/.n8n/config does not match the N8N_ENCRYPTION_KEY env var. Please make sure both keys match.

Les exports n8n export:workflow --backup et n8n export:credentials --backup servent à déplacer des flux, mais n'incluent ni les utilisateurs, ni l'historique, ni la clé : ils ne remplacent pas la copie du volume. Les sauvegardes de machine de la console ajoutent une seconde copie (7 manuelles incluses, automatiques à 3 CAD par mois).

7. Les mises à jour

n8n publie une version mineure presque chaque semaine. Sa documentation conseille de mettre à jour au moins une fois par mois, de lire les notes de version et de faire une sauvegarde complète avant. Avec la version fixée dans compose.yml :

bash
cd /opt/n8n
sudo sed -i 's|n8nio/n8n:2.46.4|n8nio/n8n:NOUVELLE_VERSION|' compose.yml
sudo docker compose pull
sudo docker compose up -d

Notre passage de 2.35.3 à 2.46.4 a appliqué les migrations de la base seul. Le conteneur répondait à /healthz 13 secondes après le redémarrage, mais les webhooks ont renvoyé une erreur 404 pendant encore 25 secondes au plus, le temps que n8n réactive les flux publiés. Prévoyez ce trou, ou faites la mise à jour à une heure creuse.

Le 3 novembre 2026, stable pointait vers la 2.46.4, mais une 3.1.0 était déjà publiée. Avant un saut de version majeure, essayez sur une copie : une VM à l'heure restaurée depuis votre archive.

8. Licence et limites

n8n n'est pas un logiciel libre au sens de l'OSI. Il est publié sous la Sustainable Use License, que n8n classe dans le modèle « fair-code » : code source disponible, usage gratuit, mais usage commercial encadré. D'après la FAQ de la licence :

  • autorisé : automatiser votre propre entreprise, des projets personnels, construire des flux pour vos clients sur votre instance tant qu'ils ne peuvent pas les créer ni les modifier, facturer la création, l'installation et la maintenance de flux ;
  • interdit sans accord commercial : héberger n8n comme service où vos clients construisent leurs propres flux, les laisser configurer la logique par votre interface, par l'API ou par un agent IA, revendre n8n sous votre marque.

L'édition communautaire comprend presque tout. Il lui manque, selon la documentation : les projets et le partage de flux et d'identifiants entre utilisateurs, la connexion unique (SAML, LDAP), les environnements et le contrôle de version par Git, les secrets externes, les variables personnalisées, le stockage externe des fichiers, l'envoi des journaux vers un outil externe et le mode multi-principal. Une inscription gratuite par courriel débloque les dossiers, le débogage dans l'éditeur et les données d'exécution personnalisées.

Enfin, SQLite convient à une instance seule ; le mode file d'attente (queue mode), avec plusieurs workers, demande PostgreSQL et Redis. L'administration du serveur vous revient (voir notre guide pour sécuriser Ubuntu). Les autres images du catalogue sont sur la page Images.

Des vignettes de photos qui montent d'un téléphone vers un serveur où elles se rangent en grille

Immich : remplacer Google Photos sur votre serveur

Sauvegarde du téléphone, visages, recherche par le contenu : Immich fait l'essentiel de Google Photos, sur une machine que vous administrez au Canada. Quelle offre prendre, notre image ou une installation à la main, les sauvegardes 3-2-1 et les limites.

Lire l'article 7 min de lecture

Un panneau d'applications dans une fenêtre, une tuile en cours de déploiement

VPS Easypanel : préinstallé, prêt en deux minutes

Easypanel rejoint le catalogue : un VPS livré avec le panneau Docker déjà installé, qui répond sur le port 3000 moins de deux minutes après la commande.

Lire l'article 4 min de lecture

Support & discussions

Questions techniques, retours d'incidents ou discussions d'infrastructure, l'équipe est présente sur Discord, Telegram, X, Instagram, Reddit et IRC.