Files
k8s-manifests/n8n/deployment-n8n.yaml
T
chemavxandClaude Opus 5 440eb5b6a1 n8n: dar permisos de reinicio al auto-restart de Uptime Kuma
El workflow "Uptime Kuma -> K8s Auto-Restart" lleva desde siempre sin poder
reiniciar nada: hacia el PATCH con el token de la ServiceAccount "default" del
namespace, que no tiene ni un permiso, y el API contestaba 403. Se iba entonces
por la rama de "reinicio fallido" y mandaba el aviso por Telegram -- que se
enviaba bien, y por eso los 23 "exitos" de workflow_statistics. La integracion
parecia viva y no lo estaba.

SA propia (n8n-restarter) en vez de la default, y un RoleBinding por namespace
en lugar de un ClusterRoleBinding: el webhook que dispara esto es publico y sin
autenticar, asi que el alcance se limita al SERVICE_MAP del workflow.

El ClusterRole incluye get ademas de patch porque el workflow relee el objeto a
los 60 s para comprobar readyReplicas (sin get: "Cannot read properties of
undefined"), y statefulsets ademas de deployments porque Gitea es lo primero.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 19:58:29 +00:00

124 lines
5.2 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: n8n
namespace: n8n
annotations:
# El operator de Infisical redespliega este Deployment cuando cambia
# n8n-secret-infisical (p.ej. rotación de GETXAPI_TOKEN) — sin kubectl manual.
secrets.infisical.com/auto-reload: "true"
spec:
replicas: 1
selector:
matchLabels:
app: n8n
# Single-replica n8n with a 485MB SQLite DB (+ active WAL) on a RWO local-path
# PVC: Recreate fully terminates the old pod (releasing the PVC and closing the
# SQLite-WAL) before the new pod starts — avoids two writers racing one DB file
# (RollingUpdate would surge a 2nd pod first).
strategy:
type: Recreate
template:
metadata:
labels:
app: n8n
spec:
# El workflow del auto-reinicio lee el token proyectado de ESTA SA para
# hablar con el API de K8s (ver rbac-restarter.yaml). Hasta el 2026-07-30
# heredaba la "default", que no tiene ningún permiso: 403 en cada intento.
serviceAccountName: n8n-restarter
securityContext:
fsGroup: 1000
runAsUser: 1000
containers:
- name: n8n
image: git.chemavx.xyz/chemavx/n8n:01d60680
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5678
env:
- name: N8N_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: n8n-secret-infisical
key: encryption-key
# Token getxapi (X autopost) — rotado 2026-07-09; el workflow lo lee
# con la expresión {{ $env.GETXAPI_TOKEN }}, nunca inline en el nodo.
- name: GETXAPI_TOKEN
valueFrom:
secretKeyRef:
name: n8n-secret-infisical
key: GETXAPI_TOKEN
# Token del bot @chemavx_bot (notificaciones) — rotado 2026-07-09.
# Lo consume el workflow "Health Check General" vía process.env,
# ya no hardcodeado. Fuente: Infisical homelab/prod/telegram.
- name: TELEGRAM_BOT_TOKEN
valueFrom:
secretKeyRef:
name: telegram-notify-infisical
key: TELEGRAM_BOT_TOKEN
- name: TELEGRAM_CHAT_ID
valueFrom:
secretKeyRef:
name: telegram-notify-infisical
key: TELEGRAM_CHAT_ID
# n8n ≥1.x bloquea $env en expresiones por defecto; sin esto el nodo
# HTTP del autopost no puede leer GETXAPI_TOKEN. Instancia single-user.
- name: N8N_BLOCK_ENV_ACCESS_IN_NODE
value: "false"
- name: N8N_HOST
value: n8n.chemavx.xyz
- name: N8N_PORT
value: "5678"
- name: N8N_PROTOCOL
value: https
- name: WEBHOOK_URL
value: https://n8n.chemavx.xyz/
- name: N8N_USER_FOLDER
value: /home/node/.n8n
- name: NODE_FUNCTION_ALLOW_EXTERNAL
value: "*"
# ALLOW_EXTERNAL es para paquetes npm; los módulos INTERNOS de Node
# necesitan esta otra, y sin ella el task runner responde
# "Module 'https' is disallowed" (2026-07-30). Tenía tres workflows
# activos rotos sin que saltara nada: el auto-reinicio que dispara
# Uptime Kuma (último éxito 23-jul 07:51, se rompió al reiniciarse el
# pod esa tarde), "TLS Certs → Alerta Telegram" (último éxito 13-abr)
# y "Resumen Diario — Métricas K8s" (30 fallos, 0 éxitos).
# Lista explícita y no "*": es exactamente lo que piden los nodos Code
# de esos workflows, y si algún día hace falta otro módulo, que falle
# a la vista en vez de conceder todo por defecto.
- name: NODE_FUNCTION_ALLOW_BUILTIN
value: "fs,http,https"
- name: GENERIC_TIMEZONE
value: Europe/Madrid
- name: DB_TYPE
value: sqlite
- name: DB_SQLITE_DATABASE
value: /home/node/.n8n/database.sqlite
# No guardar el payload de las ejecuciones que salen BIEN (2026-07-30).
# La poda por edad ya venía activa de serie (336 h), así que la BD no
# se desbocaba; el problema era otro: de los 322 MB de execution_data,
# 246 MB eran las 3.436 tiradas VERDES de "Real Madrid RSS → Twitter",
# que corre cada 5 min y guarda 73 KB por vuelta. Los fallos, que son
# lo que se depura, ocupaban 2 MB. Y /data/n8n va entero en la lista
# CROWN del backup: eso viajaba a MEGA a diario y a B2 en las dos
# últimas copias — justo lo que reventó la cuota el 2026-07-25.
# Los errores se siguen guardando enteros (SAVE_ON_ERROR=all, defecto).
- name: EXECUTIONS_DATA_SAVE_ON_SUCCESS
value: none
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
volumeMounts:
- name: n8n-data
mountPath: /home/node/.n8n
volumes:
- name: n8n-data
persistentVolumeClaim:
claimName: n8n-pvc