conkafecito-observability — dashboards HTML + TUI sobre la Omada Open API

Dos dashboards de observability para Conkafecito (estado WAN/APs/clientes del sitio Controlador Comisariato, más los 4 endpoints reales de conkafecito.com), construidos sobre la conexión ya resuelta a la Omada Open API. Repo ehalso/conkafecito-observability (privado, no existía un conkafecito-infra al que sumarlo).

Por qué en vm-playground y no en vm-ubuntu

El pedido original apuntaba a desplegar en vm-ubuntu (10.10.20.12) — ese host ya no existe: no responde ping, y la propia Omada Open API tampoco lo ve como cliente conectado a la red (confirmado consultando GET .../clients antes de tocar el destino de despliegue). Se desplegó en vm-playground en su lugar, por indicación directa de Esteban a mitad de la construcción — segunda excepción al rol de “workstation pura” de este host (la primera fue DBHub), posible por el mismo motivo: NetBird ya le da a este host alcance a 10.10.20.0/24.

Diferencia clave con DBHub: acá los puertos (8090 HTML, 8091 TUI-web) se publican directos, sin túnel de Cloudflare — el propósito es acceso desde la LAN de Conkafecito (o vía NetBird, dado que vm-playground no está en esa LAN física), no un servicio público en internet.

Los datos reales no se parecían al mockup

El prototipo visual de partida asumía 3 sitios (matriz/sucursal-norte/sucursal-sur), 7 APs, un panel de peers de Netbird, y 5 endpoints de conkafecito.com. Ninguno de esos supuestos sobrevivió el contacto con la API real:

  • 1 solo sitio (“Controlador Comisariato”), no 3 — confirmado con GET .../sites.
  • 3 APs, no 7 — GET .../devices.
  • Sin Netbird peers: no hay token de API de Netbird en Infisical, y los peers reales de Conkafecito (sr250, vm-rds, vm-contpaq, vm-mpro, vm-biotime) viven en una cuenta Netbird vieja no migrada, invisible desde el CLI/API de este host (ver hosts.md § Conkafecito). Se sustituyó por la lista de clientes LAN que sí expone la Open API de Omada (GET .../clients) — señal equivalente o mejor, ya que refleja presencia real en la red en vez de que el agente de Netbird esté corriendo.
  • 4 hostnames reales, no 5 — rds/contpaq/mpro/biotime/ubuntu.conkafecito.com no resuelven en DNS, no existen. Los reales son conkafecito.com, www., oci., glpi. (los mismos dos últimos que ya documenta Túneles de Cloudflare § vm-main, túnel cloudflared-conkafecito.service).
  • Sin Uptime Kuma — al principio: no se encontró ninguna instancia corriendo en wiki-personal, Infisical, ni ningún host alcanzable desde esta sesión, así que el backend arrancó cubriendo el 100% del polling por su cuenta. Se agregó después (ver § Uptime Kuma abajo) a pedido explícito.
  • Sin historial 24h: la Open API de este controlador no expone un endpoint de histórico confirmado (varios paths probados devolvieron 400/404). El backend arma su propio historial en memoria, acumulando muestras reales cada 30s desde que arranca, en vez de simular un pasado que no se puede consultar.
  • Sin ISP por sitio: tampoco viene en el listado de dispositivos de la Open API.

Arquitectura

docker-compose.yml con tres servicios, cada uno con su container_name, restart: unless-stopped:

  • uptime-kuma (louislam/uptime-kuma:1, puerto 3001): 15 monitores (4 HTTP a conkafecito.com, 11 ping a gateway/APs/VMs del vSwitch de sr250), agrupados en una status page pública conkafecito — es lo que el backend consume, no la API interna autenticada.
  • backend (FastAPI + Uvicorn, puerto 8090): poller en background cada 30s (Omada + heartbeats de la status page de Kuma, sin auth), cacheado en memoria — /api/status nunca dispara llamadas nuevas por request. Si Kuma no responde, cae a un chequeo HTTP directo de los 4 endpoints (kuma_source: "fallback-http" en la respuesta). Sirve también el HTML estático en /.
  • tui (puerto 8091): la misma TUI en textual detrás de ttyd — un solo binario terminal-a-web, elegido sobre gotty/wetty por no depender de un runtime de Node.js aparte. El binario se descarga de GitHub Releases en el Dockerfile (detecta aarch64, arquitectura de este host) porque no está empaquetado de forma confiable en Debian slim.

Secretos (OMADA_CTRL_COMISARIATO_*, CONKAFECITO_UPTIME_KUMA_ADMIN_*) vía Infisical, inyectados a un .env local (chmod 600, no versionado) — mismo patrón que el resto de esta infra. Los signos $ del client_secret de Omada se escriben duplicados en .env, mismo gotcha de escapado de Compose ya documentado en DBHub.

Uptime Kuma: sin API REST para el setup inicial

Uptime Kuma no tiene forma de crear el usuario admin, monitores, o una status page vía REST — todo pasa por Socket.IO, sin documentar públicamente. tools/kuma_setup.py automatiza ese flujo (usuario, 15 monitores, status page), encontrado a prueba y error contra el contenedor real:

  • El evento add de un monitor exige accepted_statuscodes (array) incluso para monitores que no son HTTP — sin eso tira Cannot read properties of undefined (reading 'every'), un error que no dice qué campo falta.
  • El campo tags en el payload de add rompe con un error de SQL (table monitor has no column named tags) pese a que la UI lo muestra como campo editable — se gestiona por una tabla de relación aparte, no se manda al crear.
  • saveStatusPage espera cuatro argumentos posicionales (slug, config, imgDataUrl, publicGroupList), no dos (slug, config con publicGroupList anidado ahí adentro) — con la forma incorrecta el servidor lanza una excepción no capturada y el callback nunca se dispara, así que del lado del cliente se ve como un timeout sin ninguna pista de la causa real (hubo que mirar los logs del contenedor para encontrarla).

El backend nunca usa las credenciales de admin — lee la status page pública (/api/status-page/heartbeat/conkafecito) sin autenticarse.

Véase también