Installer des modules npm externes dans le node Code de n8n
Publié le 29 juillet 2026 · 5 min de lecture
Coller un extrait trouvé en ligne dans un node Code n8n, avec un require('axios') ou un import dayjs from 'dayjs', produit presque toujours la même erreur : Cannot find module 'axios'. Ce n'est pas un bug — c'est une restriction volontaire, et la lever correctement demande de comprendre deux variables d'environnement, une nuance liée aux Task Runners, et un vrai arbitrage de sécurité avant de taper NODE_FUNCTION_ALLOW_EXTERNAL=*.
Pourquoi n8n bloque les imports par défaut
Le node Code exécute du JavaScript (ou du Python) arbitraire fourni par l'utilisateur d'un workflow. Sur une instance qui manipule des credentials API, des données clients et parfois des webhooks exposés publiquement, autoriser sans restriction require('fs'), require('child_process') ou n'importe quel package npm reviendrait à donner un accès système complet à quiconque peut éditer un workflow. n8n adopte donc une posture par défaut restrictive : ni modules Node.js intégrés ni modules npm externes ne sont accessibles depuis le node Code, sauf autorisation explicite.
Deux variables distinctes, pour deux catégories de modules
n8n distingue les modules intégrés à Node.js (comme crypto, path ou querystring) des modules externes installés via npm (comme axios, lodash ou dayjs) :
NODE_FUNCTION_ALLOW_BUILTIN— liste, séparée par des virgules, des modules Node.js intégrés autorisés. Exemple :NODE_FUNCTION_ALLOW_BUILTIN=crypto,querystring.NODE_FUNCTION_ALLOW_EXTERNAL— liste, séparée par des virgules, des packages npm externes autorisés, à condition qu'ils soient physiquement présents dans lenode_modulesde l'instance. Exemple :NODE_FUNCTION_ALLOW_EXTERNAL=axios,lodash,dayjs.
Les deux acceptent aussi un astérisque (NODE_FUNCTION_ALLOW_EXTERNAL=*) pour tout autoriser d'un coup — une option pratique en développement, à manier avec précaution en production, comme détaillé plus bas. Dans un docker-compose.yml, cela s'ajoute simplement au bloc environment du service n8n :
environment:
- NODE_FUNCTION_ALLOW_BUILTIN=crypto
- NODE_FUNCTION_ALLOW_EXTERNAL=axios,dayjs
Un redémarrage du conteneur suffit à appliquer le changement — pas besoin de relancer un workflow ou de rouvrir le node Code pour que la nouvelle liste soit prise en compte.
Autoriser un module ne suffit pas s'il n'est pas installé
NODE_FUNCTION_ALLOW_EXTERNAL lève une interdiction, il n'installe rien. Si le package ne figure pas déjà dans le node_modules embarqué par l'image officielle n8n (qui inclut par défaut quelques utilitaires courants comme moment ou lodash), il faut l'y ajouter physiquement :
- Solution rapide, non persistante :
docker exec -it <conteneur> npm install axios— fonctionne immédiatement, mais le package disparaît au prochain redéploiement du conteneur si celui-ci n'est pas monté sur un volume dédié. - Solution recommandée en production : construire une image Docker personnalisée qui étend l'image officielle avec un
RUN npm installà la construction. Le package survit alors à chaque redéploiement, exactement comme les credentials survivent grâce aux sauvegardes PostgreSQL et non à un mécanisme distinct.
Si votre instance utilise des Task Runners
Sur les instances plus récentes, l'exécution du node Code peut être déportée vers un processus Task Runner séparé du processus principal n8n — une architecture qui isole le code utilisateur et facilite la montée en charge en mode queue. Le piège classique : quand les Task Runners sont actifs, les variables NODE_FUNCTION_ALLOW_BUILTIN et NODE_FUNCTION_ALLOW_EXTERNAL doivent être définies sur le processus du runner, pas sur le processus principal n8n. Les poser uniquement sur le service n8n de votre docker-compose.yml n'a alors aucun effet : le module reste introuvable, et rien dans l'interface n'indique clairement pourquoi, puisque l'instance principale démarre normalement. Si l'erreur Cannot find module persiste après avoir vérifié la syntaxe des variables, le premier réflexe est de contrôler où tourne réellement l'exécution du node Code — processus principal ou runner externe — avant de re-vérifier le placement de la configuration.
Le vrai risque de l'astérisque
Poser NODE_FUNCTION_ALLOW_EXTERNAL=* fait disparaître le problème une fois pour toutes — et c'est justement ce qui en fait une mauvaise habitude sur une instance de production. Une étude de référence de Zimmermann, Staicu, Tenny et Pradel, présentée au USENIX Security Symposium en 2019, a quantifié ce risque à l'échelle de l'écosystème npm : elle montre qu'un nombre restreint de mainteneurs et de packages très dépendus concentrent un risque de sécurité disproportionné, une seule dépendance compromise pouvant se propager, de façon transitive, à des centaines de milliers de projets en aval (Zimmermann et al., 2019, « Small World with High Risks » — Google Scholar). Sur une instance n8n qui manipule des clés API et des données métier, autoriser tout package présent dans node_modules — y compris ceux qu'un futur npm install ajoutera sans revue — revient à étendre cette surface d'attaque à chaque nouvelle dépendance installée par erreur ou par un collaborateur pressé. Une liste explicite (axios,dayjs, pas *) coûte quelques secondes de plus à chaque nouveau besoin et reste la pratique la plus sûre dès qu'une instance sort du cadre d'un test personnel.
Avant d'installer un module, vérifier qu'il est vraiment nécessaire
Une bonne partie des besoins qui poussent vers require() ont déjà une solution native dans n8n, sans toucher à la configuration du serveur :
- Formatage de dates : le node Code et les expressions intègrent déjà Luxon, qui couvre la quasi-totalité des usages qui poussent normalement vers
dayjsoumoment. - Appeler une API tierce : le node HTTP Request fait le travail d'un SDK HTTP comme
axios, avec retry et gestion des credentials intégrés — sans dépendance supplémentaire à maintenir. - Logique réutilisable et complexe : un sub-workflow ou un node communautaire packagent souvent proprement ce qu'un module npm générique ferait de façon plus fragile dans un node Code isolé.
Le pipeline d'ingestion PDF du Pack Assistant RAG (119 €) illustre ce principe : le découpage des documents avant vectorisation passe par le node Text Splitter natif de n8n plutôt que par une librairie de chunking installée à la main — une dépendance en moins à sécuriser, pour un résultat équivalent sur la majorité des documents texte.
En résumé
NODE_FUNCTION_ALLOW_BUILTIN et NODE_FUNCTION_ALLOW_EXTERNAL débloquent le node Code, à condition d'être définies sur le bon processus — le principal ou le Task Runner selon votre configuration — et le package doit être physiquement présent dans node_modules, ce qui suppose une image personnalisée pour tenir dans la durée. Réservez l'astérisque aux instances de test, préférez une liste explicite en production, et avant d'ajouter une dépendance, vérifiez qu'un node HTTP Request ou une expression Luxon ne suffit pas déjà. Les packs FlowKit suivent cette même logique : minimiser les dépendances externes pour des workflows plus simples à auditer et à maintenir dans la durée.
FAQ
Questions fréquentes
NODE_FUNCTION_ALLOW_EXTERNAL fonctionne-t-il sur n8n Cloud ?
Non. Ces variables d'environnement ne s'appliquent qu'à une instance self-hosted, où vous contrôlez le processus n8n (ou celui du Task Runner). Sur n8n Cloud, le node Code reste limité aux modules intégrés autorisés par défaut et à un sous-ensemble de librairies déjà embarquées : impossible d'ajouter un package tiers arbitraire.
Comment savoir si mon instance utilise les Task Runners ?
Vérifiez la variable N8N_RUNNERS_ENABLED dans votre configuration, ou regardez les logs au démarrage : une instance avec Task Runners actifs affiche l'établissement d'une connexion entre le processus principal et un processus runner séparé. Si vous ne l'avez jamais configuré explicitement, votre instance tourne probablement encore en exécution classique, dans le processus principal.
Comment installer un package qui n'existe pas déjà dans l'image n8n ?
Il faut l'ajouter physiquement au dossier node_modules du conteneur : soit via un docker exec ponctuel (non persistant après un redémarrage sans volume dédié), soit — solution recommandée en production — via une image Docker personnalisée qui étend l'image officielle n8n avec un RUN npm install à la construction, garantissant que le package survit aux redéploiements.
Bundle FlowKit Complet
269 €