Deployment von n8n in minikube und ngrok
Seit einigen Monaten sorgt das Low-Code-Integrationstool n8n für Gesprächsstoff in der Tech-Welt. Angetrieben vom aktuellen Hype um KI-Agenten hat sich das Tool zum Liebling vieler Automatisierungsfans entwickelt. Sein Versprechen klingt verlockend: Workflows im Handumdrehen automatisieren und KI-Agenten ohne großen Aufwand integrieren – ganz ohne komplexe Programmierung. Als Teil des Integrationsteams bei der codecentric AG machte mich das natürlich neugierig, und so begann ich im Frühjahr 2025, n8n unter die Lupe zu nehmen. In diesem Blogpost zeige ich, welche Hürden mir dabei begegnet sind und welche Stolpersteine es zu beachten gilt. Am Ende des Artikels verlinke ich ein öffentliches GitHub-Repository, das ein fertiges Helm-Chart enthält. Damit lässt sich n8n lokal in Minikube deployen – und alle hier beschriebenen Probleme sind darin bereits gelöst.
Unterstützte Deployment/Hosting Szenarien
Möchte man mit n8n starten, stellt sich zuerst die Frage, wie man es einfach verwenden kann. Auf der Seite n8n Hosting finden sich als Installationsmöglichkeiten npm, Docker, Docker-Compose und diverse SaaS-Anbieter. Um n8n lokal auszuprobieren, reicht natürlich Docker aus. Möchte man auch Webhooks verwenden, damit zum Beispiel auf Events von GitHub reagiert werden kann, muss eine öffentliche Domäne auf die lokale Docker-Instanz zeigen – was sich einfach mit der ngrok-CLI umsetzen lässt. Was einem früher oder später auffällt, ist die fehlende Möglichkeit, ein Deployment in einem selbstgehosteten Kubernetes-Cluster durchzuführen. Die einzige offizielle Möglichkeit, n8n in Produktion zu betreiben, ist somit das Hosten durch einen der SaaS-Anbieter. Die Firma 8gears AG hat dieses Problem adressiert und ein passendes Helm-Chart auf GitHub veröffentlicht.
Damit ist es möglich, n8n auch in Produktion in Kubernetes selbst zu hosten. Für das Entwickeln von Anwendungen ist es immer von Vorteil, ein ähnliches Setup zu haben, das der Produktionsumgebung entspricht. Ich versuchte daraufhin, dieses Helm-Chart bei mir in Minikube zu deployen.
Ingress beim 8gears Helm Chart
Die Anleitung von 8gears auf GitHub ist sehr ausführlich, und man kommt schnell zu Ergebnissen. Nutzt man dieses Chart, werden zusätzliche Services für Worker und Webhooks erzeugt – und bei Bedarf sowohl Valkey als auch ein Ingress. Ich möchte das Helm-Chart nicht in der Tiefe erläutern, jedoch auf die Ingress-Komponente eingehen, da diese für das Erreichen von n8n in Minikube relevant ist. Der folgende Ausschnitt zeigt ein Beispiel der Ingress-Konfiguration.
1ingress: 2 enabled: true 3 className: nginx 4 annotations: {} 5 hosts: 6 - host: workflow.example.com 7 paths: 8 - /
Dieses Beispiel ist mit Absicht einfach gehalten und soll lediglich dazu dienen, mit dem Befehl helmfile template
die Ingress-Ressource zu erzeugen, damit wir sehen, was letzten Endes deployed wird und welche Endpunkte erreichbar sein müssen. Ich habe die erstellte Konfiguration auf das Wesentliche gekürzt.
1kind: Ingress 2metadata: 3 name: n8n 4spec: 5 ingressClassName: nginx 6 tls: 7 - hosts: 8 - "workflow.example.com" 9 rules: 10 - host: "workflow.example.com" 11 http: 12 paths: 13 - path: / 14 pathType: Prefix 15 backend: 16 service: 17 name: n8n 18 - path: /webhook/ 19 pathType: Prefix 20 backend: 21 service: 22 name: n8n-webhook 23 - path: /webhook-test/ 24 pathType: Prefix 25 backend: 26 service: 27 name: n8n 28 - path: /webhook-waiting/ 29 pathType: Prefix 30 backend: 31 service: 32 name: n8n-webhook 33 - path: /form/Seit einigen Monaten sorgt das Low-Code-Integrationstool n8n für Gesprächsstoff in der Tech-Welt. Angetrieben vom aktuellen Hype um KI-Agenten hat sich das Tool zum Liebling vieler Automatisierungsfans entwickelt. Sein Versprechen klingt verlockend: Workflows im Handumdrehen automatisieren und KI-Agenten ohne großen Aufwand integrieren – ganz ohne komplexe Programmierung. 34 pathType: Prefix 35 backend: 36 service: 37 name: n8n-webhook
Hier sehen wir nun fünf Endpunkte, die auf zwei Services, n8n-webhook und n8n, verweisen. Außerdem wird deutlich, dass Webhooks bei der Workflow-Automatisierung mit n8n eine wichtige Rolle einnehmen. Zum Beispiel ist eine Integration zwischen GitHub und Slack möglich, bei der Nutzer über Pull Requests oder neue Issues informiert werden. GitHub würde in diesem Szenario n8n über die Pfade /webhook-test/ oder /webhook/ erreichen. Der n8n-Workflow-Editor ist über den Root-Pfad / erreichbar. Lokal n8n zu betreiben, ohne dass ein Zugriff aus dem öffentlichen Netz möglich ist, würde die Zahl an Anwendungsszenarien deutlich einschränken. Als Entwickler, die mit Kubernetes arbeiten wollen, benötigen wir also eine Möglichkeit, unsere lokale n8n-Instanz inklusive Webhooks auf unkomplizierte Art und Weise öffentlich aufrufbar zu machen.
ngrok kommt zur Hilfe
ngrok ist eine Cloud-Plattform, die öffentliche Endpunkte bereitstellt und Datenverkehr über TLS-Tunnel an lokal laufende Anwendungen, wie unser Minikube, weiterleitet. Zum Verwenden des Dienstes brauchen wir einen ngrok Account. ngrok hat drei Subscription-Modelle:
- free-plan
- development (mindestens $10/Monat)
- pay-as-you-go (mindestens $18/Monat)
Der kostenlose Account reicht für unsere Zwecke aus, da wir wenig Datenverkehr haben und nur eine öffentliche Domäne benötigen.
ngrok Kubernetes Operator
Es ist möglich, die ngrok-CLI zu verwenden und ein Port-Forwarding einzurichten, um unsere n8n-Instanz zu erreichen. Da wir uns aber in Minikube befinden, stellt ngrok etwas Besseres zur Verfügung: den ngrok-Operator. Mit dem Operator ist die Verknüpfung unseres Minikube-Clusters mit der ngrok-Cloud besonders einfach. Wir müssen ihn dafür lediglich im Helm-Chart deklarieren und uns bei ngrok einen API-Key sowie einen API-Token generieren, die wir lokal in Umgebungsvariablen ablegen. Dass es dann doch nicht ganz so einfach ist, wenn man den Free-Plan von ngrok verwendet, wird sich jedoch gleich zeigen.
helmfile.yaml:
1repositories: 2 - name: ngrok 3 url: https://charts.ngrok.com 4 5releases: 6 - name: ngrok 7 namespace: ngrok-operator 8 chart: ngrok/ngrok-operator 9 values: 10 - values/ngrok-values.yaml.gotmpl
ngrok-values.yaml.gotmpl:
1credentials: 2 apiKey: {{ requiredEnv `NGROK_API_KEY` }} 3 authtoken: {{ requiredEnv `NGROK_AUTHTOKEN` }}
Damit der ngrok-Operator nun den vorher deklarierten Ingress kennt, setzen wir className: ngrok statt className: nginx und geben auch gleich unsere neue, kostenlose ngrok-Domäne mit. Ich habe diese beispielhaft he-man.ngrok-free.app genannt. Unsere n8n-Instanz wäre dann über https://he-man.ngrok-free.app/ erreichbar, und Webhooks könnten über https://he-man.ngrok-free.app/webhook/ getriggert werden.
1ingress: 2 enabled: true 3 className: ngrok 4 annotations: {} 5 hosts: 6 - host: he-man.ngrok-free.app 7 paths: 8 - /
Der Operator interpretiert nun den erstellten Ingress und erstellt für uns sogenannte öffentliche AgentEndpoints, die in der ngrok-Cloud registriert werden sollen. Die fünf Endpunkte aus dem Ingress sollten nun über unsere Domäne erreichbar sein. Leider ist es jedoch so, dass der Operator nicht besonders klug agiert und beim Anlegen ein Limit des Free-Plans überschreitet – keiner der n8n-Endpunkte ist daraufhin aufrufbar. Den Hinweis auf das Limit findet man als Event im angelegten AgentEndpoint in Kubernetes.
This agent has exceeded its policy rule limit of 5. Please log into https://dashboard.ngrok.com ...
Front Door Pattern
So schnell wollte ich nicht die Flinte ins Korn werfen und habe deshalb nach anderen Möglichkeiten gesucht, n8n mit ngrok zu verknüpfen. Die Lösung ist relativ simpel: Ich implementiere das Front Door Pattern. Das Front Door Pattern hilft, das eben erreichte Limit zu umgehen, indem wir selbst unsere ngrok-Ressourcen anlegen und geschickt konfigurieren.
Aus diesem Grund ist es nicht mehr notwendig, überhaupt einen Ingress zu erstellen, der vom ngrok-Operator interpretiert wird. Wir können also Minikube ohne Ingress-Addon starten, behalten aber den ngrok-Operator für die Kommunikation mit der ngrok-Cloud bei.
Im folgenden Bild wird die neue Architektur ersichtlich.
Der CloudEndpoint ist der Einstiegspunkt in unser Minikube-Cluster und öffentlich erreichbar. Seine Aufgabe ist es, den Datenverkehr anhand einer Traffic Policy zu den passenden internen AgentEndpoints weiterzuleiten.
1apiVersion: ngrok.k8s.ngrok.com/v1alpha1 2kind: CloudEndpoint 3metadata: 4 name: n8n-cloud 5spec: 6 url: he-man.ngrok-free.app 7 domain: 8 name: he-man.ngrok-free.app 9 bindings: 10 - public 11 trafficPolicy: 12 policy: 13 on_http_request: 14 - expressions: 15 - "req.url.path.startsWith('/webhook/') || req.url.path.startsWith('/webhook-waiting/') || req.url.path.startsWith('/form/')" 16 actions: 17 - type: forward-internal 18 config: 19 url: http://n8n.webhook.internal 20 - actions: 21 - type: forward-internal 22 config: 23 url: http://n8n.internal
Am folgenden Beispiel (n8n) sieht man die Konfiguration eines internen AgentEndpoint, welcher schlussendlich zum Service weiterleitet.
1apiVersion: ngrok.k8s.ngrok.com/v1alpha1 2kind: AgentEndpoint 3metadata: 4 name: n8n-agent 5spec: 6 url: http://n8n.internal 7 upstream: 8 url: http://n8n.n8n.svc.cluster.local:80
Durch weitere Actions kann der CloudEndpoint bei Bedarf mit Basic Auth und so weiter abgesichert werden. Durch diese paar Anpassungen können wir n8n öffentlich erreichbar machen.
Erweitertes 8gears Helm-Chart
Das Helm-Chart von 8gears ist ein guter Einstieg, um n8n in Kubernetes zu deployen. Die notwendigen Anpassungen, um es lokal mit ngrok zu starten, habe ich im GitHub-Repository n8n-Minikube hinterlegt. Ich wünsche euch viel Spaß beim Ausprobieren, aber bitte daran denken, dass n8n von allen aufrufbar ist, die eure Endpunkte kennen.
Weitere Beiträge
von Benjamin Lüdicke
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Blog-Autor*in
Benjamin Lüdicke
Senior IT Consultant
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.