Kustomize manifests for running n8n on OpenShift 4.x.
Most n8n deployment guides assume Docker Compose or vanilla Kubernetes. Neither works on OpenShift without changes. OpenShift runs containers with random UIDs, enforces restricted security contexts, and uses Routes instead of Ingress. This repo handles all of that.
base/ # Portable Kubernetes resources
deployment.yaml # apps/v1 Deployment with health probes and resource limits
service.yaml # ClusterIP on port 5678
pvc.yaml # 5Gi persistent volume for n8n data
configmap.yaml # Runtime configuration (port, protocol, timezone, user folder)
kustomization.yaml
overlays/openshift/ # OpenShift-specific additions
route.yaml # TLS edge-terminated Route (auto-assigned hostname)
security-patch.yaml # runAsNonRoot, fsGroup, drop ALL capabilities, seccomp
kustomization.yaml
The base layer works on any Kubernetes cluster. The OpenShift overlay adds the Route and locks down the security context to pass the restricted-v2 SCC.
# Log in to your cluster
oc login --token=<token> --server=https://api.<cluster>:6443
# Create a project
oc new-project n8n
# Deploy
oc apply -k overlays/openshift/n8n will be available at the Route URL the cluster assigns. Check it with:
oc get route n8n -o jsonpath='https://{.spec.host}'The first time you open the UI, n8n walks you through creating an admin account.
Edit base/configmap.yaml to change runtime settings:
| Variable | Default | Purpose |
|---|---|---|
N8N_PORT |
5678 |
HTTP listen port |
N8N_PROTOCOL |
https |
Protocol for generated URLs (matches the Route) |
N8N_USER_FOLDER |
/home/node |
Where n8n stores config and SQLite data |
GENERIC_TIMEZONE |
UTC |
Default timezone for scheduled workflows |
For additional variables, see the n8n environment variables docs.
OpenShift assigns a random UID from the namespace's allocated range. The n8n container image expects to run as the node user (UID 1000), but that UID won't match. This doesn't matter as long as the filesystem is writable. The fsGroup in the security patch makes the PVC group-writable for the assigned UID.
If you deploy to a different namespace, update the fsGroup value in overlays/openshift/security-patch.yaml to match your namespace's range:
oc get namespace <your-namespace> -o jsonpath='{.metadata.annotations.openshift\.io/sa\.scc\.supplemental-groups}'
# Use the first number from the outputThe PVC mounts at /home/node (the parent directory). n8n creates its .n8n subdirectory inside it on first boot. Mounting directly at /home/node/.n8n causes permission errors because the random UID can't create the directory within a root-owned mount point.
The overlay sets:
runAsNonRoot: trueallowPrivilegeEscalation: falsecapabilities.drop: [ALL]seccompProfile.type: RuntimeDefault
This satisfies the restricted-v2 SCC without needing any elevated permissions.
For anything beyond a single user, swap SQLite for PostgreSQL. Add these to the ConfigMap (or better, use a Secret for the password):
DB_TYPE: "postgresdb"
DB_POSTGRESDB_HOST: "postgres.n8n.svc"
DB_POSTGRESDB_PORT: "5432"
DB_POSTGRESDB_DATABASE: "n8n"
DB_POSTGRESDB_USER: "n8n"With PostgreSQL, you can also scale the Deployment beyond one replica.