Compare commits

..
45 Commits
Author SHA1 Message Date
khwezi 9a8805b976 Update docker-stacks/app-server/infisical.yml 2026-07-18 09:41:25 +02:00
khwezi b12bd4f6c0 Add docker-stacks/app-server/infisical.yml 2026-07-18 09:35:03 +02:00
khwezi 480a4fd28b Delete .vscode/settings.json 2026-07-18 09:22:07 +02:00
khwezi 4507db4d5a Changed port mappings of penpot frontend 2026-06-20 21:14:54 +02:00
khwezi c2204a345e Simplified frontend ebv var injection 2026-06-20 21:10:36 +02:00
khwezi b90103f503 Updated frontend env var injection 2026-06-20 21:09:11 +02:00
khwezi 1bfa151ff0 Refactored flags 2026-06-20 17:20:25 +02:00
khwezi 19653b0fdf Refactored penpot to use its own redis instance 2026-06-20 17:07:37 +02:00
khwezi 909f636cb0 Refactored penpot to use its own database 2026-06-20 17:02:40 +02:00
khwezi 5647189bba Added startup flag to backend 2026-06-20 16:55:00 +02:00
khwezi 1d78a1c148 Merged my code wih official compose file 2026-06-20 16:25:30 +02:00
khwezi dd3516bc13 Added email and s3 configs 2026-06-20 10:32:04 +02:00
khwezi c15b43b7b3 Refactored to handle schema migrations 2026-06-19 17:40:21 +02:00
khwezi 5910220bde Removed docuseal tag 2026-06-19 17:37:38 +02:00
khwezi 2231469493 Using latest image tag 2026-06-19 17:36:20 +02:00
khwezi 70c73bd4aa Using specific docuseal docker image 2026-06-19 17:35:16 +02:00
khwezi 6b518f310a Added chromim settings 2026-06-19 17:31:44 +02:00
khwezi 8bb6d3803f Added exporter secret key to backend 2026-06-19 17:27:36 +02:00
khwezi 979da4a20b Reverted exporter env mappings 2026-06-19 17:25:38 +02:00
khwezi 12d6613160 Added penpot chromium flags 2026-06-19 17:21:56 +02:00
khwezi 637d026103 Provided sanbox flag 2026-06-19 17:20:06 +02:00
khwezi a6c5471805 Refactored penpod exporter redis connection 2026-06-19 17:16:59 +02:00
khwezi 509608722b Added missing exporter env vars for penpot 2026-06-19 17:09:26 +02:00
khwezi 5abd91e66c Added shared penpot network 2026-06-19 17:01:26 +02:00
khwezi 88e3af666c Added shared network and exporter to penpot 2026-06-19 17:00:14 +02:00
khwezi 9e0324d9c3 Changed penpot port to 8084 2026-06-19 16:45:59 +02:00
khwezi 439feb92ef Changed docuseal port to 3001 2026-06-19 16:45:18 +02:00
= 7ba7e02534 Merge branch 'main' of https://gitea.khongisa.co.za/MngomaLab/automation 2026-06-19 14:24:20 +00:00
= 5cc9b4929a Refactored droneci 2026-06-19 14:21:51 +00:00
khwezi 72d1ddfce6 Added penpot.yml 2026-06-19 15:33:39 +02:00
khwezi c0e33e039d Added docuseal.yml 2026-06-19 15:32:56 +02:00
= 546e2f621c Garage Admin Ui works very stable, web access and object security is also in place 2026-05-18 21:22:58 +00:00
= 396e9e9e7e Added garag.yml as my s3 compatible object store 2026-05-18 19:32:21 +00:00
= 631ef583f5 Removed gitea and version lines 2026-05-09 08:39:44 +00:00
= d48abb626e Fixed sytax issue with service listing 2026-05-09 08:38:47 +00:00
= ef6df93bd2 Fixed typo 2026-05-09 08:36:01 +00:00
= b0dee982ac Refactored droneci user create to be a string literal 2026-05-09 08:13:52 +00:00
= c885cffdd2 Refactored DRONE_RPC_HOST=localhost 2026-05-09 08:08:22 +00:00
= e9862f7c3c Hardcoded rone username against gitea 2026-05-09 08:00:27 +00:00
= 5853440e1b Fixed droneci.yml syntax error 2026-05-09 07:55:29 +00:00
= 25506f6bd0 Added drone-ci to docker app server stacks 2026-05-09 07:31:51 +00:00
= 69c228997d added n8n 2026-05-02 16:50:55 +00:00
= 7e17336bcf Refactored to use v13 2026-05-02 10:46:51 +00:00
Khwezi Mngoma e5ef94def8 Changed dynamic config 2026-05-02 09:50:37 +02:00
Khwezi Mngoma 3b3f4139aa Changed oltp-http ingresroute 2026-05-02 09:49:57 +02:00
10 changed files with 713 additions and 142 deletions
-5
View File
@@ -1,5 +0,0 @@
{
"yaml.schemas": {
"kubernetes://schema/traefik.io/v1alpha1%40ingressroute": "file:///mnt/c/Users/Admin/source/repos/mngomalab/k3s/stacks/droneci.yml"
}
}
+24
View File
@@ -0,0 +1,24 @@
services:
docuseal:
image: docuseal/docuseal
restart: always
environment:
- DATABASE_URL=${DATABASE_URL}
- PORT=3000
- HOST=${PUBLIC_URL}
- SECRET_KEY_BASE=${SECRET_KEY_BASE}
- RAILS_ENV=production
- SKIP_MIGRATION_VALIDATION=true
- SMTP_USERNAME=${SMTP_USERNAME}
- SMTP_PASSWORD=${SMTP_PASSWORD}
- SMTP_ADDRESS=${SMTP_ADDRESS}
- SMTP_FROM=${SMTP_FROM}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_REGION=${AWS_REGION}
- S3_ATTACHMENTS_BUCKET=${S3_ATTACHMENTS_BUCKET}
ports:
- "3001:3000"
volumes:
- ./docuseal_data:/data
+43
View File
@@ -0,0 +1,43 @@
services:
drone:
image: drone/drone:2
container_name: drone
ports:
- "8080:80"
environment:
- DRONE_GITEA_SERVER=${GITEA_ADDRESS}
- DRONE_GITEA_CLIENT_ID=${DRONE_GITEA_CLIENT_ID}
- DRONE_GITEA_CLIENT_SECRET=${DRONE_GITEA_CLIENT_SECRET}
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
- DRONE_SERVER_HOST=${DRONE_SERVER_ADDRESS}
- DRONE_SERVER_PROTO=${DRONE_SERVER_PROTO}
- DRONE_USER_CREATE=username:drone,admin:true
volumes:
- drone-data:/data
restart: unless-stopped
networks:
- droneci-network
drone-runner:
image: drone/drone-runner-docker:1
container_name: drone-runner
environment:
- DRONE_RPC_PROTO=http
- DRONE_RPC_HOST=drone
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
- DRONE_RUNNER_CAPACITY=2
- DRONE_RUNNER_NAME=local-runner
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- drone
restart: unless-stopped
networks:
- droneci-network
volumes:
drone-data:
networks:
droneci-network:
driver: bridge
+56
View File
@@ -0,0 +1,56 @@
version: "3"
services:
backend:
container_name: infisical-backend
restart: unless-stopped
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
image: infisical/infisical:latest # PIN THIS TO A SPECIFIC TAG
pull_policy: always
env_file: .env
ports:
- 80:8080
environment:
- NODE_ENV=production
networks:
- infisical
redis:
image: redis
container_name: infisical-dev-redis
env_file: .env
restart: always
environment:
- ALLOW_EMPTY_PASSWORD=yes
networks:
- infisical
volumes:
- redis_data:/data
db:
container_name: infisical-db
image: postgres:14-alpine
restart: always
env_file: .env
volumes:
- pg_data:/var/lib/postgresql/data
networks:
- infisical
healthcheck:
test: "pg_isready --username=${POSTGRES_USER} && psql --username=${POSTGRES_USER} --list"
interval: 5s
timeout: 10s
retries: 10
volumes:
pg_data:
driver: local
redis_data:
driver: local
networks:
infisical:
+135
View File
@@ -0,0 +1,135 @@
x-flags: &penpot-flags
# Merged disable-sandbox into the flags array to protect the headless engine
# PENPOT_FLAGS: disable-email-verification enable-smtp enable-prepl-server disable-secure-session-cookies enable-mcp disable-sandbox enable-login-with-password
PENPOT_FLAGS: disable-email-verification enable-smtp enable-prepl-server disable-secure-session-cookies disable-sandbox enable-login-with-password
x-uri: &penpot-public-uri
PENPOT_PUBLIC_URI: ${PENPOT_PUBLIC_URI}
x-body-size: &penpot-http-body-size
PENPOT_HTTP_SERVER_MAX_BODY_SIZE: 367001600
PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE: 367001600
x-secret-key: &penpot-secret-key
PENPOT_SECRET_KEY: ${PENPOT_SECRET_KEY}
networks:
penpot-net:
driver: bridge
volumes:
penpot_assets:
penpot_postgres_v15:
services:
penpot-frontend:
image: "penpotapp/frontend:${PENPOT_VERSION:-latest}"
restart: always
ports:
- "8084:8080"
volumes:
- penpot_assets:/opt/data/assets
depends_on:
- penpot-backend
- penpot-exporter
- penpot-mcp
networks:
- penpot-net
environment:
<<: [*penpot-flags, *penpot-http-body-size, *penpot-public-uri]
penpot-backend:
image: "penpotapp/backend:${PENPOT_VERSION:-latest}"
restart: always
volumes:
- penpot_assets:/opt/data/assets
networks:
- penpot-net
ports:
- "6060:6060"
depends_on:
penpot-postgres:
condition: service_healthy # Wait for database stability
penpot-valkey:
condition: service_healthy # Wait for internal caching layer stability
environment:
<< : [*penpot-flags, *penpot-public-uri, *penpot-http-body-size, *penpot-secret-key]
# Security Handshake Key for internal Exporter validation routines
PENPOT_EXPORTER_SECRET_KEY: ${PENPOT_EXPORTER_SECRET_KEY}
## Local Internal Database connection parameters
PENPOT_DATABASE_URI: postgresql://penpot-postgres/penpot
PENPOT_DATABASE_USERNAME: penpot
PENPOT_DATABASE_PASSWORD: penpot
## Local Caching Layer connection parameter
PENPOT_REDIS_URI: redis://penpot-valkey/0
## Storage Settings
PENPOT_OBJECTS_STORAGE_BACKEND: fs
PENPOT_OBJECTS_STORAGE_FS_DIRECTORY: /opt/data/assets
## Telemetry & Optional settings
PENPOT_TELEMETRY_ENABLED: "false"
penpot-mcp:
image: "penpotapp/mcp:${PENPOT_VERSION:-latest}"
restart: always
networks:
- penpot-net
penpot-exporter:
image: "penpotapp/exporter:${PENPOT_VERSION:-latest}"
restart: always
shm_size: '2gb' # Protects Puppeteer rendering processes from memory crashes
depends_on:
penpot-valkey:
condition: service_healthy
networks:
- penpot-net
environment:
<< : [*penpot-secret-key]
PENPOT_EXPORTER_SECRET_KEY: ${PENPOT_EXPORTER_SECRET_KEY}
PENPOT_PUBLIC_URI: http://penpot-frontend:8080
## Local Caching Layer connections for the exporter sub-engine
PENPOT_REDIS_URI: redis://penpot-valkey/0
PENPOT_REDIS_URL: redis://penpot-valkey/0
PENPOT_FLAGS: disable-sandbox
# Integrated isolated Database Service
penpot-postgres:
image: "postgres:15"
restart: always
stop_signal: SIGINT
networks:
- penpot-net
volumes:
- penpot_postgres_v15:/var/lib/postgresql/data
environment:
- POSTGRES_INITDB_ARGS=--data-checksums
- POSTGRES_DB=penpot
- POSTGRES_USER=penpot
- POSTGRES_PASSWORD=penpot
healthcheck:
test: ["CMD-SHELL", "pg_isready -U penpot"]
interval: 2s
timeout: 10s
retries: 5
start_period: 2s
# Integrated isolated Caching Engine (Valkey drop-in for Redis)
penpot-valkey:
image: valkey/valkey:8.1
restart: always
networks:
- penpot-net
environment:
- VALKEY_EXTRA_FLAGS=--maxmemory 128mb --maxmemory-policy volatile-lfu
healthcheck:
test: ["CMD-SHELL", "valkey-cli ping | grep PONG"]
interval: 1s
timeout: 3s
retries: 5
start_period: 3s
@@ -1,91 +0,0 @@
http:
middlewares:
nexus-buffer:
buffering:
maxRequestBodyBytes: 0
memRequestBodyBytes: 2097152 # 2MB
crowdsec:
plugin:
crowdsec:
crowdsecAppsecBodyLimit: 0
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
routers:
nexus-docker-router:
rule: "Host(`nexus.khongisa.co.za`) && PathPrefix(`/v2`)"
service: api-service # Or whichever service points to Pangolin port 3000/3001
entryPoints:
- websecure
middlewares:
- nexus-buffer
- badger
tls:
certResolver: letsencrypt
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`khongisa.co.za`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
- badger
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`khongisa.co.za`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`khongisa.co.za`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`khongisa.co.za`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
tcp:
serversTransports:
pp-transport-v1:
proxyProtocol:
version: 1
pp-transport-v2:
proxyProtocol:
version: 2
+47 -45
View File
@@ -35,6 +35,7 @@ spec:
requests:
storage: 1Gi
---
# 1. Aspire Dashboard Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -50,9 +51,11 @@ spec:
labels:
app: aspire-dashboard
spec:
securityContext:
fsGroup: 1000
containers:
- name: dashboard
image: mcr.microsoft.com/dotnet/aspire-dashboard:8.0
image: mcr.microsoft.com/dotnet/aspire-dashboard:13
ports:
- name: ui
containerPort: 18888
@@ -61,30 +64,20 @@ spec:
- name: otlp-http
containerPort: 18890
env:
- name: DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS
value: "true"
- name: ASPNETCORE_URLS
value: "http://0.0.0.0:18888"
- name: DOTNET_DASHBOARD_OTLP_ENDPOINT_URL
value: "http://0.0.0.0:18889"
- name: DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL
value: "http://0.0.0.0:18890"
- name: Dashboard__ApplicationName
value: "Khongisa Monitoring"
- name: Dashboard__Frontend__EndpointUrls
value: "http://0.0.0.0:18888"
- name: Dashboard__Otlp__EndpointUrl
value: "http://0.0.0.0:18889"
- name: Dashboard__Otlp__HttpEndpointUrl
value: "http://0.0.0.0:18890"
- name: ASPIRE_ALLOW_UNSECURED_TRANSPORT
value: "true"
- name: Dashboard__Frontend__AuthMode
value: "BrowserToken"
- name: Dashboard__Frontend__BrowserToken
valueFrom:
secretKeyRef:
name: aspire-dashboard-auth
key: dashboard-token
- name: Dashboard__Otlp__AuthMode
value: "ApiKey"
- name: Dashboard__Otlp__PrimaryApiKey
valueFrom:
secretKeyRef:
name: aspire-dashboard-auth
key: otlp-api-key
- name: Dashboard__TelemetryLimits__MaxLogCount
value: "50000"
- name: Dashboard__ResourceServiceClient__AuthMode
value: "Unsecured"
volumeMounts:
- name: aspire-keys
mountPath: /home/app/.aspnet/DataProtection-Keys
@@ -92,7 +85,9 @@ spec:
- name: aspire-keys
persistentVolumeClaim:
claimName: aspire-dashboard-pvc
---
# 2. UI & Telemetry Service (Combined)
apiVersion: v1
kind: Service
metadata:
@@ -106,43 +101,50 @@ spec:
- name: ui
port: 18888
targetPort: 18888
- name: otlp-grpc
port: 18889
targetPort: 18889
- name: otlp-http
port: 18890
targetPort: 18890
---
# 3. Path Stripping Middleware
# This removes /otlp-http from the URL before sending it to the pod
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: aspire-otlp-strip-prefix
namespace: aspire
spec:
stripPrefix:
prefixes:
- /otlp-http
---
# 4. IngressRoute (Updated for UI and Telemetry Path)
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: aspire-dashboard-web
name: aspire-dashboard-ui-web
namespace: aspire
spec:
entryPoints:
- websecure
routes:
# Telemetry Route: Catches your app traffic
- match: Host(`aspire.khongisa.co.za`) && PathPrefix(`/otlp-http`)
kind: Rule
priority: 20
middlewares:
- name: aspire-otlp-strip-prefix
services:
- name: aspire-dashboard-service
port: 18890
# UI Route: Standard access
- match: Host(`aspire.khongisa.co.za`) && PathPrefix(`/`)
kind: Rule
priority: 10
services:
- name: aspire-dashboard-service
port: 18888
- match: Host(`aspire.khongisa.co.za`) && PathPrefix(`/otlp`)
kind: Rule
middlewares:
- name: aspire-strip-prefix
services:
- name: aspire-dashboard-service
port: 4318
tls:
secretName: aspire-cert-secret
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: aspire-strip-prefix
namespace: aspire
spec:
stripPrefix:
prefixes:
- /otlp
secretName: aspire-cert-secret
+1 -1
View File
@@ -45,7 +45,7 @@ spec:
storageClassName: nfs-storage
resources:
requests:
storage: 5Gi
storage: 10Gi
---
apiVersion: v1
kind: Secret
+207
View File
@@ -0,0 +1,207 @@
apiVersion: v1
kind: Namespace
metadata:
name: garage
---
apiVersion: v1
kind: Secret
metadata:
name: garage-secrets
namespace: garage
type: Opaque
data:
GARAGE_RPC_SECRET: "Yjk2YzRjZDE2ZDY4NDFjYTZhZTEwNDQxOGJiNTIxMDc4MTYyMzkyMzk4OGZiMWRmNWI0MmQzMmQzYmQwMGIwZQ=="
GARAGE_ADMIN_TOKEN: "c1dHNW8yc2E5eEp4NUVyM0NnWHF2T1VTSFhvZkZhejBwRWoyRzlyb1E1aERSRUdRVlZvQUZTRXY4aU1MUTZxTw=="
---
apiVersion: v1
kind: ConfigMap
metadata:
name: garage-config
namespace: garage
data:
garage.toml: |
metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
replication_factor = 1
rpc_bind_addr = "[::]:3901"
rpc_public_addr = "garage.garage.svc.cluster.local:3901"
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
# Leaving this blank removes the hostname restriction on the API port.
# This allows internal pods to use 'garage.garage.svc.cluster.local' AND
# external apps to use '192.168.1.177:30900' or 's3.khongisa.co.za' without signature errors.
root_domain = ""
[admin]
api_bind_addr = "[::]:3903"
admin_token = "sWG5o2sa9xJx5Er3CgXqvOUSHXofFaz0pEj2G9roQ5hDREGQVVoAFSEv8iMLQ6qO"
[s3_web]
bind_addr = "[::]:3902"
# This enforces that public web traffic matches 'test-bucket.s3.khongisa.co.za'
root_domain = ".cdn.khongisa.co.za"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: garage-data-pvc
namespace: garage
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs-storage
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: garage
namespace: garage
spec:
serviceName: "garage"
replicas: 1
selector:
matchLabels:
app: garage
template:
metadata:
labels:
app: garage
spec:
securityContext:
fsGroup: 999
containers:
- name: garage
image: dxflrs/garage:v2.3.0
args: ["/garage", "server"]
env:
- name: GARAGE_RPC_SECRET
valueFrom:
secretKeyRef:
name: garage-secrets
key: GARAGE_RPC_SECRET
ports:
- containerPort: 3900
name: s3-api
- containerPort: 3903
name: admin-api
- containerPort: 3902
name: s3-web
volumeMounts:
- name: config
mountPath: /etc/garage.toml
subPath: garage.toml
- name: data
mountPath: /var/lib/garage
volumes:
- name: config
configMap:
name: garage-config
- name: data
persistentVolumeClaim:
claimName: garage-data-pvc
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: garage-ui
namespace: garage
spec:
replicas: 1
selector:
matchLabels:
app: garage-ui
template:
metadata:
labels:
app: garage-ui
spec:
containers:
- name: garage-ui
image: khairul169/garage-webui:latest
ports:
- containerPort: 3909
env:
- name: API_BASE_URL
value: "http://garage:3903"
- name: S3_ENDPOINT_URL
value: "http://garage:3900"
- name: API_ADMIN_KEY
valueFrom:
secretKeyRef:
name: garage-secrets
key: GARAGE_ADMIN_TOKEN
volumeMounts:
- name: config
mountPath: /etc/garage.toml
subPath: garage.toml
volumes:
- name: config
configMap:
name: garage-config
---
apiVersion: v1
kind: Service
metadata:
name: garage
namespace: garage
spec:
selector:
app: garage
ports:
- name: s3-api
port: 3900
- name: admin-api
port: 3903
- name: s3-web
port: 3902
---
apiVersion: v1
kind: Service
metadata:
name: garage-ui
namespace: garage
spec:
selector:
app: garage-ui
ports:
- name: http
port: 80
targetPort: 3909
---
apiVersion: v1
kind: Service
metadata:
name: garage-external-nodeport
namespace: garage
spec:
type: NodePort
selector:
app: garage
ports:
- name: s3-api-external
port: 3900
targetPort: 3900
nodePort: 30900
- name: s3-web-external
port: 3902
targetPort: 3902
nodePort: 30902
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: garage-ui-external
namespace: garage
spec:
entryPoints: ["websecure"]
routes:
- match: Host(`s3.khongisa.co.za`)
kind: Rule
services:
- name: garage-ui
port: 80
+200
View File
@@ -0,0 +1,200 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: n8n
---
apiVersion: v1
kind: Secret
metadata:
name: n8n-secrets
namespace: n8n
type: Opaque
data:
# Base64 values from your previous manifest
N8N_ADMIN_USER: a2h3ZXpp
N8N_ADMIN_PASSWORD: cWVaVllWQ20wOEhaWmU=
POSTGRES_PASSWORD: RmJsV0xPTlM4alVjNUE=
N8N_ENCRYPTION_KEY: Tm90U2VjcmV0S2V5MTIzIQ==
N8N_TASKS_RUNNER_AUTH_TOKEN: bXktc2hhcmVkLXNlY3JldC10b2tlbi0xMjM=
---
apiVersion: v1
kind: ConfigMap
metadata:
name: n8n-config
namespace: n8n
data:
N8N_HOST: "n8n.khongisa.co.za"
N8N_PROTOCOL: "https"
NODE_ENV: "production"
WEBHOOK_URL: "https://n8n.khongisa.co.za/"
GENERIC_TIMEZONE: "Africa/Johannesburg"
DB_TYPE: "postgresdb"
DB_POSTGRESDB_HOST: "n8n-db-service"
DB_POSTGRESDB_PORT: "5432"
DB_POSTGRESDB_DATABASE: "n8n_db"
DB_POSTGRESDB_USER: "n8n_user"
N8N_PROXY_HOPS: "1"
# DEFINITIVE FIX: Force n8n to listen on all interfaces
N8N_LISTEN_ADDRESS: "0.0.0.0"
N8N_PORT: "5678"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: n8n-data-pvc
namespace: n8n
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: n8n-db-pvc
namespace: n8n
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
---
# Database Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: n8n-db
namespace: n8n
spec:
replicas: 1
selector:
matchLabels:
app: n8n-db
template:
metadata:
labels:
app: n8n-db
spec:
containers:
- name: postgres
image: postgres:14-alpine
env:
- name: POSTGRES_USER
value: "n8n_user"
- name: POSTGRES_DB
value: "n8n_db"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: n8n-secrets
key: POSTGRES_PASSWORD
ports:
- containerPort: 5432
volumeMounts:
- name: db-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: db-storage
persistentVolumeClaim:
claimName: n8n-db-pvc
---
# Database Internal Service
apiVersion: v1
kind: Service
metadata:
name: n8n-db-service
namespace: n8n
spec:
ports:
- port: 5432
selector:
app: n8n-db
---
# n8n Application Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: n8n
namespace: n8n
spec:
replicas: 1
selector:
matchLabels:
app: n8n-app # Standardized label selector
template:
metadata:
labels:
app: n8n-app # Matches selector and service
spec:
containers:
- name: n8n
image: docker.n8n.io/n8nio/n8n:latest
ports:
- containerPort: 5678
- containerPort: 5679 # Explicitly open the Task Broker port
envFrom:
- configMapRef:
name: n8n-config
env:
# DEFINITIVE FIX: Align communication between main process and Task Runner
- name: N8N_TASKS_RUNNER_BROKER_HOST
value: "127.0.0.1"
- name: N8N_TASKS_RUNNER_BROKER_PORT
value: "5679"
- name: N8N_TASKS_RUNNER_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: n8n-secrets
key: N8N_TASKS_RUNNER_AUTH_TOKEN
# Database and Admin overrides
- name: DB_POSTGRESDB_PASSWORD
valueFrom:
secretKeyRef:
name: n8n-secrets
key: POSTGRES_PASSWORD
- name: N8N_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: n8n-secrets
key: N8N_ENCRYPTION_KEY
- name: N8N_USER_MANAGEMENT_ADMIN_USER
valueFrom:
secretKeyRef:
name: n8n-secrets
key: N8N_ADMIN_USER
- name: N8N_USER_MANAGEMENT_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: n8n-secrets
key: N8N_ADMIN_PASSWORD
- name: N8N_SECURE_COOKIE
value: "false"
- name: N8N_COOKIES_SAME_SITE
value: "lax"
- name: N8N_PROXY_HOPS
value: "1"
volumeMounts:
- name: n8n-data
mountPath: /home/node/.n8n
volumes:
- name: n8n-data
persistentVolumeClaim:
claimName: n8n-data-pvc
---
# NodePort Service
apiVersion: v1
kind: Service
metadata:
name: n8n-service
namespace: n8n
spec:
type: NodePort
selector:
app: n8n-app # Correctly targets the refactored Deployment labels
ports:
- protocol: TCP
port: 5678
targetPort: 5678
nodePort: 30567