From 35c6c6f6542962b8a02ae741f1bcc55f7972f938 Mon Sep 17 00:00:00 2001 From: juvdiaz Date: Wed, 10 Jun 2026 10:38:50 -0600 Subject: [PATCH] Add n8n workflow app --- README.md | 8 ++- apps/heimdall/web-app.yaml | 7 +++ apps/n8n/ingress.yaml | 18 ++++++ apps/n8n/kustomization.yaml | 6 ++ apps/n8n/namespace.yaml | 4 ++ apps/n8n/web-app.yaml | 112 ++++++++++++++++++++++++++++++++++++ bootstrap/apps/variables.tf | 9 +++ lab.sh | 13 +++++ 8 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 apps/n8n/ingress.yaml create mode 100644 apps/n8n/kustomization.yaml create mode 100644 apps/n8n/namespace.yaml create mode 100644 apps/n8n/web-app.yaml diff --git a/README.md b/README.md index 7dfb0f1..9cd9b39 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ accidentally modify the cluster. listens on loopback inside the container, OPcache is enabled, and pre-rendered HTML handles the read-heavy pages - default apps are `container-registry`, `website-production`, - `demos-static`, `heimdall`, and `supply-chain-policy` + `demos-static`, `heimdall`, `n8n`, and `supply-chain-policy` 5. `bootstrap/edge` - connects to the OCI jump box @@ -332,6 +332,7 @@ Traefik's address: 192.168.100.240 lab2025.duckdns.org 192.168.100.240 demos.lab2025.duckdns.org 192.168.100.240 heimdall.lab2025.duckdns.org +192.168.100.240 n8n.lab2025.duckdns.org 192.168.100.240 grafana.lab2025.duckdns.org 192.168.100.240 argocd.lab2025.duckdns.org ``` @@ -480,6 +481,11 @@ Because Heimdall does not support reverse-proxy subfolder hosting cleanly, it is exposed through the dedicated hostname `heimdall.lab2025.duckdns.org` rather than a `/heimdall/` path. +The `n8n` app runs in the `n8n` namespace with retained OpenEBS storage and is +exposed at `https://n8n.lab2025.duckdns.org`. It receives +`OLLAMA_BASE_URL=http://192.168.100.68:11434` so workflows can call the existing +Debian-host Ollama API for translation prewarming and batch jobs. + ## Storage OpenEBS provides the platform storage provisioner. Stateful Kubernetes apps use diff --git a/apps/heimdall/web-app.yaml b/apps/heimdall/web-app.yaml index 3cbdf59..954ea2f 100644 --- a/apps/heimdall/web-app.yaml +++ b/apps/heimdall/web-app.yaml @@ -81,6 +81,13 @@ data: "description": "Homelab service dashboard", "colour": "#7c3aed", "class": "Heimdall" + }, + { + "title": "n8n", + "url": "https://n8n.lab2025.duckdns.org/", + "description": "Workflow automation for translation jobs and homelab tasks", + "colour": "#ea4b71", + "class": "N8N" } ] seed.py: | diff --git a/apps/n8n/ingress.yaml b/apps/n8n/ingress.yaml new file mode 100644 index 0000000..18d216b --- /dev/null +++ b/apps/n8n/ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: n8n + namespace: n8n +spec: + ingressClassName: traefik + rules: + - host: n8n.lab2025.duckdns.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: n8n + port: + number: 80 diff --git a/apps/n8n/kustomization.yaml b/apps/n8n/kustomization.yaml new file mode 100644 index 0000000..4ee1166 --- /dev/null +++ b/apps/n8n/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - web-app.yaml + - ingress.yaml diff --git a/apps/n8n/namespace.yaml b/apps/n8n/namespace.yaml new file mode 100644 index 0000000..8389695 --- /dev/null +++ b/apps/n8n/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: n8n diff --git a/apps/n8n/web-app.yaml b/apps/n8n/web-app.yaml new file mode 100644 index 0000000..5bc3ba6 --- /dev/null +++ b/apps/n8n/web-app.yaml @@ -0,0 +1,112 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: n8n-data + namespace: n8n +spec: + accessModes: + - ReadWriteOnce + storageClassName: openebs-hostpath-retain + resources: + requests: + storage: 2Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: n8n + namespace: n8n + labels: + app: n8n +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: n8n + template: + metadata: + labels: + app: n8n + spec: + nodeSelector: + kubernetes.io/os: linux + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: OnRootMismatch + containers: + - name: n8n + image: n8nio/n8n:2.5.2 + imagePullPolicy: IfNotPresent + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + env: + - name: N8N_HOST + value: n8n.lab2025.duckdns.org + - name: N8N_PORT + value: "5678" + - name: N8N_PROTOCOL + value: https + - name: WEBHOOK_URL + value: https://n8n.lab2025.duckdns.org/ + - name: GENERIC_TIMEZONE + value: America/Mexico_City + - name: TZ + value: America/Mexico_City + - name: N8N_DIAGNOSTICS_ENABLED + value: "false" + - name: N8N_VERSION_NOTIFICATIONS_ENABLED + value: "false" + - name: N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS + value: "true" + - name: N8N_RUNNERS_ENABLED + value: "true" + - name: OLLAMA_BASE_URL + value: http://192.168.100.68:11434 + ports: + - containerPort: 5678 + name: http + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 90 + periodSeconds: 30 + resources: + requests: + cpu: 100m + memory: 384Mi + limits: + memory: 1Gi + volumeMounts: + - name: n8n-data + mountPath: /home/node/.n8n + volumes: + - name: n8n-data + persistentVolumeClaim: + claimName: n8n-data +--- +apiVersion: v1 +kind: Service +metadata: + name: n8n + namespace: n8n +spec: + ports: + - port: 80 + targetPort: http + selector: + app: n8n diff --git a/bootstrap/apps/variables.tf b/bootstrap/apps/variables.tf index 9dd36ff..da60f4a 100644 --- a/bootstrap/apps/variables.tf +++ b/bootstrap/apps/variables.tf @@ -66,6 +66,15 @@ variable "applications" { self_heal = true create_namespace = true } + n8n = { + project = "default" + path = "apps/n8n" + namespace = "n8n" + target_revision = "main" + prune = true + self_heal = true + create_namespace = true + } supply-chain-policy = { project = "default" path = "apps/supply-chain-policy" diff --git a/lab.sh b/lab.sh index abb0c70..df57979 100755 --- a/lab.sh +++ b/lab.sh @@ -191,6 +191,14 @@ adopt_apps_existing_resources() { "argoproj.io/v1alpha1" \ "Application" \ "heimdall" + adopt_tofu_kubernetes_manifest \ + "${stack}" \ + 'kubernetes_manifest.argocd_application["n8n"]' \ + "${namespace}" \ + "applications.argoproj.io" \ + "argoproj.io/v1alpha1" \ + "Application" \ + "n8n" adopt_tofu_kubernetes_manifest \ "${stack}" \ 'kubernetes_manifest.argocd_application["supply-chain-policy"]' \ @@ -3069,6 +3077,11 @@ apps() { wait_for_namespaced_resource heimdall deployment heimdall heimdall 300 wait_for_deployment_ready heimdall heimdall heimdall 300 + refresh_argocd_application n8n + wait_for_namespace n8n n8n 300 + wait_for_namespaced_resource n8n deployment n8n n8n 300 + wait_for_deployment_ready n8n n8n n8n 300 + echo "Application deployment successfully completed." }