Stéphane Tailland 3ca122287f fix: pin a version of n8n that exists
1.128.2 was invented; the current line is 2.37.x.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 12:39:32 +02:00
2026-08-29 12:34:40 +02:00
2026-08-29 12:39:32 +02:00
2026-08-29 12:34:40 +02:00

infra-n8n

n8n on the lab cluster: the runtime for the estate's autonomous agents, Approvisionnement and Recouvrement, whose workflows live in classic-models-agent-flows.

Nothing business-specific is here. This repo deploys the engine; the workflows are imported into it.

Layout

k8s/postgres/ the database, a StatefulSet with its own volume claim
k8s/n8n/ the workload, its config and its data volume
k8s/ingress/ a cert-manager Certificate and the nginx Ingress
k8s/secrets/ the ClusterSecretStore for this estate and the ExternalSecret
dev/ the Flux plumbing that applies k8s/, and manages itself

Reachable at https://n8n.sttlab.local once 192.168.139.101 (ingress-nginx) resolves for that name.

Two secrets, both of which must outlive any pod

They live in Vault at secrets/n8n/instance, read through the vault-n8n store — an AppRole whose policy can read n8n/* and nothing else, so a compromise here is not a way into the keycloak estate's secrets.

  • DB_PASSWORD
  • N8N_ENCRYPTION_KEY — encrypts the credentials n8n stores in its database. Never regenerate it. A new key does not re-encrypt what is stored; it orphans it. The workflows survive, every credential in them does not.

Bootstrap

Three manual applies, once. The Vault side is set up first — the commands are in k8s/secrets/clustersecretstore.yaml.

kubectl apply -f k8s/namespace.yaml
kubectl apply -f dev/gitrepository.yaml
kubectl apply -f dev/bootstrap-kustomization.yaml

After that everything reconciles from git, dev/ included. Never kubectl apply the objects under k8s/ afterwards — Flux reverts them within its interval and the cluster silently stops matching what you edited.

Choices worth knowing

One replica, and strategy: Recreate. n8n splits editor from workers only in queue mode, which needs Redis; without it a second replica is two schedulers racing over the same cron triggers. And the data volume is ReadWriteOnce, so a rolling update would deadlock — the new pod waiting for a volume the old one has not released.

The certificate is issued, not committed. cert-manager writes n8n-tls from the sttlab-local-ca ClusterIssuer. The private key stays in the cluster.

The CA certificate is committed, in k8s/ca-configmap.yaml, and mounted as NODE_EXTRA_CA_CERTS. It is a certificate, never a key, and checking it in means a workflow can call keycloak.sttlab.local and the domain gateways without anyone disabling verification to make it work. Regenerate on rotation — it expires 2026-11-24.

N8N_HOST and WEBHOOK_URL are the ingress host, not the Service. They go into the webhook URLs n8n hands out; advertised as the in-cluster name, they would be URLs nothing outside can call.

Executions are pruned after two weeks. The default keeps them for ever, which turns the database into a log.

What is deliberately not here

Authentication. n8n's own user management is left at its defaults, and the instance is reachable to anyone who can resolve the host on the lab network. Before it holds anything that matters, it needs either n8n's SSO against the classic-models realm or an openid-connect filter at the ingress — the same Keycloak the rest of the estate already uses.

S
Description
No description provided
Readme 76 KiB