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 |

