Skip to main content

Phase 83 β€” n8n Workflow Automation

Deployed: 2026-08-01 | Version: n8n 2.32.7 | Namespace: automation

n8n is a self-hosted workflow automation platform β€” like Zapier or Make, but running entirely on the cluster. Workflows connect internal services (Plane, NATS, Stalwart mail, ERPNext, Backstage) and external APIs without sending data off-platform.


Three orchestration shapes β€” n8n vs Temporal vs Airflow​

These are not competitors β€” they are three different shapes of orchestration, chosen by the nature of the work, not preference. Picking the wrong one is the common mistake.

n8n (live)Temporal (live)Airflow (deferred, #153)
Shapeevent-driven integrationdurable stateful workflowscheduled batch DAG
Triggeran event/webhook happensa business process must run to completiona clock (cron / interval)
Built byanyone, visual UI (low-code)developers, in code (Go/TS/Py)developers, Python DAGs
Durabilitybest-effort + per-step retrydeterministic replay β€” survives crashes, resumes exactly, runs for days/months, saga/compensationtask-level retry within a run
Reach for it when…"when X happens, call Y and Z across APIs, retry/alert on failure" β€” glue, human-editablethe process is long-lived and must not lose state / must guarantee completion (e.g. claims-settlement saga: reserve β†’ approve β†’ SEPA payout β†’ accounting β†’ notify, rollback on failure)time-driven data/ML pipelines ("run the dbt transform nightly at 02:00")
On this clusterintegration glue: premium-collection lifecycle, SEPA/Stripe webhooks, notificationsdurable workflows: MAAS node power-dispatch/provisioning; the intended home for long insurance sagasnone yet — the analytical data platform (ClickHouse→dbt→BI) isn't built, so nothing needs cron DAGs; Airflow earns its place when it is

Litmus test: reactive glue β†’ n8n; a transaction that must survive failure and complete β†’ Temporal; a scheduled pipeline over data β†’ Airflow. Two orchestrators are live (n8n + Temporal, each with a distinct role); the third is deferred until its use case (scheduled data pipelines) becomes real β€” see Temporal and Airflow.


Architecture​

https://n8n.devandre.sbs
β”‚
Cloudflare Tunnel
β”‚
ingress-nginx
β”‚ (Authentik forward auth β€” nginx snippet pattern)
β–Ό
n8n Deployment (automation ns)
β”‚ SQLite on Longhorn 5Gi RWO PVC
β”‚ Encryption key from Vault
β–Ό
/webhook/ /webhook-test/ ← separate ingress, no auth
(for Plane/NATS/external triggers)
ComponentDetail
Imagedocker.io/n8nio/n8n:2.32.7
DatabaseSQLite on Longhorn RWO PVC (/home/node/.n8n)
Storagen8n-data PVC, 5Gi, longhorn StorageClass
AuthAuthentik forward auth (proxy provider pk 17, forward_single)
Webhooks/webhook/ and /webhook-test/ bypass Authentik (separate ingress)
TLScert-manager, ClusterIssuer minicloud-ca
SecretsESO β†’ platform/n8n.encryption_key, platform/mail.smtp-relay-password
SMTPStalwart (stalwart.mail.svc.cluster.local:587), sender n8n@devandre.sbs
TimezoneEurope/Paris

GitOps layout​

manifests/n8n/
β”œβ”€β”€ 00-namespace.yaml # automation namespace
β”œβ”€β”€ 01-externalsecret.yaml # Vault β†’ n8n-credentials secret
β”œβ”€β”€ 02-pvc.yaml # 5Gi Longhorn RWO
β”œβ”€β”€ 03-deployment.yaml # n8n Deployment
β”œβ”€β”€ 04-service.yaml # ClusterIP :5678
β”œβ”€β”€ 05-ingress.yaml # main (Authentik) + webhook (open)
└── 06-certificate.yaml # cert-manager TLS
apps/n8n.yaml # ArgoCD Application

Access​

URLAuth
https://n8n.devandre.sbsAuthentik OIDC (kanmegnea + TOTP) β†’ n8n login
https://n8n.10.0.0.200.nip.ioInternal only (requires Tailscale)

Owner account: kanmegnea@gmail.com (set at first deploy via /rest/owner/setup).


Deployment gotchas​

1. Gatekeeper policy violations​

The cluster's OPA Gatekeeper enforces constraints that n8n's default pod spec violates:

PolicyFix
require-non-rootsecurityContext.runAsNonRoot: true, runAsUser: 1000
no-privilege-escalationsecurityContext.allowPrivilegeEscalation: false
block-net-rawsecurityContext.capabilities.drop: [NET_RAW]
require-resource-limitsresources.limits.cpu: 1000m

2. Node.js OOM at 512Mi​

n8n requires at least 1 GB RAM. The V8 heap exhausted at 512Mi:

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

Fix: memory limit 1.5Gi + NODE_OPTIONS=--max-old-space-size=1024.

3. Cloudflare tunnel requires a config.yml entry​

cloudflared tunnel route dns creates the DNS CNAME but does not add the ingress rule. Every new public hostname needs a manual entry in ~/.cloudflared/config.yml:

- hostname: n8n.devandre.sbs
service: https://10.0.0.200
originRequest:
noTLSVerify: true
originServerName: n8n.10.0.0.200.nip.io

Restart: pkill -f 'cloudflared tunnel' && nohup ~/.local/bin/cloudflared tunnel --config ~/.cloudflared/config.yml run >> ~/.cloudflared/cloudflared.log 2>&1 &


Authentik provider (rebuild reference)​

# Create proxy provider (forward_single)
curl -X POST https://auth.devandre.sbs/api/v3/providers/proxy/ \
-H "Authorization: Bearer $AK_TOKEN" -H "Content-Type: application/json" \
-d '{
"name":"n8n-forward-auth",
"authorization_flow":"3cb61a3d-47ba-47ac-bf32-b270179bb735",
"invalidation_flow":"2c1cd937-5a93-4e36-b9df-96839a9e3e05",
"external_host":"https://n8n.devandre.sbs",
"mode":"forward_single",
"property_mappings":["35c5c354-c9ce-4942-a919-43208923127f","06730f5f-cf59-4227-afe7-7fdf9dc113ba","d4967c11-acbe-4ae6-80c0-4b45c0fcf95b","677d145c-2abe-407e-9e5f-e425b65a8740","6e52eb60-9e8c-4684-be85-6cf79e894a01"],
"token_validity":"hours=24"}'
# β†’ note the returned pk, then:
curl -X POST https://auth.devandre.sbs/api/v3/core/applications/ \
-d '{"name":"n8n","slug":"n8n","provider":<pk>,"meta_launch_url":"https://n8n.devandre.sbs"}'
# Add provider pk to embedded outpost providers list
curl -X PATCH https://auth.devandre.sbs/api/v3/outposts/instances/93d11dbf-e7fe-4604-afb1-7269980a5b47/ \
-d '{"providers":[1,8,15,<pk>]}'

Use cases on this platform​

  • Plane β†’ Stalwart: email notifications for issue state transitions
  • ERPNext webhooks β†’ NATS: publish HR events to the messaging bus
  • Monitoring alerts β†’ custom logic: route Alertmanager webhooks beyond Slack
  • Scheduled exports: pull ERPNext/Plane data, format, send via Stalwart

Real-world skills demonstrated​

SkillIndustry context
Self-hosted workflow automationReplaces SaaS tools (Zapier, Make) for compliance-sensitive data
Authentik nginx forward authStandard proxy-auth pattern for internal tools without native OIDC
Separate webhook ingressProtect UI, expose API surface β€” same shape as Stripe/GitHub webhook receivers
Gatekeeper policy complianceEnforcing non-root, no NET_RAW, resource limits on third-party images
Vault-backed secrets at deployEncryption key injected from Vault β€” no plaintext in gitops