5.2.35. n8n¶
Workflow automation engine. The stack runs n8n in queue mode by default — one n8n web/API container plus an n8n-worker container that consumes jobs from Redis. A short-lived n8n-init container handles first-run setup: installing community nodes (ComfyUI image-to-image). Seeded workflow templates (under services/n8n/init/config/) and PostgreSQL credentials are imported manually — n8n-init prints the next steps; it does not auto-import workflows or seed credentials (see the setup steps below). The result is a fully-wired automation surface that ties LLM (LiteLLM), media (ComfyUI/STT/TTS/Docling/SearXNG), and data (Supabase/Weaviate/MinIO) services together without writing code.
n8n is also the only "agents"-tier service besides Hermes; the two are complementary. n8n is event-driven and visual (cron triggers, webhooks, manual runs); Hermes is conversational and skill-driven. n8n reaches Hermes through a shared HERMES_ENDPOINT env var so a workflow can hand off to an agent (the reverse edge — Hermes calling a workflow — isn't wired today; see §4).
1. Overview¶
Image: n8nio/n8n:2.28.2. The web/API container handles HTTP + UI; the worker container handles execution. Both share state through Supabase Postgres (workflow definitions, executions history, credentials) and Redis (queue + execution coordination). The n8n-init container runs after the web/API container is reachable, installs required community nodes, then exits. The launcher checks that one-shot exit code and fails if it exited nonzero.
Track placement: n8n is available in all, gen-ai-eng, and gen-ai-rag. In the RAG track it provides workflow orchestration for document ingestion, search-to-extraction flows, vector-store operations, and human-reviewed automation around the RAG services.
2. Access¶
| Path | URL | Notes |
|---|---|---|
| Direct | http://localhost:${N8N_PORT} (default 63075) |
UI + REST API. |
| Kong | http://n8n.localhost:${KONG_HTTP_PORT} |
Recommended for browser use; needs ./start.sh --setup-hosts. Kong route uses preserve_host: True. |
| Webhook | ${N8N_HOST}/webhook/<path> |
n8n's webhook entry point; resolves to whichever host you used to reach n8n. |
Canonical port table: Ports and Routes.
3. Configuration¶
N8N_SOURCE=container # container | disabled
N8N_PORT=63075 # computed by topology.py
N8N_ENCRYPTION_KEY=<random> # auto-generated by bootstrapper; rotate before deploy
N8N_HOST=n8n.localhost # Kong alias hostname
N8N_PROTOCOL=http
N8N_EXECUTIONS_MODE=queue # queue (default, requires worker + redis) | regular (single-process)
N8N_INIT_NODES=n8n-nodes-comfyui@0.0.9,@ksc1234/n8n-nodes-comfyui-image-to-image@1.0.2
n8n 2.28.2 always uses the owner-account setup flow, and community nodes are
loaded from the pinned packages installed by n8n-init — no auth-mode or
community-package env vars are needed for the pinned image.
Adaptive env (auto-injected based on active SOURCE values):
STT_ENDPOINT=... # resolved per STT_PROVIDER_SOURCE
PARAKEET_API_TOKEN= # generated Parakeet bearer; server-side only
TTS_ENDPOINT=... # resolved per TTS_PROVIDER_SOURCE
DOCLING_ENDPOINT=... # resolved per DOC_PROCESSOR_SOURCE
DOCLING_API_TOKEN= # generated Docling bearer; server-side only
Required Postgres/Redis env (built from the upstream services' creds):
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=supabase-db
DB_POSTGRESDB_DATABASE=postgres
DB_POSTGRESDB_USER=supabase_admin
DB_POSTGRESDB_PASSWORD=${SUPABASE_DB_PASSWORD}
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
BACKEND_N8N_API_TOKEN= # auto-generated workflow-scoped bearer
The bundled Backend-calling workflows attach
Authorization: Bearer $env.BACKEND_N8N_API_TOKEN to every request; the
value is present on both the n8n web and worker containers because queue-mode
executions run on the worker. The token is scoped to a limited set of Backend
routes — the Backend's own docs define exactly which routes it can and cannot
reach. Do not return it in webhook payloads, execution output, or browser-side
code.
The web and worker containers also receive the Docling and Parakeet provider tokens because either process may execute an HTTP Request node. Calls to ${DOCLING_ENDPOINT}/v1/document/convert must attach Authorization: Bearer {{$env.DOCLING_API_TOKEN}}; calls to a Parakeet ${STT_ENDPOINT}/v1/audio/transcriptions route must similarly use {{$env.PARAKEET_API_TOKEN}}. Speaches and whisper.cpp do not use the Parakeet token. Keep both credentials in server-side expressions and never include them in execution output, webhook responses, or browser JavaScript.
Required runtime dep: weaviate (per runtime_deps.n8n.requires). With WEAVIATE_SOURCE=disabled, n8n is force-disabled with an error message — the stack design treats Weaviate-backed vector ops as load-bearing for the seeded AI workflows.
4. Architecture & wiring¶
Queue mode flow:
- UI/webhook hits
n8n:5678(web container) → workflow record stored in Supabase Postgres. - Execution is pushed onto BullMQ queue in Redis db
/0(QUEUE_BULL_REDIS_DB: 0). n8n-workerpolls Redis, picks up the job, runs the workflow, writes execution history back to Postgres.- UI streams progress via Redis pub/sub back to the web container.
Init flow (n8n-init, pinned n8n image + npm lockfile):
- Before the n8n web or worker process starts, install the committed exact package set with
npm ci --omit=dev --ignore-scriptsinto the shared/home/node/.n8n/nodesdirectory. - Package versions (including the
n8n-workflowpeer dependency) are pinned to avoid drift; the pinning rationale and community-node replacement history are documented as comments near the n8n-init lockfile.N8N_INIT_NODEScan replace the default set only with comma-separated exactname@x.y.zspecs. - Print completion. The seeded workflow template in
services/n8n/init/config/(mounted at/config/) is imported manually via the n8n UI —n8n-initdoes not auto-import workflows. - Exit 0 only when the complete package tree is installed; otherwise exit 1 and prevent n8n from starting. Initialization does not call n8n's authenticated internal REST API.
Hard dependencies (depends_on.required): supabase, redis, litellm. Without LiteLLM, all AI Agent nodes (the most-used feature) 404.
Adaptive integrations (runtime_adaptive.n8n.adapts_to): stt_provider, tts_provider, doc_processor, tika, lightrag, hermes, crawl4ai, supavisor. When any of those is disabled, the corresponding endpoint env var is set to empty and workflow nodes referencing it surface 502 at run time.
Hermes wiring. HERMES_ENDPOINT is injected so workflows can call into Hermes via the HTTP Request node. Inverse path (Hermes → n8n) is webhook-driven: n8n's public REST API has no execute endpoint, so expose a Webhook-trigger workflow and have Hermes POST to its URL.
Seeded workflows. services/n8n/init/config/searxng-research-workflow.json ships as a worked example of the SearXNG → LiteLLM research pattern, imported manually via the n8n UI. Additional example workflows are staged under services/n8n/workflows-stage/workflows/ for the same manual-import path. Before activating any staged webhook workflow, create an n8n Header Auth credential, select it on the webhook node in place of the Atlas Webhook Header Auth placeholder, and configure callers with the same header and value. The examples intentionally cannot expose a production webhook until that local credential is bound. Parameter validation ranges (query count/length, loop limits, search-API choice) and node-level behavior live in the workflow JSON's own inline notes; the bootstrapper test suite validates the workflow's structure and importability.
Consumer workflow seeding. A downstream consumer no longer has to script workflow import/activation/readiness itself: it declares an n8n_workflows block in atlas.consumer.yml (see reusing-atlas.md §6.3.3), and the bootstrapper validates, namespaces (atlas-consumer-<id>), imports, and activates each workflow via a dedicated n8n-seed container once n8n is healthy — idempotently, and best-effort per workflow so one bad consumer workflow can't abort startup. Removed manifest entries are reconciled (deactivated + deleted) when an N8N_API_KEY is configured. Timeout/size bounds and the full validation, namespacing, and reconciliation spec live in the bootstrapper seeder implementation under services/n8n/.
5. Calling LightRAG from n8n¶
When LIGHTRAG_SOURCE != disabled, the env vars LIGHTRAG_ENDPOINT and LIGHTRAG_API_KEY are injected into n8n containers. Use the HTTP Request node:
- URL:
={{$env.LIGHTRAG_ENDPOINT}}/query - Auth: Bearer token from
={{$env.LIGHTRAG_API_KEY}} - Body (JSON):
{"query": "/hybrid Your question"}
6. Dependencies & Integrations¶
6.1. Current — Upstream (this service calls)¶
| Service | Category |
|---|---|
| redis | data |
| supabase | data |
| supavisor | data |
| weaviate | data |
| litellm | llm |
| crawl4ai | media |
| doc-processor | media |
| searxng | media |
| stt-provider | media |
| tika | media |
| tts-provider | media |
| hermes | agents |
| lightrag | agents |
| backend ↔ | apps |
6.2. Current — Downstream (services that call this)¶
| Service | Category |
|---|---|
| kong | infra |
| prometheus | infra |
| backend ↔ | apps |
| jupyterhub | apps |
6.3. Architecture diagram¶
Open the full-size diagram for a full-screen view.
6.4. Future — Missing pair integrations¶
- n8n ↔ comfyui — Why:
n8n-nodes-comfyuiis installed byn8n-init, but noCOMFYUI_ENDPOINTenv is injected into n8n's compose, so users hand-enterhttp://comfyui:18188in every workflow credential. Mechanism: injectCOMFYUI_ENDPOINT=${COMFYUI_ENDPOINT}(matches the STT/TTS/DOCLING pattern); addcomfyuitoruntime_deps.optional. Effort: small. Confidence: high. - n8n ↔ minio — Why: MinIO already provisions an
n8nbucket plusMINIO_N8N_*creds, but neither credentials nor the S3 endpoint are passed to n8n, so the dedicated bucket sits unused. Mechanism: env-injectS3_ENDPOINT=http://minio:9000,S3_BUCKET=${MINIO_BUCKET_N8N},S3_ACCESS_KEY/S3_SECRET_KEY; addminiotoruntime_deps.optional. Path-style addressing required. Effort: small. Confidence: high. - n8n ↔ neo4j — Why: Neo4j is the stack's graph store but has no first-party n8n node; KG-from-document flows can't write to Neo4j without custom HTTP-node calls. Mechanism: inject
NEO4J_URI=bolt://neo4j-graph-db:7687+ creds; use the HTTP Request node hittinghttp://neo4j-graph-db:7474/db/neo4j/tx/commituntil a vetted community node is adopted. Effort: medium. Confidence: medium. - n8n ↔ searxng — Why: n8n advertises a
SearXNG Toolsub-node for AI-agent workflows but the endpoint is not injected. Mechanism: injectSEARXNG_ENDPOINT=http://searxng:8080; addsearxngtoruntime_deps.optional. Effort: small. Confidence: high. - n8n ↔ openclaw — Why: OpenClaw is the messaging-platform gateway. Wiring it to n8n turns every n8n webhook into a chat-triggered automation. Mechanism: OpenClaw → n8n via webhook at
http://n8n:5678/webhook/<path>; n8n → OpenClaw via HTTP Request node; shared bearer secret in both manifests. Effort: medium. Confidence: medium.
6.5. Future — Candidate new services¶
- Browserless (details) — Headline: headless-Chrome backend so n8n can scrape JS-rendered pages, render PDFs, screenshot. Wires into: searxng, doc-processor, backend.
- NocoDB (details) — Headline: spreadsheet UI over the existing Supabase Postgres, with a first-party n8n node for row CRUD. Wires into: supabase, backend.
6.6. Future — Unused features in this service¶
- MCP Server Trigger node — Why pursue: the pinned n8n runtime already ships first-party MCP client, tool, registry, and trigger nodes, but bundled workflows do not yet expose an Atlas workflow as an MCP tool for Hermes/LiteLLM clients. Effort: small.
- Native Weaviate Vector Store cluster node — Why pursue: upstream ships a native Weaviate vector-store node; workflows currently talk to Weaviate via raw HTTP. Switching unlocks embeddings + retrievers without custom code. Effort: small.
- Signed webhook verification — Why pursue: staged Backend-calling examples now require n8n Header Auth credentials, while provider-native signature verification remains useful for third-party event sources that sign request bodies. Effort: small.
7. Troubleshooting¶
Command start not found restart loop. Almost always corruption in the atlas-n8n-data volume after a partial cold-start. Surgical fix: docker volume rm <project>-n8n-data (without ./stop.sh --cold). On next ./start.sh, n8n re-initializes from scratch.
Init container exits with EACCES writing nodes. The community-package install needs the node-modules dir writable. Check docker logs <project>-n8n-init; typically a remnant from an earlier failed run. docker volume rm <project>-n8n-data clears it.
Workflows enqueued but never execute. EXECUTIONS_MODE=queue requires both the web and worker containers up. Verify docker compose ps | grep n8n shows two healthy n8n rows and Redis is reachable from both.
AI Agent nodes 404. LiteLLM is down or LITELLM_MASTER_KEY rotated without restarting n8n. n8n caches the key at startup; bounce n8n after rotation.
docker compose ps n8n n8n-worker
docker compose logs -f n8n
docker compose logs -f n8n-worker
docker compose logs n8n-init # one-shot; useful for first-run debug
For general startup and routing issues, see Troubleshooting.