Dashboard como imagen en la red local
http://192.168.117.7:9100/latest.png sirve una captura del dashboard
Compras, actualizada sola cada hora, sin login — para un
equipo en la red local que necesita verlo sin credenciales de Lightdash (ej.
una pantalla fija o un carrusel). No pasa por dash.frento.com.mx ni por el
túnel de Cloudflare: es una URL aparte, solo accesible dentro de la red
192.168.117.0/24.
Por qué no es simplemente “compartir el dashboard”
Lightdash corre en la edición gratuita/self-hosted, sin
license key. Tanto el “shareable link” como el “embedding” completo son en
realidad la misma función (motor JWT compartido) y ambos están gateados a
Cloud/Enterprise — confirmado contra la propia instancia: el controlador
vive en packages/backend/dist/ee/controllers/embedController.js (carpeta
ee/, igual que la pantalla “Welcome” que también resultó ser Enterprise) y
/api/v1/health devuelve embedding.enabled: false. No hay manera de
exponer un dashboard sin autenticación usando la función nativa de Lightdash
en esta instancia.
La alternativa real dentro de la edición gratuita: un scheduled delivery en
formato imagen. Lightdash sí trae esa función completa (requiere un
headless browser, que esta instancia no tenía — ver
Lightdash § Arquitectura para el detalle de
ghcr.io/browserless/chromium:v2.49.0 agregado al docker-compose.yml) —
genera un PNG del dashboard y lo sube al bucket S3/MinIO interno como parte
normal de su flujo de entrega. Ese PNG es justo lo que este pipeline
intercepta y republica sin autenticación.
Cómo funciona, de punta a punta
cron (Lightdash, 0 * * * *)
-> scheduled delivery "Compras - export horario a Minio" (formato image)
-> headless browser renderiza el dashboard, sube PNG a MinIO (bucket "lightdash")
-> MinIO dispara webhook (bucket notification, filtro *.png)
-> receiver.py (systemd: lightdash-dashboard-pipeline.service, puerto 9100)
copia el objeto más reciente a /var/www/dashboard/latest.png
-> mismo receiver.py sirve ese archivo por HTTP en /latest.png
Nada de este flujo necesita intervención manual una vez configurado — se verificó end-to-end dos veces (una simulando el webhook a mano, otra dejando correr el pipeline real completo) y en ambas el archivo se actualizó solo.
Piezas nuevas
- Scheduled delivery: dashboard Compras,
schedulerUuid 17fb027e-d2b4-4e68-8600-28931afc6b3d, cron0 * * * *,format: image. Target: un email desechable (dashboards@ctunlinux.local, nunca se envía de verdad) — Lightdash exige al menos un destino para guardar el scheduler aunque el destino real (el bucket) no sea configurable como tal. Versources/trivasa/lightdash-dashboards-demo/pipeline-imagen-webhook.mdpara por qué no existe un target “S3 directo”. ghcr.io/browserless/chromium:v2.49.0(contenedorlightdash-headless-browser) — agregado aldocker-compose.ymlde Lightdash. 3.84GB, el pull falló dos veces antes por espacio en disco del host (ver ctunlinux para el contexto de RAM/disco ajustados) — completó a la tercera con más margen.- Notificación de bucket en MinIO:
notify_webhook:dashboard -> http://172.21.0.1:9100/minio-event(172.21.0.1es el gateway de la red Dockerlightdash_default, la forma en que un contenedor de esa red llega al host), filtrosuffix=.png. lightdash-dashboard-pipeline.service(systemd,enabled+active) — correscripts/lightdash/receiver.py, un solo script de Python (librería estándar, sin dependencias) que hace de webhook receiver y de servidor HTTP a la vez. No usa credenciales S3 propias: trae el objeto víadocker exec lightdash-minio mc cat ...(MinIO ya traemcempacado en su propia imagen). Deploy: copia idéntica del script entrivasa-bi-dev/lightdash/dashboard-pipeline/receiver.pyen ctunlinux — si se edita, actualizar los dos (repo primero, después el hostsystemctl restart lightdash-dashboard-pipeline.service).
Gotcha resuelto: el modal de onboarding salía en las capturas
La primera captura de prueba salió con un modal de Lightdash tapando la mitad
del dashboard (“Nearly there… Tell us a bit more about yourself”) — el
usuario admin de esta instancia se creó por API (ver
Lightdash § Acceso) y nunca pasó por el flujo de
onboarding normal de la UI, así que isSetupComplete seguía en false. Se
completó vía PATCH /api/v1/user/me/complete (el mismo endpoint que había
fallado semanas atrás por no existir todavía la organización — ahora sí
funciona) y las capturas siguientes salieron limpias.
Cambiar el dashboard o la frecuencia
Editar el scheduler existente desde la UI de Lightdash (Compras → ⚙ →
Scheduled deliveries), o crear uno nuevo por API contra otro dashboard —
sources/trivasa/lightdash-dashboards-demo/pipeline-imagen-webhook.md trae
el body exacto de la llamada POST /api/v1/dashboards/{uuid}/schedulers. El
receiver no necesita ningún cambio: sirve lo último que caiga en el bucket
lightdash con sufijo .png, sin importar qué scheduler lo generó — si se
agrega un segundo scheduler para otro dashboard, ambos escriben al mismo
/var/www/dashboard/latest.png (el que llegue después pisa al anterior). Un
carrusel real con más de un dashboard necesitaría rutas de salida separadas
por scheduler — implementado en
Carrusel de dashboards para TV, que reemplazó el
scheduler original de Compras por 3 (uno por dashboard). Este servicio
(lightdash-dashboard-pipeline.service, puerto 9100) sigue activo tal cual,
pero como resultado ya no muestra siempre Compras — sirve el último .png
subido al bucket sin importar cuál de los 3 schedulers lo generó.
Véase también
- Lightdash — la instancia y los dashboards que este pipeline expone.
- Carrusel de dashboards para TV — extensión de este mismo patrón a los 3 dashboards en rotación, sirviendo en el puerto 8888.
- ctunlinux — RAM/disco del host, relevante para el peso del headless browser.
sources/trivasa/lightdash-dashboards-demo/pipeline-imagen-webhook.md— cierre técnico completo: schema exacto de la API de schedulers, formato del evento de MinIO, y el scriptreceiver.pycompleto.