Deploying n8n on Oracle Kubernetes Engine (OKE)

This guide walks you through deploying the n8n automation platform on Oracle Cloud Infrastructure (OCI) using Oracle Kubernetes Engine (OKE) — including persistent storage, authentication, and public access via an OCI Load Balancer.
Overview
n8n (“nodemation”) is an open-source workflow automation tool that lets you visually connect services and automate tasks.
Oracle Kubernetes Engine (OKE) is a managed Kubernetes service on OCI that provides scalable, highly available clusters with integrated networking and load balancing.
In this guide, you’ll:
Create a namespace and persistent volume for n8n data
Deploy n8n to OKE
Expose it through an OCI LoadBalancer
Fix permission and cookie issues for production readiness
Prerequisites
Before you begin, ensure you have:
An existing OKE cluster (v1.34.1 or newer)
kubectlconfigured to connect to the cluster (kubectl get nodesworks)One public subnet OCID (for the OCI Load Balancer)
Basic understanding of Kubernetes YAML manifests
Step 1 — Create the Namespace and Persistent Volume Claim
Create a namespace for organizational isolation and a PVC to persist n8n configuration and workflows.
apiVersion: v1
kind: Namespace
metadata:
name: n8n
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: n8n-pvc
namespace: n8n
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
Apply it:
kubectl apply -f n8n-storage.yaml
Step 2 — Create Authentication Secret
Create a Kubernetes secret for n8n’s basic authentication.
apiVersion: v1
kind: Secret
metadata:
name: n8n-secret
namespace: n8n
type: Opaque
stringData:
username: admin
password: strongpassword123
Apply it:
kubectl apply -f n8n-secret.yaml
Step 3 — Deploy n8n Application
Below is a production-ready Deployment that:
Uses the fully qualified Docker image
Mounts the PVC for persistence
Fixes file-permission issues (
fsGroup: 1000)Disables secure cookie enforcement (for HTTP access via LoadBalancer)
apiVersion: apps/v1
kind: Deployment
metadata:
name: n8n
namespace: n8n
spec:
replicas: 1
selector:
matchLabels:
app: n8n
template:
metadata:
labels:
app: n8n
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: n8n
image: docker.io/n8nio/n8n:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5678
env:
- name: N8N_BASIC_AUTH_ACTIVE
value: "true"
- name: N8N_BASIC_AUTH_USER
valueFrom:
secretKeyRef:
name: n8n-secret
key: username
- name: N8N_BASIC_AUTH_PASSWORD
valueFrom:
secretKeyRef:
name: n8n-secret
key: password
- name: N8N_HOST
value: "n8n"
- name: N8N_PORT
value: "5678"
- name: N8N_PROTOCOL
value: "http"
- name: N8N_SECURE_COOKIE
value: "false"
- name: GENERIC_TIMEZONE
value: "Asia/Kolkata"
- name: TZ
value: "Asia/Kolkata"
volumeMounts:
- name: n8n-data
mountPath: /home/node/.n8n
volumes:
- name: n8n-data
persistentVolumeClaim:
claimName: n8n-pvc
Apply it:
kubectl apply -f n8n-deployment.yaml
Step 4 — Expose n8n via OCI LoadBalancer
Now expose n8n externally so you can access it through a public IP.
apiVersion: v1
kind: Service
metadata:
name: n8n-service
namespace: n8n
spec:
type: LoadBalancer
selector:
app: n8n
ports:
- name: http
port: 80
targetPort: 5678
protocol: TCP
Apply it:
kubectl apply -f n8n-service.yaml
After a few minutes:
kubectl get svc -n n8n
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
n8n-service LoadBalancer 10.96.123.45 140.238.xxx.xxx 80:31234/TCP 2m
Step 5 — Verify and Troubleshoot
Check pod logs:
kubectl logs -f -n n8n deploy/n8n
Expected startup log:
Editor is now accessible:
▸ http://0.0.0.0:5678/
If you see permission errors like EACCES: permission denied, confirm your fsGroup: 1000 is present in the YAML.
If you get a “secure cookie” warning, ensure N8N_SECURE_COOKIE=false is set, or enable HTTPS on your LoadBalancer.
Step 6 — (Optional) Add HTTPS with OCI LoadBalancer
For production, you can enable HTTPS by adding these annotations to the Service:
metadata:
annotations:
service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/oci-load-balancer-tls-secret: "n8n/n8n-tls"
Then create a TLS secret:
kubectl create secret tls n8n-tls \
--cert=server.crt --key=server.key -n n8n
Step 7 — (Optional) Use PostgreSQL for Production
For better performance and reliability, you can connect n8n to an external PostgreSQL (or OCI Autonomous Database):
- name: DB_TYPE
value: "postgresdb"
- name: DB_POSTGRESDB_HOST
value: "<your-db-host>"
- name: DB_POSTGRESDB_USER
value: "<your-db-user>"
- name: DB_POSTGRESDB_PASSWORD
value: "<your-db-password>"
- name: DB_POSTGRESDB_DATABASE
value: "n8n"

Summary
| Component | Purpose |
| Namespace | Isolates resources |
| PVC | Persists workflow data |
| Secret | Stores login credentials |
| Deployment | Runs n8n container securely |
| Service (LoadBalancer) | Exposes n8n externally |
| SecurityContext | Fixes PVC permission issues |
| Optional TLS | Enables HTTPS via OCI LoadBalancer |






