first commit
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
# One-off Job to create the "n8n" database on the shared Postgres instance.
|
||||
# Mirrors k8s/miniflux/create-db-job.yaml.
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: create-db-n8n
|
||||
namespace: postgres
|
||||
spec:
|
||||
backoffLimit: 3
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: create-db
|
||||
image: postgres:18-alpine
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: postgres-admin
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
psql "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres-postgresql:5432/postgres" \
|
||||
-tc "SELECT 1 FROM pg_database WHERE datname = 'n8n'" | grep -q 1 \
|
||||
|| psql "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres-postgresql:5432/postgres" \
|
||||
-c "CREATE DATABASE n8n"
|
||||
@@ -0,0 +1,97 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: n8n
|
||||
namespace: watch
|
||||
labels:
|
||||
app.kubernetes.io/name: n8n
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate # single ReadWriteOnce PVC, avoid two pods mounting it at once
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: n8n
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: n8n
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 1000 # matches the "node" user baked into the n8n image
|
||||
containers:
|
||||
- name: n8n
|
||||
image: n8nio/n8n:latest
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 5678
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: n8n-credentials
|
||||
env:
|
||||
- name: DB_TYPE
|
||||
value: postgresdb
|
||||
- name: DB_POSTGRESDB_HOST
|
||||
value: postgres-postgresql.postgres.svc.cluster.local
|
||||
- name: DB_POSTGRESDB_PORT
|
||||
value: "5432"
|
||||
- name: DB_POSTGRESDB_DATABASE
|
||||
value: n8n
|
||||
- name: N8N_HOST
|
||||
value: n8n.sttlab.pc
|
||||
- name: N8N_PORT
|
||||
value: "5678"
|
||||
- name: N8N_PROTOCOL
|
||||
value: https
|
||||
- name: N8N_WEBHOOK_URL
|
||||
value: https://n8n.sttlab.pc/
|
||||
- name: GENERIC_TIMEZONE
|
||||
value: Europe/Paris
|
||||
- name: TZ
|
||||
value: Europe/Paris
|
||||
- name: N8N_RESTRICT_FILE_ACCESS_TO
|
||||
value: "/data" # single path only (no list support)
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /home/node/.n8n
|
||||
- name: digest-workspace
|
||||
mountPath: /data # dedicated volume for Read/Write File nodes, separate from n8n's own
|
||||
# internal directory (which n8n always blocks file-node access to, regardless of
|
||||
# N8N_RESTRICT_FILE_ACCESS_TO, via N8N_BLOCK_FILE_ACCESS_TO_N8N_FILES)
|
||||
- name: digest-prompt
|
||||
mountPath: /data/prompts/digest.md
|
||||
subPath: digest.md # avoids the ConfigMap symlink indirection, which trips n8n's file-access allowlist check
|
||||
readOnly: true
|
||||
- name: digest-prompt
|
||||
mountPath: /data/prompts/editorial.md
|
||||
subPath: editorial.md
|
||||
readOnly: true
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 2Gi
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 20
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: n8n-data
|
||||
- name: digest-workspace
|
||||
persistentVolumeClaim:
|
||||
claimName: n8n-digest-workspace
|
||||
- name: digest-prompt
|
||||
configMap:
|
||||
name: n8n-digest-prompt
|
||||
@@ -0,0 +1,20 @@
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: n8n
|
||||
namespace: watch
|
||||
spec:
|
||||
gatewayClassName: envoy
|
||||
listeners:
|
||||
- name: https
|
||||
protocol: HTTPS
|
||||
port: 443
|
||||
hostname: n8n.sttlab.pc
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: Same
|
||||
tls:
|
||||
mode: Terminate
|
||||
certificateRefs:
|
||||
- kind: Secret
|
||||
name: sttlab-pc-tls
|
||||
@@ -0,0 +1,21 @@
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: n8n
|
||||
namespace: watch
|
||||
spec:
|
||||
parentRefs:
|
||||
- group: gateway.networking.k8s.io
|
||||
kind: Gateway
|
||||
name: n8n
|
||||
hostnames:
|
||||
- n8n.sttlab.pc
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- kind: Service
|
||||
name: n8n
|
||||
port: 80
|
||||
@@ -0,0 +1,20 @@
|
||||
# Copy to miniflux-token-secret.yaml, fill in the real token, and apply with:
|
||||
# kubectl apply -f miniflux-token-secret.yaml
|
||||
# Never commit the filled-in file to git.
|
||||
#
|
||||
# Generate the token in the Miniflux UI under Settings -> API Keys (no
|
||||
# public REST endpoint creates one). Kept here as the source of truth /
|
||||
# backup; the digest workflow itself should use an n8n "Header Auth"
|
||||
# credential (header name X-Auth-Token) created in the n8n UI from these
|
||||
# same values, not a raw env var — n8n blocks $env access from workflow
|
||||
# expressions by default (N8N_BLOCK_ENV_ACCESS_IN_NODE), so this Secret is
|
||||
# not wired into the n8n Deployment's envFrom.
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: miniflux-api-token
|
||||
namespace: watch
|
||||
type: Opaque
|
||||
stringData:
|
||||
MINIFLUX_URL: https://miniflux.sttlab.pc/v1/
|
||||
MINIFLUX_API_TOKEN: changeme
|
||||
@@ -0,0 +1,26 @@
|
||||
# Persists /home/node/.n8n (encryption key backup, local binary data cache,
|
||||
# community nodes). Workflow/execution data itself lives in Postgres.
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: n8n-data
|
||||
namespace: watch
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
---
|
||||
# Separate volume for Read/Write File nodes (digest prompt + output), kept
|
||||
# apart from n8n-data (n8n's own internal directory, which n8n always
|
||||
# blocks file-node access to regardless of N8N_RESTRICT_FILE_ACCESS_TO).
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: n8n-digest-workspace
|
||||
namespace: watch
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copy to secret.yaml, fill in real values, and apply with:
|
||||
# kubectl apply -f secret.yaml
|
||||
# Never commit the filled-in secret.yaml to git.
|
||||
#
|
||||
# DB_POSTGRESDB_USER/PASSWORD must match k8s/postgres/secret.yaml.
|
||||
#
|
||||
# N8N_ENCRYPTION_KEY encrypts credentials stored in the n8n database.
|
||||
# Generate once with `openssl rand -hex 24` and never change it afterwards
|
||||
# (rotating it locks n8n out of every credential already saved).
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: n8n-credentials
|
||||
namespace: watch
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_POSTGRESDB_USER: postgres
|
||||
DB_POSTGRESDB_PASSWORD: changeme
|
||||
N8N_ENCRYPTION_KEY: changeme
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: n8n
|
||||
namespace: watch
|
||||
labels:
|
||||
app.kubernetes.io/name: n8n
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/name: n8n
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 5678
|
||||
Reference in New Issue
Block a user