Expressions verstehen: $json, $node und items ohne Code mappen
Die größte n8n-Lernhürde erklärt: was Items, $json und $node bedeuten und wie Sie Werte per Drag-and-Drop ohne Code mappen.
n8n Task Runners führen Code-Nodes isoliert aus statt im Hauptprozess. So funktionieren interner und externer Modus.
Task Runners führen den JavaScript- und Python-Code aus dem Code-Node nicht mehr im Hauptprozess von n8n aus, sondern in einem getrennten Prozess oder Container. Damit kommt fehlerhafter oder fremder Code nicht mehr an Zugangsdaten, Verschlüsselungsschlüssel oder Umgebungsvariablen der Instanz.
Ab n8n 1.111.0 lässt sich der externe Modus produktiv betreiben. Dieser Artikel zeigt den Unterschied zu internen Runnern, eine lauffähige Compose-Datei, die Allowlist für Module und die Härtungsmaßnahmen aus der n8n-Dokumentation.
Task Runners sind ein Mechanismus, der Aufgaben getrennt vom Hauptprozess ausführt. n8n nutzt sie ausschließlich für den nutzergesteuerten Code aus dem Code-Node.
Drei Bestandteile arbeiten zusammen:
Bestandteil | Rolle | Wo er läuft
Bestandteil: Task Runner · Rolle: führt den Code tatsächlich aus · Wo er läuft: Kindprozess oder eigener Container
Bestandteil: Task Broker · Rolle: verteilt Aufgaben und koordiniert die Antworten · Wo er läuft: in der n8n-Hauptinstanz oder im Worker
Bestandteil: Task Requester · Rolle: fordert eine Ausführung an · Wo er läuft: der Code-Node im Workflow
Der Runner verbindet sich per WebSocket mit dem Broker. Der Broker gibt eine wartende Aufgabe heraus, der Runner liefert das Ergebnis zurück an den Requester.
Ohne Task Runner läuft der Code direkt in n8n. Wer dann einen Workflow bearbeiten darf, kann laut Dokumentation potenziell die Datenbank, den Verschlüsselungsschlüssel und alle gespeicherten Zugangsdaten auslesen.
Der interne Modus startet den Runner als Kindprozess mit derselben Benutzer- und Gruppen-ID wie n8n, der externe Modus startet ihn in einem eigenen Container. Nur der externe Modus gilt laut n8n als produktionstauglich.
Kriterium | Intern (`internal`) | Extern (`external`)
Kriterium: Standardeinstellung · Intern (internal): ja · Extern (external): nein
Kriterium: Prozessmodell · Intern (internal): Kindprozess von n8n · Extern (external): Sidecar-Container mit Launcher
Kriterium: Rechte des Codes · Intern (internal): gleiche uid und gid wie n8n · Extern (external): eigener Container, eigener Nutzer
Kriterium: Zugriff bei Sandbox-Ausbruch · Intern (internal): wie n8n, inklusive Zugangsdaten · Extern (external): auf den Runner-Container begrenzt
Kriterium: Zusätzliche Container · Intern (internal): keine · Extern (external): einer je Hauptinstanz und je Worker
Kriterium: Mindestversion · Intern (internal): seit Langem verfügbar · Extern (external): n8n 1.111.0
Kriterium: Empfehlung von n8n · Intern (internal): nur für isolierte Instanzen ohne sensible Daten · Extern (external): Produktion
Der interne Modus ist kein Sicherheitsgewinn, sondern ein Kompromiss. n8n nennt ihn ausdrücklich unsicher, weil der Runner auf demselben Host mit denselben Rechten läuft.
Sie ergänzen einen zweiten Container mit dem Image n8nio/runners und verbinden beide über ein gemeinsames Geheimnis. Die Version des Runner-Image muss exakt zur n8n-Version passen.
1services:2 n8n:3 image: n8nio/n8n:1.111.04 container_name: n8n-main5 environment:6 - N8N_RUNNERS_ENABLED=true7 - N8N_RUNNERS_MODE=external8 - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.09 - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN}10 - N8N_NATIVE_PYTHON_RUNNER=true11 ports:12 - "127.0.0.1:5678:5678"13 volumes:14 - n8n_data:/home/node/.n8n15
16 task-runners:17 image: n8nio/runners:1.111.018 container_name: n8n-runners19 environment:20 - N8N_RUNNERS_TASK_BROKER_URI=http://n8n-main:567921 - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN}22 depends_on:23 - n8n24
25volumes:26 n8n_data:N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0 ist Pflicht, sobald zwei Container im Spiel sind. Ohne diesen Wert lauscht der Broker nur auf 127.0.0.1 und der Sidecar erreicht ihn nie.
Das Token gehört in die .env-Datei neben der Compose-Datei, nicht in die Compose-Datei selbst. In n8n 1.x setzen Sie zusätzlich N8N_RUNNERS_ENABLED=true. Ab n8n 2.0 ist die Variable veraltet und überflüssig.
Standardmäßig keine. n8n blockiert im Code-Node sowohl Node.js-Bordmittel als auch Python-Standardbibliothek und Drittanbieter-Pakete, bis Sie sie ausdrücklich freigeben.
Im externen Modus setzen Sie diese Allowlists nicht als Container-Variablen, sondern in der Launcher-Konfiguration /etc/n8n-task-runners.json. Der Launcher reicht sie als env-overrides an den jeweiligen Runner weiter.
1{2 "task-runners": [3 {4 "runner-type": "javascript",5 "env-overrides": {6 "NODE_FUNCTION_ALLOW_BUILTIN": "crypto",7 "NODE_FUNCTION_ALLOW_EXTERNAL": "moment,uuid"8 }9 },10 {11 "runner-type": "python",12 "env-overrides": {13 "PYTHONPATH": "/opt/runners/task-runner-python",14 "N8N_RUNNERS_STDLIB_ALLOW": "json",15 "N8N_RUNNERS_EXTERNAL_ALLOW": "numpy,pandas"16 }17 }18 ]19}Die Datei binden Sie als Volume ein, etwa mit ./n8n-task-runners.json:/etc/n8n-task-runners.json. Drittanbieter-Pakete müssen zusätzlich im Image liegen. Dafür erweitern Sie n8nio/runners per eigenem Dockerfile.
Verzichten Sie auf den Platzhalter *. Er erlaubt sämtliche Module und hebt einen wesentlichen Teil der Absicherung wieder auf.
Die folgenden Variablen decken den Regelbetrieb ab. Alle Standardwerte stammen aus der Referenz zu den Task-Runner-Umgebungsvariablen.
Variable | Standard | Wirkung
Variable: N8N_RUNNERS_MODE · Standard: internal · Wirkung: Betriebsart, internal oder external
Variable: N8N_RUNNERS_AUTH_TOKEN · Standard: Zufallswert · Wirkung: gemeinsames Geheimnis zwischen Runner und Broker
Variable: N8N_RUNNERS_BROKER_PORT · Standard: 5679 · Wirkung: Port, auf dem der Broker Verbindungen annimmt
Variable: N8N_RUNNERS_BROKER_LISTEN_ADDRESS · Standard: 127.0.0.1 · Wirkung: Lauschadresse, im Mehrcontainer-Betrieb 0.0.0.0
Variable: N8N_RUNNERS_TASK_BROKER_URI · Standard: http://127.0.0.1:5679 · Wirkung: Adresse des Brokers aus Sicht des Runners
Variable: N8N_RUNNERS_MAX_CONCURRENCY · Standard: 5 · Wirkung: gleichzeitige Aufgaben je Runner
Variable: N8N_RUNNERS_TASK_TIMEOUT · Standard: 300 · Wirkung: Laufzeitgrenze je Aufgabe in Sekunden
Variable: N8N_RUNNERS_TASK_REQUEST_TIMEOUT · Standard: 60 · Wirkung: Wartezeit auf einen freien Runner in Sekunden
Variable: N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT · Standard: 15 · Wirkung: Leerlaufsekunden bis zum Herunterfahren des Runners
Variable: N8N_BLOCK_RUNNER_ENV_ACCESS · Standard: true · Wirkung: blockiert os.environ im Python-Code
Variable: GENERIC_TIMEZONE · Standard: America/New_York · Wirkung: Zeitzone im Runner, in Deutschland auf Europe/Berlin setzen
Eine Besonderheit betrifft Geheimnisse: Das Runner-Image unterstützt keine dateibasierte Konfiguration. Variablen mit dem Suffix _FILE werden dort nicht ausgewertet.
n8n nennt vier Maßnahmen über den externen Modus hinaus. Sie greifen unabhängig voneinander und lassen sich einzeln einführen.
Maßnahme | Umsetzung | Nutzen
Maßnahme: Distroless-Image · Umsetzung: Tag-Suffix -distroless, etwa 2.4.6-distroless · Nutzen: keine Shell, kein Paketmanager im Container
Maßnahme: Unprivilegierter Nutzer · Umsetzung: Runner als nobody mit UID und GID 65532 · Nutzen: kein Prozess mit Root-Rechten
Maßnahme: Schreibgeschütztes Dateisystem · Umsetzung: Root read-only, kleines emptyDir auf /tmp · Nutzen: Code kann keine Systemdateien ändern
Maßnahme: AppArmor-Profil · Umsetzung: Regel gegen /proc-Zugriffe (siehe unten) · Nutzen: verhindert das Auslesen von Umgebungsvariablen
Die AppArmor-Regel aus der Dokumentation lautet:
1audit deny @{PROC}/[0-9]*/{environ,mounts} rwl,Sie verweigert Lesen, Schreiben und Verlinken auf die Dateien environ und mounts je Prozess und protokolliert jeden Versuch. Ohne diese Regel kann Code im Container Umgebungsvariablen anderer Prozesse auslesen.
Der Umstieg lohnt sich für jede selbst gehostete Instanz, die echte Zugangsdaten speichert oder Workflows mehrerer Teams betreibt. Auf isolierten Testinstanzen mit reinen Beispieldaten ist der interne Modus ein vertretbarer Kompromiss.
Ehrlich gesagt kostet der externe Modus Betriebsaufwand. Sie betreiben einen zusätzlichen Container je Worker, pflegen zwei Image-Versionen im Gleichschritt und verwalten eigene Allowlists.
Diesen Aufwand sollten Sie trotzdem einplanen. n8n stuft N8N_RUNNERS_ENABLED ab Version 2.0 als veraltet ein, und der interne Modus bleibt dauerhaft als unsicher gekennzeichnet.
NordFlux richtet n8n-Instanzen inklusive Task-Runner-Absicherung ein und dokumentiert die Konfiguration nachvollziehbar. Mehr dazu auf der Seite zur n8n-Beratung.
Fünf Fehlerbilder treten beim Einrichten externer Task Runner besonders häufig auf.
Der Sidecar verbindet sich nicht, das Log meldet einen Verbindungsfehler zum Broker.
Ursache: N8N_RUNNERS_BROKER_LISTEN_ADDRESS steht auf dem Standard 127.0.0.1, der Broker nimmt nur lokale Verbindungen an. Lösung: Den Wert im n8n-Container auf 0.0.0.0 setzen. Quelle: Set up task runners.
Der Runner meldet einen Authentifizierungsfehler.
Ursache: Die beiden Container tragen unterschiedliche Werte in N8N_RUNNERS_AUTH_TOKEN, oder das Token fehlt im Sidecar. Lösung: Beide Container aus derselben Variable in der .env-Datei speisen. Quelle: Task-Runner-Umgebungsvariablen.
Ein `require` oder `import` im Code-Node schlägt trotz gesetzter Variable fehl.
Ursache: NODE_FUNCTION_ALLOW_EXTERNAL oder N8N_RUNNERS_EXTERNAL_ALLOW wurde als Container-Variable gesetzt. Im externen Modus wertet der Launcher diese Variablen nur aus der Konfigurationsdatei aus. Lösung: Die Allowlist als env-override in /etc/n8n-task-runners.json eintragen und die Datei mounten. Quelle: Set up task runners.
Nach einem Update startet der Runner nicht mehr oder verhält sich unerwartet.
Ursache: Die Versionen von n8nio/n8n und n8nio/runners stimmen nicht überein. Lösung: Beide Tags auf dieselbe Version setzen und gemeinsam aktualisieren. Quelle: Set up task runners.
Im Queue-Modus laufen Code-Nodes auf einem Worker in einen Timeout.
Ursache: Nur die Hauptinstanz hat einen Sidecar, die Worker haben keinen. Jeder Worker benötigt einen eigenen Runner-Container. Lösung: Je Worker einen Sidecar ergänzen. Quelle: Queue-Modus aktivieren.
Im internen Modus läuft der Runner als Kindprozess von n8n mit denselben Rechten. Im externen Modus läuft er in einem eigenen Container und ist vom Hauptprozess isoliert. Nur der externe Modus gilt als produktionstauglich.
Ab n8n 1.111.0. Zusätzlich muss die Version des Image n8nio/runners exakt zur eingesetzten n8n-Version passen.
Ja. Im Queue-Modus braucht jeder Worker einen eigenen Sidecar. Hauptinstanzen brauchen ebenfalls einen, sofern OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS nicht aktiv ist und sie manuelle Ausführungen selbst verarbeiten.
Für Python ist der Zugriff über os.environ per N8N_BLOCK_RUNNER_ENV_ACCESS standardmäßig blockiert. Für Isolation auf Betriebssystemebene empfiehlt n8n zusätzlich ein AppArmor-Profil gegen /proc-Zugriffe.
Quellen: Set up task runners, Harden task runners und Task-Runner-Umgebungsvariablen.
Gründer von NordFlux. Sieben Jahre Erfahrung von Web und SEO bis zur Automatisierung im Konzern-Maßstab, heute pragmatisch für den Mittelstand und mit deutscher Datenhoheit.
Zertifizierungen
Die größte n8n-Lernhürde erklärt: was Items, $json und $node bedeuten und wie Sie Werte per Drag-and-Drop ohne Code mappen.
So härten Sie n8n ab: 2FA aktivieren, SSRF-Schutz einrichten, riskante Nodes mit NODES_EXCLUDE sperren und die Public API abschalten, wenn ungenutzt.
Task Runners sind ein Baustein, ein sicher betriebenes n8n braucht daneben Hardening, Rechtekonzept und saubere Updates. NordFlux betreibt n8n-Instanzen mit externem Task-Runner-Modus, Monitoring und dokumentierter Konfiguration. So laufen auch Code-lastige Workflows produktiv, ohne dass eine einzelne Node die ganze Instanz gefährdet.