refactor: make this a reusable deployment, not ours
Every environment value is a ${VAR} for the caller to substitute: hostname,
images, storage, ingress class, TLS issuer, Vault server and path, timezone,
retention. Nothing in k8s/ names a host, a realm, an agent or an estate.
Removed: the Flux plumbing under dev/, which described one deployment, and the
ExternalSecret pulling a specific agent's Keycloak client secret. Both belong to
whoever deploys this. The lab CA ConfigMap goes with them — the mount stays,
parameterised and marked optional, because 'trust a private CA' is a property of
an environment and not of n8n.
The README is now the template's: how to consume it, what every variable means,
and the three things it deliberately does not do.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+12
-16
@@ -4,21 +4,21 @@ apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: n8n-config
|
||||
namespace: n8n
|
||||
namespace: ${NAMESPACE}
|
||||
data:
|
||||
GENERIC_TIMEZONE: Europe/Paris
|
||||
TZ: Europe/Paris
|
||||
GENERIC_TIMEZONE: ${TIMEZONE}
|
||||
TZ: ${TIMEZONE}
|
||||
NODE_ENV: production
|
||||
|
||||
# What n8n believes it is reachable at. It goes into the webhook URLs it
|
||||
# generates and into the links it puts in its own UI, so it must be the
|
||||
# ingress host and not the Service — a webhook advertised as `n8n` inside the
|
||||
# cluster is a webhook nothing outside can call.
|
||||
N8N_HOST: n8n.sttlab.local
|
||||
N8N_HOST: ${N8N_HOSTNAME}
|
||||
N8N_PORT: "5678"
|
||||
N8N_PROTOCOL: https
|
||||
WEBHOOK_URL: https://n8n.sttlab.local/
|
||||
N8N_EDITOR_BASE_URL: https://n8n.sttlab.local/
|
||||
WEBHOOK_URL: https://${N8N_HOSTNAME}/
|
||||
N8N_EDITOR_BASE_URL: https://${N8N_HOSTNAME}/
|
||||
|
||||
# TLS terminates at the ingress, so n8n itself serves plain HTTP and must be
|
||||
# told it is behind a proxy — otherwise it reads the hop's address instead of
|
||||
@@ -28,18 +28,14 @@ data:
|
||||
# The default is to keep every execution for ever, which turns the database
|
||||
# into a log. Two weeks is long enough to debug a failed run.
|
||||
EXECUTIONS_DATA_PRUNE: "true"
|
||||
EXECUTIONS_DATA_MAX_AGE: "336"
|
||||
EXECUTIONS_DATA_MAX_AGE: ${EXECUTIONS_MAX_AGE_HOURS}
|
||||
|
||||
N8N_DIAGNOSTICS_ENABLED: "false"
|
||||
N8N_VERSION_NOTIFICATIONS_ENABLED: "false"
|
||||
N8N_RUNNERS_ENABLED: "true"
|
||||
|
||||
# Lets a workflow read `$env.<NAME>`. n8n blocks this by default, which is the
|
||||
# right default for an instance where anyone can write a workflow — here it is
|
||||
# how an agent's client secret reaches the workflow that acts as that agent,
|
||||
# without the secret being stored in the workflow JSON and committed.
|
||||
#
|
||||
# It does mean any workflow can read any variable in the pod. That is
|
||||
# acceptable while the instance runs this estate's own agents and nothing
|
||||
# else; it stops being acceptable the moment it is shared.
|
||||
N8N_BLOCK_ENV_ACCESS_IN_NODE: "false"
|
||||
# "false" lets a workflow read `$env.<NAME>`, which is how a secret reaches a
|
||||
# workflow without being stored in the workflow JSON. n8n blocks it by
|
||||
# default, and that default is right wherever more than one team can write a
|
||||
# workflow: any workflow can then read any variable in the pod.
|
||||
N8N_BLOCK_ENV_ACCESS_IN_NODE: ${BLOCK_ENV_ACCESS}
|
||||
|
||||
+19
-15
@@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: n8n
|
||||
namespace: n8n
|
||||
namespace: ${NAMESPACE}
|
||||
spec:
|
||||
# One replica. n8n's queue mode splits the editor from workers and needs Redis
|
||||
# to do it; without that, a second replica is two schedulers racing over the
|
||||
@@ -26,7 +26,7 @@ spec:
|
||||
fsGroup: 1000
|
||||
initContainers:
|
||||
- name: wait-for-postgres
|
||||
image: postgres:16.10-alpine
|
||||
image: ${POSTGRES_IMAGE}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
@@ -36,7 +36,7 @@ spec:
|
||||
done
|
||||
containers:
|
||||
- name: n8n
|
||||
image: docker.n8n.io/n8nio/n8n:2.37.4
|
||||
image: ${N8N_IMAGE}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 5678
|
||||
@@ -64,24 +64,27 @@ spec:
|
||||
secretKeyRef:
|
||||
name: n8n-secrets
|
||||
key: N8N_ENCRYPTION_KEY
|
||||
# The lab CA, so a workflow can call keycloak.sttlab.local and the
|
||||
# domain gateways without disabling verification. n8n is Node, hence
|
||||
# this variable rather than a trust store.
|
||||
# A private CA to trust, so a workflow can call an internal
|
||||
# endpoint over TLS without anyone disabling verification to make it
|
||||
# work. n8n is Node, hence this variable rather than a trust store.
|
||||
# Provided by the deployment; an empty ConfigMap disables it in
|
||||
# practice, since the file will not exist and Node falls back to its
|
||||
# own bundle.
|
||||
- name: NODE_EXTRA_CA_CERTS
|
||||
value: /etc/sttlab-ca/ca.crt
|
||||
value: /etc/extra-ca/ca.crt
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: n8n-config
|
||||
# The agents' Keycloak client secrets, reached from a workflow as
|
||||
# `$env.APPROVISIONNEMENT_CLIENT_SECRET`. A workflow acts as its
|
||||
# agent, so it is the workflow that must be able to exchange tokens.
|
||||
# Whatever else this deployment's workflows need in their
|
||||
# environment. Provided by the deployment, not by this repo: an
|
||||
# empty Secret of that name is a valid answer.
|
||||
- secretRef:
|
||||
name: n8n-agent-secrets
|
||||
name: ${EXTRA_ENV_SECRET}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /home/node/.n8n
|
||||
- name: sttlab-ca
|
||||
mountPath: /etc/sttlab-ca
|
||||
- name: extra-ca
|
||||
mountPath: /etc/extra-ca
|
||||
readOnly: true
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
@@ -110,6 +113,7 @@ spec:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: n8n-data
|
||||
- name: sttlab-ca
|
||||
- name: extra-ca
|
||||
configMap:
|
||||
name: sttlab-ca
|
||||
name: ${EXTRA_CA_CONFIGMAP}
|
||||
optional: true
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: n8n-data
|
||||
namespace: n8n
|
||||
namespace: ${NAMESPACE}
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
storage: ${N8N_STORAGE}
|
||||
|
||||
@@ -2,7 +2,7 @@ apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: n8n
|
||||
namespace: n8n
|
||||
namespace: ${NAMESPACE}
|
||||
spec:
|
||||
selector:
|
||||
app: n8n
|
||||
|
||||
Reference in New Issue
Block a user