Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions openshift/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 n8n - Workflow Automation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
74 changes: 74 additions & 0 deletions openshift/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# n8n on OpenShift

Manifests in this folder deploy:

- `n8n` in namespace `n8n`
- PostgreSQL backend (`postgres:18`)
- Persistent volumes for both workloads
- OpenShift `Route` with TLS edge termination

Deployment is managed through `kustomization.yaml`.

## Files in this folder

- `namespace.yaml`: Creates namespace `n8n`
- `postgres-secret.yaml`: PostgreSQL credentials
- `postgres-configmap.yaml`: DB init script to create non-root DB user
- `postgres-claim0-persistentvolumeclaim.yaml`: PostgreSQL PVC (`300Gi`)
- `postgres-deployment.yaml`: PostgreSQL Deployment
- `postgres-service.yaml`: PostgreSQL headless Service (`postgres-service`)
- `n8n-claim0-persistentvolumeclaim.yaml`: n8n PVC (`2Gi`)
- `n8n-deployment.yaml`: n8n Deployment configured for PostgreSQL
- `n8n-service.yaml`: n8n ClusterIP Service
- `n8n-route.yaml`: Public OpenShift Route for n8n

## Prerequisites

- OpenShift cluster access (`oc` logged in)
- Dynamic storage class available for PVC provisioning
- DNS for route host (or host override for testing)

## Required changes before deploy

1. Update PostgreSQL credentials in `postgres-secret.yaml`.
2. Update route hostname in `n8n-route.yaml`:
- `spec.host: n8n.example.com`
3. Update n8n webhook URL in `n8n-deployment.yaml`:
- `WEBHOOK_URL=https://n8n.example.com/`

Recommended:

- Right-size PostgreSQL resources and storage (`300Gi` may be larger than needed in small labs).

## Deploy

From this folder:

```bash
oc apply -k .
```

## Verify

```bash
oc get all -n n8n
oc get pvc -n n8n
oc get route n8n-web -n n8n
```

Wait until both Deployments are available:

```bash
oc rollout status deploy/postgres -n n8n
oc rollout status deploy/n8n -n n8n
```

## Access

Open the route host configured in `n8n-route.yaml` (for example `https://n8n.example.com`).

## Cleanup

```bash
oc delete -k .
```
17 changes: 17 additions & 0 deletions openshift/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: n8n

resources:
- namespace.yaml
- postgres-configmap.yaml
- postgres-secret.yaml
- postgres-claim0-persistentvolumeclaim.yaml
- postgres-deployment.yaml
- postgres-service.yaml
- n8n-claim0-persistentvolumeclaim.yaml
- n8n-deployment.yaml
- n8n-service.yaml
- n8n-route.yaml
13 changes: 13 additions & 0 deletions openshift/n8n-claim0-persistentvolumeclaim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
service: n8n-claim0
name: n8n-claim0
namespace: n8n
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
73 changes: 73 additions & 0 deletions openshift/n8n-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: n8n
name: n8n
namespace: n8n
spec:
replicas: 1
selector:
matchLabels:
service: n8n
strategy:
type: Recreate
template:
metadata:
labels:
service: n8n
spec:
containers:
- command:
- /bin/sh
args:
- -c
- sleep 5; n8n start
env:
- name: DB_TYPE
value: postgresdb
- name: DB_POSTGRESDB_HOST
value: postgres-service.n8n.svc.cluster.local
- name: DB_POSTGRESDB_PORT
value: "5432"
- name: DB_POSTGRESDB_DATABASE
value: n8n
- name: DB_POSTGRESDB_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_NON_ROOT_USER
- name: DB_POSTGRESDB_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_NON_ROOT_PASSWORD
# OpenShift
- name: N8N_USER_FOLDER
value: /data
- name: N8N_PROTOCOL
value: https
- name: WEBHOOK_URL
value: https://n8n.example.com/
- name: N8N_PORT
value: "5678"
image: n8nio/n8n
name: n8n
ports:
- containerPort: 5678
resources:
requests:
memory: "250Mi"
limits:
memory: "500Mi"
volumeMounts:
- mountPath: /data
name: n8n-claim0
restartPolicy: Always
volumes:
- name: n8n-claim0
persistentVolumeClaim:
claimName: n8n-claim0
- name: postgres-secret
secret:
secretName: postgres-secret
17 changes: 17 additions & 0 deletions openshift/n8n-route.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
kind: Route
apiVersion: route.openshift.io/v1
metadata:
name: n8n-web
namespace: n8n
spec:
host: n8n.example.com
to:
kind: Service
name: n8n
weight: 100
port:
targetPort: 5678
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
wildcardPolicy: None
16 changes: 16 additions & 0 deletions openshift/n8n-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
service: n8n
name: n8n
namespace: n8n
spec:
type: ClusterIP
ports:
- name: "n8n"
port: 5678
targetPort: 5678
protocol: TCP
selector:
service: n8n
4 changes: 4 additions & 0 deletions openshift/namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: n8n
11 changes: 11 additions & 0 deletions openshift/postgres-claim0-persistentvolumeclaim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: postgresql-pv
namespace: n8n
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 300Gi
19 changes: 19 additions & 0 deletions openshift/postgres-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: init-data
namespace: n8n
data:
init-data.sh: |
#!/bin/bash
set -e;
if [ -n "${POSTGRES_NON_ROOT_USER:-}" ] && [ -n "${POSTGRES_NON_ROOT_PASSWORD:-}" ]; then
ESCAPED_PASSWORD="${POSTGRES_NON_ROOT_PASSWORD//\'/\'\'}"
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER "${POSTGRES_NON_ROOT_USER}" WITH PASSWORD '${ESCAPED_PASSWORD}';
GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO "${POSTGRES_NON_ROOT_USER}";
GRANT ALL ON SCHEMA public TO "${POSTGRES_NON_ROOT_USER}";
EOSQL
else
echo "SETUP INFO: No Environment variables given!"
fi
81 changes: 81 additions & 0 deletions openshift/postgres-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: postgres-n8n
name: postgres
namespace: n8n
spec:
replicas: 1
selector:
matchLabels:
service: postgres-n8n
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
service: postgres-n8n
spec:
containers:
- image: postgres:18
name: postgres
resources:
limits:
cpu: "4"
memory: 4Gi
requests:
cpu: "1"
memory: 2Gi
ports:
- containerPort: 5432
volumeMounts:
- name: postgresql-pv
mountPath: /var/lib/postgresql/data
- name: init-data
mountPath: /docker-entrypoint-initdb.d/init-n8n-user.sh
subPath: init-data.sh
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
- name: POSTGRES_DB
value: n8n
- name: POSTGRES_NON_ROOT_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_NON_ROOT_USER
- name: POSTGRES_NON_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_NON_ROOT_PASSWORD
- name: POSTGRES_HOST
value: postgres-service
- name: POSTGRES_PORT
value: '5432'
restartPolicy: Always
volumes:
- name: postgresql-pv
persistentVolumeClaim:
claimName: postgresql-pv
- name: postgres-secret
secret:
secretName: postgres-secret
- name: init-data
configMap:
name: init-data
defaultMode: 0744
12 changes: 12 additions & 0 deletions openshift/postgres-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
namespace: n8n
name: postgres-secret
type: Opaque
stringData:
POSTGRES_USER: changeUser
POSTGRES_PASSWORD: changePassword
POSTGRES_DB: n8n
POSTGRES_NON_ROOT_USER: changeUser
POSTGRES_NON_ROOT_PASSWORD: changePassword
16 changes: 16 additions & 0 deletions openshift/postgres-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
service: postgres-n8n
name: postgres-service
namespace: n8n
spec:
clusterIP: None
ports:
- name: "5432"
port: 5432
targetPort: 5432
protocol: TCP
selector:
service: postgres-n8n