Skip to main content

Command Palette

Search for a command to run...

Deploying n8n on Oracle Kubernetes Engine (OKE)

Updated
4 min read
Deploying n8n on Oracle Kubernetes Engine (OKE)
P

I’m Pratik Borkar, a Technical Architecture specializing in Oracle Cloud Infrastructure (OCI) and Kubernetes. I have extensive experience designing, automating, and optimizing cloud environments using Terraform, CI/CD pipelines, and container orchestration tools. I enjoy sharing hands-on guides and real-world implementations that help engineers simplify cloud operations, improve scalability, and adopt Infrastructure as Code best practices. When I’m not automating infrastructure, I explore new DevOps tools, contribute to open-source projects, and write about cloud-native technologies.

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)

  • kubectl configured to connect to the cluster (kubectl get nodes works)

  • 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"

n8n

Summary

ComponentPurpose
NamespaceIsolates resources
PVCPersists workflow data
SecretStores login credentials
DeploymentRuns n8n container securely
Service (LoadBalancer)Exposes n8n externally
SecurityContextFixes PVC permission issues
Optional TLSEnables HTTPS via OCI LoadBalancer

More from this blog

P

Pratik N Borkar's blog

13 posts