Commit Graph
35 Commits
Author SHA1 Message Date
chemavxandClaude Opus 5 50f090bbea Cerrar el auto-reinicio: fail-closed, permisos por nombre y fallo visible
Tres agujeros que encontro una review adversarial de Codex sobre el trabajo
de ayer. Los tres verificados contra el fichero antes de tocar nada.

1. El webhook publico fallaba en ABIERTO. Con `optional: true` y un
   `if (secreto && ...)`, la ausencia del secreto equivalia a autorizacion:
   cualquier POST con heartbeat.status=0 y un monitor.name del mapa reiniciaba
   n8n, Gitea, ArgoCD, Vaultwarden o los blogs. El argumento para dejarlo asi
   era "que un despiste no te deje sin avisos", y era falso: el aviso de caida
   lo manda Kuma por su notificacion 1, directa, no por este webhook.
   Ahora el secreto es obligatorio (sin `optional`) y la puerta rechaza si
   falta. Secreto ausente da error ruidoso; cabecera que no casa, vacio.

2. El ClusterRole permitia patch sobre CUALQUIER deployment de 10 namespaces,
   y la SA va montada en el pod entero de n8n: cualquier workflow con un nodo
   Code heredaba eso. Ahora son Roles por namespace con resourceNames sobre
   los 12 workloads exactos del SERVICE_MAP.

3. El flujo daba exito aunque el PATCH fallara. `restartOk` se calculaba y se
   tiraba: `K8s API Check Status` construia un objeto nuevo sin el, y el IF
   final solo miraba `statusOk`. Un 403 sobre un servicio ya sano mandaba
   "reiniciado correctamente". Ahora hay rama de fallo tras el PATCH y el
   exito exige observedGeneration >= la generation que devolvio el PATCH.
   Se compara con >= porque selfHeal de ArgoCD revierte la anotacion y vuelve
   a subir la generation; con == daria un fallo falso.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 08:02:07 +00:00
chemavxandClaude Opus 5 125cdc9de0 n8n: cerrar el webhook del auto-reinicio con un secreto compartido
/webhook/uptime-kuma-restart es publico y sin autenticar. Mientras no reiniciaba
nada daba igual; desde hoy reinicia doce servicios, los dos blogs incluidos, asi
que cualquiera que diera con la ruta podia zarandear el cluster.

Uptime Kuma manda ahora la cabecera X-Kuma-Token (webhookAdditionalHeaders de la
notificacion "n8n Auto-Restart") y el primer nodo Code la compara con
KUMA_WEBHOOK_TOKEN antes de hacer nada.

La comprobacion falla en ABIERTO si el secreto no esta configurado en n8n: un
despiste de configuracion degrada al comportamiento de antes en vez de dejar de
avisar en silencio, que es el fallo que no se ve venir. Si esta configurado y no
coincide, se devuelve vacio: ni reinicio, ni Telegram, ni fila de error que se
pueda llenar a base de peticiones.

El secret n8n-kuma-webhook se crea con kubectl y NO esta en git; el env va con
optional: true para que la ausencia no impida arrancar el pod.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:25:17 +00:00
chemavxandClaude Opus 5 cbfbc8bf16 n8n: copia en git del workflow del auto-reinicio
Los workflows viven solo en la SQLite, que ya se revirtio sola una vez (16-jul,
a un snapshot de abril) y se llevo por delante mes y medio de trabajo. Este en
concreto es el que reacciona a las caidas, asi que conviene tenerlo fuera.

Ya no hay nada secreto que ocultar: los tres nodos de Telegram leen el token de
$env.TELEGRAM_BOT_TOKEN en vez de llevarlo incrustado.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:19:20 +00:00
chemavxandClaude Opus 5 07521216c7 n8n: el auto-reinicio alcanza tambien a los dos blogs
Ghost EN y ES son lo unico del mapa que da la cara al publico y lo que peor se
lleva con dos semanas sin nadie mirando. Entran en el SERVICE_MAP con la clave
igual al nombre exacto del monitor de Kuma.

El monitor "www.zonadeexclusion.com (301->apex)" se queda fuera a proposito:
que ese 301 falle es cosa de Traefik o del DNS, no de Ghost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:15:08 +00:00
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
chemavx 3112f92fea n8n: permitir modulos internos de Node en los nodos Code
Tres workflows ACTIVOS fallaban con "Module 'https' is disallowed" sin que
saltara ninguna alerta, porque estaba NODE_FUNCTION_ALLOW_EXTERNAL (paquetes
npm) pero no NODE_FUNCTION_ALLOW_BUILTIN (modulos internos):

  - Uptime Kuma -> K8s Auto-Restart  ultimo exito 2026-07-23 07:51
  - TLS Certs -> Alerta Telegram     ultimo exito 2026-04-13
  - Resumen Diario - Metricas K8s    30 fallos, 0 exitos

Es decir: el auto-reinicio que dispara Uptime Kuma llevaba una semana
muerto. Se rompio al reiniciarse el pod la tarde del 23-jul, cuando el task
runner empezo a bloquear require() de modulos internos.

Lista explicita (fs,http,https) en vez de '*': es justo lo que piden los
nodos Code de esos workflows, y asi un modulo nuevo falla a la vista en vez
de estar concedido de antemano.
2026-07-30 16:56:50 +00:00
chemavx c48ea74878 n8n: no guardar el payload de las ejecuciones exitosas
La poda por edad ya estaba activa de serie (n8n 2.15.1, prune=true, 336 h):
los IDs de ejecucion empiezan en 22.634 con 7.052 filas, o sea que ya habia
borrado ~22.600 el solo. El tar diario crecia 0,4 MB/dia y estaba llegando a
meseta, asi que no habia desbocamiento: la premisa era falsa.

El problema real era la composicion. De 322 MB de execution_data, 246 MB
(76%) eran las 3.436 ejecuciones EXITOSAS de 'Real Madrid RSS -> Twitter',
que corre cada 5 min y guarda 73 KB por vuelta. Sus errores -lo unico que
sirve para depurar- ocupaban 2 MB.

Y no es un problema de disco (21%, 699 GB libres) sino de backup: n8n esta
en CROWN, asi que ese .tar.gz de 101 MB viajaba entero a MEGA cada dia y a
B2 en las dos ultimas copias. Es justo el gasto que revento la cuota el
2026-07-25.

Nada depende de ese historico: el monitor de reversion solo lee
workflow_entity, el panel de Grafana mira replicas del deployment y
'Resumen Diario' saca metricas de k8s por un nodo Code.
2026-07-30 16:30:34 +00:00
chemavxandClaude Opus 4.8 ef75792c18 n8n: vigilante contra reversiones de BD (alerta Telegram)
CronJob externo a n8n que lee la SQLite en solo-lectura por el hostPath y avisa
si el workflow del autopost desaparece (firma de la reversión del 2026-07-16) o
si el total de workflows se desploma. La reversión SUBE el nº de activos, así que
un umbral de activos no la cazaría; el disparador es la desaparición del autopost.
Cada 6h. Reutiliza telegram-notify-infisical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 16:45:20 +00:00
chemavxandClaude Fable 5 e00c520a26 Decomisión de openclaw
- Elimina manifests openclaw/ y argocd/application-openclaw.yaml
- backup-system: fuera del backup diario, crown-jewels, expected y retain;
  fuera el mount hostPath del cronjob y la fila de RESTORE.md
- monitoring: eliminado panel openclaw del dashboard homelab-overview
- n8n: openclaw y polymarket fuera del health-check (espejo del workflow vivo)
- cluster-wide/namespaces.yaml: fuera openclaw + añadidos separadores '---'
  que faltaban (el archivo era un único doc YAML donde ganaba el último ns)

Cluster ya limpio: app ArgoCD, namespace, PVC/PV, RBAC cluster-scoped y
monitor de Uptime Kuma. Backup final: ~/decommissioned/openclaw-final-2026-07-18.tar.gz

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 14:57:46 +00:00
chemavxandClaude Fable 5 cbfb1ba039 feat(n8n): inyectar TELEGRAM_BOT_TOKEN/CHAT_ID desde telegram-notify-infisical
Para que el workflow 'Health Check General' lea el token del bot de notificaciones
via process.env en vez de hardcodearlo (rotación 2026-07-09).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 20:54:21 +00:00
chemavxandClaude Fable 5 43c78246a8 security: eliminar token de Telegram en claro de ficheros versionados
- openclaw/golden/openclaw.json: botToken → placeholder (referencia Infisical)
- n8n/health-check-code-node.js: literal → process.env.TELEGRAM_BOT_TOKEN

Token del bot @chemavx_bot rotado 2026-07-09 (BotFather). El valor vivo se
gestiona en Infisical homelab/prod/telegram. NOTA: el token viejo sigue en el
HISTORIAL de git; la revocación en BotFather es lo que lo neutraliza.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 20:46:04 +00:00
chemavxandClaude Fable 5 395102a85e feat(n8n): auto-reload del deployment al cambiar n8n-secret-infisical (operator Infisical)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 15:16:33 +00:00
chemavxandClaude Fable 5 9dbcb0896e fix(n8n): N8N_BLOCK_ENV_ACCESS_IN_NODE=false — n8n bloquea $env por defecto y el autopost no podía leer GETXAPI_TOKEN
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:38:32 +00:00
chemavxandClaude Fable 5 f29256ca55 feat(n8n): inyectar GETXAPI_TOKEN desde n8n-secret-infisical (rotación token X autopost)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:30:20 +00:00
chemavxandClaude Opus 4.8 81745dee4b n8n: decommission old n8n-secret (remove empty stub + ignoreDifferences)
3c: n8n now sources the encryption key from n8n-secret-infisical (Infisical).
Remove the empty CreateOnly stub manifest and the now-dead ignoreDifferences
/data stanza so ArgoCD prunes the old out-of-band n8n-secret.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 11:35:46 +00:00
chemavxandClaude Opus 4.8 77f55fb100 n8n: repoint encryption-key secretKeyRef to n8n-secret-infisical + Recreate
Cut n8n over to the Infisical-synced encryption key (byte-identical, key never
changes -> credentials stay decryptable) and switch RollingUpdate -> Recreate
(485MB SQLite + WAL on RWO must not have two writers during a roll).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 11:31:10 +00:00
chemavxandClaude Opus 4.8 5c7323c533 n8n: add InfisicalStaticSecret for n8n-secret (centralize N8N_ENCRYPTION_KEY)
Out-of-band Secret -> Infisical homelab/prod /n8n. Parallel-name target
n8n-secret-infisical (Owner), passthrough of the single key encryption-key
(n8n's irrecoverable credentials-encryption root, lifted byte-identical).
Old secret stays live until decommission. ArgoCD-managed -> git->sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 11:30:28 +00:00
chemavxandClaude Opus 4.8 0e50d88b54 Remove plaintext telegram-notify secrets from git (n8n/portfolio/openclaw/polymarket-bot)
Phase 3c: hooks now read telegram-notify-infisical (synced from homelab/prod
/telegram). Deleting these 4 manifests prunes the old plaintext secrets — the
bot token leaves git for the remaining 4 namespaces. Completes migration #1.

NOTE: polymarket-bot/bot-secrets still embeds the same token (migration #3).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 20:34:16 +00:00
chemavxandClaude Opus 4.8 b124f128e6 Repoint PostSync hooks to telegram-notify-infisical (n8n/portfolio/openclaw/polymarket-bot)
Phase 3b: all 4 hooks' secretKeyRefs now read the Infisical-managed secret.
Old plaintext telegram-notify secrets stay as fallback until 3c.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 20:31:02 +00:00
chemavxandClaude Opus 4.8 7b1f2da613 Add InfisicalStaticSecret for telegram-notify in n8n/portfolio/openclaw/polymarket-bot (parallel)
Phase 3a of telegram-notify migration: each syncs TELEGRAM_BOT_TOKEN/
TELEGRAM_CHAT_ID from shared homelab/prod /telegram via read-only
infisical-operator/infisical-auth, into parallel-name telegram-notify-infisical.
Old plaintext secrets + hooks untouched (repoint=3b, removal=3c).
polymarket-bot: standalone secret only; bot-secrets copy is migration #3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 20:28:30 +00:00
chemavxandClaude Fable 5 0619a5caf7 feat(n8n): enable prune, guarded by Prune=false on the workflows PVC
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:50:21 +00:00
chemavxandClaude Sonnet 4.6 177d9e0f9a fix: retry loop up to 60s in n8n smoke test healthz check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 14:14:43 +00:00
Gitea CI c61d6832de ci: update n8n image to 01d60680 [skip ci] 2026-05-20 14:08:09 +00:00
chemavxandClaude Sonnet 4.6 eb46543150 feat: add Telegram notifications to PostSync smoke tests + new tests for researchowl/openclaw
- Create telegram-notify secret in n8n, portfolio, polymarket-bot, researchowl, openclaw
  namespaces (values mirrored from monitoring/grafana-telegram)
- Update existing smoke tests (n8n, portfolio, polymarket-bot) to send [OK]/[FAIL]
  Telegram notifications on success/failure
- Add postsync-smoke-test for openclaw (curl GET / on port 18789)
- Add postsync-smoke-test for researchowl (no HTTP port; checks readyReplicas via
  k8s API using a smoke-test-reader ServiceAccount + Role + RoleBinding)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 12:40:23 +00:00
chemavx 65f93b745d feat: add researchowl 2026-04-27 13:53:42 +00:00
Gitea CI f25bded509 ci: update n8n image to b6a83c68 [skip ci] 2026-04-25 10:03:27 +00:00
chemavx d3c03d5462 argocd: add PostSync smoke test hooks for polymarket-bot, n8n, portfolio 2026-04-23 09:14:12 +00:00
Gitea CI 6fdad3b667 ci: update n8n image to b9ce8e20 [skip ci] 2026-04-22 20:41:56 +00:00
chemavx 0841d6bbe6 fix: add CreateOnly sync option to n8n-secret to prevent ArgoCD from overwriting encryption key 2026-04-14 20:30:36 +00:00
chemavx 7397c1d939 refactor: rewrite n8n manifests as clean GitOps specs, remove server-exported fields 2026-04-14 20:25:16 +00:00
chemavx 192a0bfa7a fix: delete secret-n8n-tls.yaml — kubernetes.io/tls type requires data fields, cert-manager manages this secret directly 2026-04-14 20:06:32 +00:00
chemavx db04fd2cbc fix: remove REDACTED data from n8n-tls secret manifest, prevent ArgoCD from corrupting cert-manager TLS 2026-04-14 19:58:44 +00:00
chemavx 618b1e8d11 fix: remove sensitive data from secret manifest, prevent ArgoCD from overwriting encryption key 2026-04-14 19:09:41 +00:00
Gitea CI 13680d4811 ci: update n8n image to d171ce68 [skip ci] 2026-04-14 18:50:07 +00:00
chemavx ff2e6cc985 feat: export all K8 Plus cluster manifests
Namespaces: argocd, authentik, backup-system, cloudflare-ddns,
gitea, homarr, monitoring, n8n, openclaw, polymarket-bot, vaultwarden
Cluster-wide: clusterissuers, namespaces
Secrets: redacted (structure only, data=REDACTED)
2026-04-10 08:57:02 +00:00