Accueil / Blog / N8N 2.0 Env Vars Docker

N8N 2.0 : Variables d'Environnement et Réseau Docker - Guide Complet

Après la mise à jour vers N8N 2.0, vos workflows utilisant $env échouent ? Ce guide vous montre comment configurer un réseau Docker sécurisé pour les External Runners.

TL;DR

Après la mise à jour vers N8N 2.0, vos workflows utilisant $env.MA_VARIABLE échouent avec l'erreur "access to env vars denied". La cause : le mode External Runners exécute le code dans un container séparé qui n'a pas accès aux variables d'environnement du container N8N principal.

Solutions :

  1. Réseau Docker dédié + URL directe par nom de container (recommandé)
  2. Configuration du launcher pour autoriser les variables
  3. N8N Variables (fonctionnalité payante)

Note sécurité : Ne connectez PAS vos services au réseau interne N8N (infrastructure). Créez un réseau dédié pour la communication.

# ❌ Ne fonctionne plus avec external runners
{{ $env.API_URL }}/endpoint

# ✅ Solution : URL directe via nom de container Docker
http://mon-service:5001/endpoint

Le Problème : Variables d'Environnement Inaccessibles

Symptômes

Après la mise à jour vers N8N 2.0, vos workflows qui utilisaient des variables d'environnement via $env cessent de fonctionner :

Error: access to env vars denied
Erreur access to env vars denied dans N8N 2.0
L'erreur "access to env vars denied" avec les External Runners

Ou encore :

The connection cannot be established, this usually occurs due to an incorrect host (domain) value

Exemple de code qui ne fonctionne plus

// ❌ Expression N8N qui échoue en mode external runners
{{ $env.API_CALCULATEUR_URL ?? 'http://localhost:5001' }}/calculer

Pourquoi Ce Changement : External Runners

Architecture N8N 2.0

N8N 2.0 introduit les Task Runners externes pour améliorer la sécurité et l'isolation du code.

flowchart LR
    subgraph docker["Docker Host"]
        subgraph n8n["Container N8N"]
            n8n_ui["Interface UI"]
            n8n_api["API"]
            n8n_env["✅ $env vars"]
        end
        subgraph runners["Container Runners"]
            run_code["Exécute Code"]
            run_py["Python / JS"]
            run_env["❌ $env vars"]
        end
    end
    n8n <--> runners
            

Configuration typique docker-compose

services:
  n8n:
    image: n8nio/n8n:latest
    environment:
      N8N_RUNNERS_ENABLED: true
      N8N_RUNNERS_MODE: external  # ← Le code s'exécute ailleurs
      API_URL: http://localhost:5001  # ← Variable définie ici

  task-runners:
    image: n8nio/runners
    environment:
      # API_URL n'est PAS définie ici → $env.API_URL = undefined

Le problème expliqué

Élément Container N8N Container Runners
$env.API_URL ✅ Accessible Non accessible
Code Python/JS ❌ Non exécuté ici ✅ Exécuté ici
Interface UI
Résultat : L'expression $env.API_URL est évaluée dans le container runners qui ne possède pas cette variable.

Solution 1 : Réseau Docker Dédié (Recommandée)

Considérations de Sécurité

Avant de connecter vos services au réseau N8N, comprenez les implications de sécurité :

Approche Risque Isolation
Naïve : Tout sur le même réseau Élevé Votre service peut accéder à PostgreSQL, Redis, etc.
Best Practice : Réseau dédié Faible Seule la communication N8N ↔ Service est possible
Principe de moindre privilège : Un container ne devrait voir que les réseaux strictement nécessaires à son fonctionnement. (OWASP Container Security)

Le problème réseau initial

Si vos services tournent sur des réseaux Docker différents, ils ne peuvent pas communiquer par nom de container :

flowchart LR
    subgraph infra["reseau-infra"]
        n8n["n8n"]
        runners["runners"]
    end
    subgraph app["reseau-app"]
        service["mon-service :5001"]
    end
    n8n -.->|"❌ ÉCHEC"| service
            

Problèmes :

Approche Naïve (Non Recommandée)

❌ ÉVITEZ CECI : Connecter directement au réseau infrastructure

# ⚠️ DANGEREUX
docker network connect my-infrastructure_default mon-service

Problème : Votre service peut maintenant accéder à PostgreSQL, Redis, et tous les composants internes.

La solution : Réseau dédié pour la communication

Créez un réseau séparé uniquement pour la communication N8N ↔ Services externes :

# 1. Créer le réseau dédié
docker network create n8n-services-net

# 2. Connecter N8N à ce nouveau réseau
docker network connect n8n-services-net n8n

# 3. Connecter votre service à ce réseau (PAS au réseau infrastructure)
docker network connect n8n-services-net mon-service

Résultat : Architecture sécurisée avec isolation

flowchart TB
    subgraph infra["infrastructure_default (interne)"]
        n8n1["n8n"]
        pg[("PostgreSQL")]
    end
    subgraph services["n8n-services-net (dédié)"]
        n8n2["n8n"]
        svc["mon-service :5001"]
    end
    n8n1 --- n8n2
    n8n2 <-->|"✅ OK"| svc
    svc x--x|"❌ Bloqué"| pg
            
Isolation : mon-service ne peut PAS accéder à PostgreSQL ✓

Étapes de mise en œuvre

Étape 1 : Créer le réseau dédié

# Créer un réseau spécifique pour la communication N8N ↔ Services
docker network create n8n-services-net

Étape 2 : Connecter N8N au nouveau réseau

# N8N doit être sur les 2 réseaux : infrastructure (interne) + services (externe)
docker network connect n8n-services-net n8n

Étape 3 : Connecter votre service au réseau dédié

# ✅ Correct : réseau dédié
docker network connect n8n-services-net mon-service

# ❌ Éviter : réseau infrastructure
# docker network connect my-infrastructure_default mon-service

Étape 4 : Vérifier l'isolation

# Vérifier que mon-service n'a PAS accès au réseau infrastructure
docker inspect mon-service --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'
# Attendu : n8n-services-net (PAS my-infrastructure_default)

# Vérifier que N8N est sur les 2 réseaux
docker inspect n8n --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'
# Attendu : my-infrastructure_default n8n-services-net

# Tester la connectivité depuis N8N
docker exec -it n8n curl http://mon-service:5001/health

Étape 5 : Modifier le workflow N8N

Remplacez l'expression $env par l'URL directe :

Avant Après
{{ $env.API_URL }}/endpoint http://mon-service:5001/endpoint
Requête HTTP réussie avec URL directe par nom de container
Succès : la requête HTTP fonctionne avec l'URL directe par nom de container

Solution 2 : Configurer le Launcher (Avancée)

Si vous devez absolument utiliser des variables d'environnement dans vos Code nodes, configurez le launcher des runners.

Étape 1 : Créer le fichier de configuration

Créez n8n-task-runners.json :

{
  "task-runners": [
    {
      "runner-type": "javascript",
      "allowed-env": [
        "API_URL",
        "DATABASE_URL",
        "SECRET_KEY"
      ]
    },
    {
      "runner-type": "python",
      "allowed-env": [
        "API_URL",
        "DATABASE_URL"
      ]
    }
  ]
}

Étape 2 : Monter le fichier dans le container

services:
  task-runners:
    image: n8nio/runners
    environment:
      - N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
      - N8N_RUNNERS_AUTH_TOKEN=your-secret-here
      - API_URL=http://mon-service:5001  # ← Définir ici aussi
    volumes:
      - ./n8n-task-runners.json:/etc/n8n-task-runners.json:ro
Note : Cette solution nécessite de définir les variables dans les deux containers ET de les autoriser dans le launcher.

Solution 3 : N8N Variables (Payante)

N8N propose une fonctionnalité "Variables" qui résout ce problème, mais elle nécessite une licence payante.

Accès

Settings → Variables → "Upgrade to unlock variables"
Écran N8N Variables montrant Upgrade to unlock variables
L'option Variables nécessite une licence N8N payante

Utilisation (si disponible)

// Dans les expressions
{{ $vars.API_URL }}

// Dans le code Python
_vars.API_URL

Tableau Comparatif des Solutions

Solution Complexité Coût Sécurité Recommandation
Réseau Docker dédié Moyenne Gratuit Haute Recommandée
Réseau partagé (naïf) Faible Gratuit Faible ❌ Non recommandé
Config Launcher Élevée Gratuit Moyenne Pour cas spécifiques
N8N Variables Faible Payant Haute Si licence disponible

Troubleshooting

Erreur : "access to env vars denied"

Cause : Utilisation de $env dans un workflow exécuté par external runners.

Solution : Remplacez {{ $env.API_URL }}/endpoint par une URL directe http://mon-service:5001/endpoint

Erreur : "The connection cannot be established"

Causes possibles :

  • Containers sur des réseaux Docker différents
  • host.docker.internal sur Linux/WSL
  • Service non démarré

Diagnostic :

# Vérifier les réseaux du container
docker inspect mon-service --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'

# Tester la connectivité depuis n8n
docker exec -it n8n ping mon-service
docker exec -it n8n curl http://mon-service:5001/health
Erreur : "host.docker.internal not found"

Cause : host.docker.internal ne fonctionne pas sur Linux/WSL.

Solution : Utiliser le nom du container Docker au lieu de host.docker.internal.

Le workflow fonctionne manuellement mais pas en production

Cause : Les tests manuels dans l'UI N8N peuvent utiliser un chemin d'exécution différent.

Vérification :

  • Assurez-vous que N8N_RUNNERS_MODE: external est bien configuré
  • Testez avec un webhook réel, pas juste le bouton "Execute"

Bonnes Pratiques

1. Éviter $env avec External Runners

// ❌ Éviter
{{ $env.SERVICE_URL }}/api

// ✅ Préférer
http://service-name:port/api

2. Documenter les URLs hardcodées

// URL du service calculateur
// Container: calculateur-app sur réseau dédié n8n-services-net
// Note: NE PAS connecter au réseau infrastructure pour isolation sécurité
http://calculateur-app:5001/calculer

3. Script de déploiement automatisé (sécurisé)

#!/bin/bash
# deploy.sh - Utilise un réseau dédié pour l'isolation

# Créer le réseau dédié si nécessaire
docker network create n8n-services-net 2>/dev/null || true

# Démarrer le container
docker-compose up -d

# Attendre que le container soit prêt
sleep 3

# Connecter N8N au réseau dédié (si pas déjà fait)
docker network connect n8n-services-net n8n 2>/dev/null || true

# Connecter le service au réseau dédié (PAS au réseau infrastructure)
docker network connect n8n-services-net mon-service 2>/dev/null || echo "Déjà connecté"

echo "Déploiement terminé avec isolation sécurisée"

4. Vérifier après chaque redémarrage

La connexion réseau est perdue après un docker-compose down. Ajoutez la reconnexion dans vos scripts.


FAQ

Pourquoi N8N 2.0 utilise-t-il des External Runners ?

Les External Runners améliorent la sécurité et l'isolation du code exécuté dans les Code nodes. Le code utilisateur s'exécute dans un container séparé avec des permissions limitées, protégeant le container N8N principal.

Puis-je désactiver les External Runners ?

Techniquement oui, en utilisant N8N_RUNNERS_MODE=internal, mais ce n'est pas recommandé pour des raisons de sécurité. Les futures versions de N8N pourraient supprimer cette option.

Les expressions N8N ($json, $now, etc.) fonctionnent-elles encore ?

Oui, les expressions standard de N8N fonctionnent. Seul l'accès aux variables d'environnement via $env est restreint dans les runners.

Dois-je reconnecter le réseau après chaque redémarrage ?

Oui, si vous utilisez docker-compose down. La connexion réseau externe n'est pas persistante. Incluez la commande docker network connect dans vos scripts de déploiement.

Pourquoi ne pas simplement connecter mon service au réseau infrastructure ?

C'est dangereux. En connectant votre service au réseau my-infrastructure_default, il peut accéder à :

  • PostgreSQL (port 5432) : lecture/écriture des données
  • Redis (si présent) : sessions, cache
  • Task Runners : potentielle escalade de privilèges

Solution sécurisée : Créez un réseau dédié n8n-services-net où seuls N8N et vos services peuvent communiquer, sans exposer les composants internes.


Checklist de Migration


Ressources


Conclusion

La migration vers N8N 2.0 avec External Runners introduit des restrictions sur l'accès aux variables d'environnement pour des raisons de sécurité. La solution la plus robuste est d'utiliser un réseau Docker dédié (pas le réseau infrastructure interne) et des URLs directes par nom de container.

Points clés à retenir :

  1. $env n'est pas accessible dans les External Runners par défaut
  2. Créez un réseau dédié pour la communication N8N ↔ Services externes
  3. Ne connectez jamais vos services au réseau infrastructure interne
  4. Utilisez les noms de containers comme hostnames
  5. Mettez à jour vos scripts de déploiement

Sécurité : Le principe de moindre privilège s'applique aussi aux réseaux Docker. Un service externe ne devrait jamais pouvoir accéder à votre base de données.

Besoin d'aide avec votre infrastructure Docker ?

Je peux vous accompagner dans la migration vers N8N 2.0 ou sécuriser votre architecture containers.

Discutons de votre projet