Files
fn_registry/docs/capabilities/local-hub.md
T
egutierrez 32c7336bf6 feat(infra): auto-commit con 56 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 14:22:55 +02:00

4.6 KiB

Capability: local-hub

Exponer los procesos locales de la maquina como subdominios *.localhost (via Caddy) y reunirlos en una pantalla principal (Glance) con estado online/offline en vivo, refrescada a diario por dag_engine. Cubre el ciclo: descubrir servicios -> renderizar config de proxy -> renderizar config de dashboard -> recargar y reiniciar (pipeline refresh_local_hub).

Fuente de verdad de los servicios: apps/local_hub/local_services.yaml.

Por que existe

Una maquina con muchos procesos locales (Metabase :3030, Portainer :9000, Grafana, Jupyter, dag_engine, registry_api...) obliga a recordar puerto por puerto. Este grupo los pone detras de nombres legibles (metabase.localhost, portainer.localhost) sin tocar DNS ni /etc/hosts (systemd-resolved resuelve *.localhost a 127.0.0.1 por defecto, RFC 6761) y los lista en una sola pagina con su salud en vivo.

Funciones

ID Firma Que hace
discover_local_services_py_infra discover_local_services(manifest_path, include_registry=True) -> list[dict] Lee el manifiesto local_services.yaml, normaliza cada servicio (name, subdomain, port, health_path, title, icon, category) y resuelve up por chequeo TCP. Con include_registry anade los servicios del registry (via fn doctor services-spec) deduplicados.
render_caddyfile_py_infra render_caddyfile(services, dashboard=None) -> str PURA. Convierte la lista de servicios en el texto de un fragmento de Caddyfile (http://<sub>.localhost { reverse_proxy 127.0.0.1:<port> }), ordenado y determinista. El dashboard va primero.
render_glance_config_py_infra render_glance_config(services, title="Procesos locales", host_suffix="localhost") -> str PURA. Convierte la lista en YAML de Glance: una pagina con un widget monitor por categoria, cada site apuntando a http://<sub>.localhost.
refresh_local_hub_py_pipelines refresh_local_hub(manifest_path=..., reload=True) -> dict PIPELINE. Compone las 3 anteriores: descubre, renderiza Caddyfile + Glance, los escribe (/etc/caddy/conf.d/local_hub.caddy via ACL + apps/local_hub/glance/glance.yml), recarga Caddy (admin API :2019, sin sudo) y reinicia la user-unit glance.

Ejemplo canonico

# Refrescar todo el hub (descubrir + regenerar configs + recargar):
./fn run refresh_local_hub

# Acceder a un servicio por su subdominio (cualquier navegador del host):
#   http://metabase.localhost
#   http://portainer.localhost
#   http://home.localhost        <- la pantalla principal (Glance)

# Anadir un servicio nuevo: editar el manifiesto y refrescar
$EDITOR apps/local_hub/local_services.yaml   # name, subdomain, port, health_path, title, icon, category
./fn run refresh_local_hub

Composicion ad-hoc (heredoc) si se necesita solo una parte:

import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from infra.discover_local_services import discover_local_services
from infra.render_caddyfile import render_caddyfile

services = discover_local_services("apps/local_hub/local_services.yaml")
print(render_caddyfile(services, dashboard={"subdomain": "home", "port": 8585}))

Infraestructura (one-time, ya provisionada)

  • Caddy (apt, systemd system service, puerto 80): /etc/caddy/Caddyfile hace import /etc/caddy/conf.d/*.caddy. El usuario tiene ACL de escritura sobre conf.d/ para que el pipeline regenere sin sudo. Reload via admin API en localhost:2019.
  • Glance (binario nativo en ~/.local/bin/glance, systemd user service glance.service, 127.0.0.1:8585). Corre como binario del host —no contenedor— para que *.localhost resuelva igual que en el resto del sistema.
  • dag_engine: DAG refresh_local_hub diario que ejecuta el pipeline.

Fronteras

  • NO gestiona TLS: sirve HTTP plano (http://) porque es trafico loopback. Para HTTPS con CA interna habria que quitar el prefijo http:// en render_caddyfile y dejar que Caddy emita certs internos.
  • NO arranca ni para los servicios que expone: asume que ya corren. Solo crea el mapeo de subdominio y los lista. Encender/apagar un servicio es trabajo de su propia unit / systemd.
  • NO hace el health-check en vivo: eso lo hace Glance client-side. El pipeline solo resuelve un up/down puntual al regenerar (snapshot del momento).
  • Servicios no-HTTP (Postgres :5433, etc.) quedan fuera del proxy y del dashboard: Caddy y el widget monitor de Glance son HTTP.
  • Solo loopback / un PC: el manifiesto y los subdominios son locales a la maquina. No expone nada a la red. Para acceso remoto se usa SSH port-forward o el grupo ssh/wireguard.