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: 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