Beszel — monitoreo ligero

Segundo panel de monitoreo, además de Glances. El hub corre en Docker en vm-main (movido desde vm-playground el 2026-08-10, rediseño vm-producción/vm-workstation — ver hosts.md). Monitorea 11 hosts: los 4 de la cuenta personal/cloud (vm-playground, vm-personal, vm-main, pop-os) más 5 de Conkafecito (sr250, vm-contpaq, vm-rds, vm-mpro, vm-test) más ctunlinux y svr-dev (Trivasa, agregado 2026-08-16 — ver su propia sección abajo).

Dominio principal desde 2026-08-16: monitor.ehas.uk (antes dashboard.estebanalcocer.cloud). El cambio fue en dos pasos, ambos en el mismo túnel de Cloudflare de vm-main:

  1. Renombre de hostnames dentro de estebanalcocer.cloud: lo que servía Beszel (dashboard.) pasó a llamarse monitor., y lo que servía Glances (monitor.) pasó a lens. — swap de nombres entre los dos paneles.
  2. monitor.ehas.uk (dominio nuevo, misma cuenta de Cloudflare) se agregó como alias del mismo servicio y se fijó como APP_URL del hub — el dominio “canónico” que ve el usuario, aunque el resto de los hostnames de abajo sigan funcionando igual.

dashboard.estebanalcocer.cloud y monitor.estebanalcocer.cloud se dejaron como alias permanentes apuntando al mismo localhost:8090 — no por preferencia, sino porque migrar el hostname del ingress sin dejar el viejo activo tumbó a toda la flota de agentes de un tirón (ver “Incidente 2026-08-16” más abajo). Los tres hostnames (dashboard.estebanalcocer.cloud, monitor.estebanalcocer.cloud, monitor.ehas.uk) sirven exactamente lo mismo indefinidamente; solo monitor.ehas.uk es el que se usa en HUB_URL de agentes nuevos o migrados de aquí en más.

vm-backup se decomisionó, se terminó su instancia OCI, y su registro en Beszel se borró el 2026-08-10 — por API (DELETE /api/collections/systems/records/<id>), no editando config.yml ni reiniciando el hub. El motivo de evitar el restart: reiniciar el contenedor dispara SyncSystems, que borra cualquier sistema no listado en config.yml — y eso es justo lo que le había pasado a ctunlinux sin que nadie se diera cuenta: se agregó por API directa el 2026-08-09 (nunca vivió en config.yml, ver sección más abajo), y el primer docker compose up -d del hub en vm-main durante la migración del 2026-08-10 (madrugada) lo sincronizó fuera de existencia junto con el resto de fingerprints. Se detectó y reparó horas después, recreando el sistema y su fingerprint por API con el mismo BESZEL_AGENT_TOKEN_CTUNLINUX que ya estaba guardado en Infisical (el agente en ctunlinux nunca cambió su config, así que reconectó solo apenas el token volvió a existir del lado del hub). Lección para la próxima vez que se toque este hub: cualquier sistema agregado por API (fuera de config.yml) no sobrevive un restart del contenedor — o se agrega también a config.yml para que persista, o se acepta que hay que revisar/recrear por API después de cada restart.

La migración del hub fue transparente para todos los agentes existentes: todos apuntan a la URL pública, nunca a una IP/host interno, así que mudar el hub de host no les rompió la conexión — se reconectaron solos.

El agente se conecta al hub por WebSocket saliente (HUB_URL=https://monitor.ehas.uk), autenticado con un token por sistema más la llave pública del hub — nunca es el hub el que le hace pull al agente. Confirmado leyendo el handler real (internal/hub/agent_connect.go del repo de Beszel): el fingerprint SSH de cada sistema se establece sobre esa misma conexión WebSocket saliente, la primera vez que conecta (handleSingleRecord, if fpRecord.Fingerprint == "" { ... }) — no existe ningún paso donde el hub necesite alcanzar al agente por su cuenta. Por eso, a diferencia de Glances (que sí necesita que el hub llegue a cada agente y por eso usa NetBird), Beszel no necesita malla ni túnel por host: cada agente solo necesita salida HTTPS/WSS normal hacia el hub, que ya es pública. (Este punto se re-confirmó a la mala el 2026-08-16 — ver el incidente de svr-dev más abajo, donde se cambió la red del contenedor del hub por una hipótesis de “necesita alcanzar al agente” que resultó equivocada y se revirtió.)

Arquitectura por host

  • vm-main — hub en Docker (~/stacks/beszel/docker-compose.yml, movido desde vm-playground el 2026-08-10). El agente que monitorea este mismo host no corre en el mismo compose (a diferencia del viejo patrón “same-system” de vm-playground) — es el mismo agente nativo vía systemd que ya tenía desde antes, sin cambios, apuntando a la URL pública del hub como cualquier otro agente remoto.
  • vm-playground — antes alojaba el hub + su propio agente vía socket Unix en el mismo compose (“same-system”). Al mudarse el hub, ese agente dejó de aplicar; se instaló un agente nativo vía systemd nuevo el 2026-08-10, mismo patrón que el resto.
  • vm-personal, pop-os — solo agente, instalado nativo vía systemd, no en Docker. Mismo criterio que ya usa glances-agent.service en estos mismos hosts (el hub de Glances es Docker, sus agentes no): un agente de monitoreo puro no gana nada corriendo en contenedor y en vm-personal (e2-micro, 958Mi de RAM total) sí importa el overhead de menos.

Instalación del agente nativo, con el script oficial del proyecto:

curl -sL https://raw.githubusercontent.com/henrygd/beszel/main/supplemental/scripts/install-agent.sh \
  | sudo sh -s -- -k "<llave pública del hub>" -t "<token del sistema>" \
    -url "https://monitor.ehas.uk" --auto-update true

El script crea un usuario de sistema beszel (nologin), lo suma al grupo docker si existe (así igual reporta stats de los contenedores del host sin montar nada a mano) y a disk, e instala /etc/systemd/system/beszel-agent.service con sandboxing de systemd (ProtectSystem=strict, etc.). --auto-update true es obligatorio al correrlo por SSH sin TTY — si no, el script se queda esperando un prompt interactivo que nunca llega.

vm-playground no tiene credenciales SSH propias hacia vm-main ni vm-backup, así que la instalación ahí se hizo por doble salto vía vm-personal (ssh vm-personal "ssh vm-main_oracle '<comando>'"), el mismo patrón que ya se usó para los agentes de Glances en esas VMs.

Agentes Windows (Conkafecito + Trivasa) — Tarea Programada, sin NSSM

sr250 (host físico de Hyper-V), vm-contpaq, vm-rds, vm-mpro, vm-test (Conkafecito) y svr-dev (Trivasa, agregado 2026-08-16) corren el mismo modelo saliente (WebSocket hacia el hub, sin abrir puertos), pero Windows no tiene systemd, así que el mecanismo de instalación es distinto.

El instalador oficial de Beszel para Windows (install-agent.ps1) depende de Scoop o WinGet y de auto-elevación interactiva por UAC (Start-Process -Verb RunAs) — no funciona sin sesión de escritorio, que es justo el caso al instalar por SSH. En su lugar:

  1. El zip de la release se descarga directo desde GitHub y se extrae a C:\ProgramData\beszel-agent\.
  2. Un script run-agent.ps1 ahí mismo setea KEY/TOKEN/HUB_URL como variables de entorno y arranca beszel-agent.exe.
  3. Una Tarea Programada (BeszelAgent) ejecuta ese script al inicio del sistema como SYSTEM, con reinicio automático si el proceso muere.

No se usó NSSM — que es lo que sí usa el instalador oficial para registrar el binario como servicio real — porque nssm.cc no es alcanzable desde ninguno de estos hosts (se confirmó con Invoke-WebRequest antes de instalar nada; github.com y dashboard.estebanalcocer.cloud sí lo son), y bajar un binario de un mirror de terceros para correrlo como SYSTEM en servidores de producción no es aceptable. La Tarea Programada logra el mismo resultado sin depender de nada más que el binario oficial. (beszel-agent.exe no implementa el protocolo de servicio de Windows, así que ninguno de los dos caminos puede saltarse el wrapper — sc.exe create directo falla.)

El ~/.ssh/config de vm-personal tiene alias duplicados para varios de estos hosts (DNS de NetBird, IP de NetBird, y para sr250 también vía Cloudflare Access) — el DNS de NetBird no resuelve desde vm-personal, así que se usa siempre la variante _ip. Se probó primero en vm-test (la VM de pruebas) antes de tocar los 4 hosts de producción. vm-biotime (mismo patrón de alias) quedó fuera esta vuelta: su peer de NetBird no responde (“No route to host”).

svr-dev — mismo patrón, binario copiado en vez de descargado, bloqueado por ESET

svr-dev (Trivasa, 192.168.117.200 — ver hosts.md) no tenía ruta confirmada a internet abierta para descargar el release de GitHub directo, así que en vez de repetir la descarga se copió el binario ya verificado de vm-mpro vía scp de doble salto por vm-personal:

scp -O CK_vm-mpro:/ProgramData/beszel-agent/beszel-agent.exe /tmp/beszel-agent.exe
scp -O /tmp/beszel-agent.exe TRV_svr-dev:/ProgramData/beszel-agent/beszel-agent.exe

El flag -O (protocolo scp legado) es obligatorio contra el servidor OpenSSH de Windows — sin él, el scp moderno (protocolo SFTP) falla con protocol error: filename does not match request, un choque de compatibilidad conocido entre el cliente OpenSSH moderno y el servidor de Windows. Rutas con / en vez de \ funcionan igual en ambos lados.

El resto del patrón (zip → run-agent.ps1 → Tarea Programada BeszelAgent como SYSTEM) es idéntico al resto de los Windows. Se agregó una regla de Windows Firewall entrante para TCP 45876 en el proceso — innecesaria en retrospectiva (ver el punto de arriba sobre que el hub nunca necesita alcanzar al agente), no hizo daño dejarla pero no fue la causa de nada.

El bloqueo real: ESET con filtrado de tráfico SSL/TLS. El agente quedó en loop de reconexión con WebSocket connection failed err="unexpected status code: 403" incluso con el token, el fingerprint y toda la red confirmados correctos — el 403 nunca llegó a aparecer en los logs del túnel de Cloudflare de vm-main (journalctl -u cloudflared-estebanalcocer -f en blanco durante los reintentos), señal de que el bloqueo pasaba antes de salir de la red de svr-dev, no en el lado del hub. Confirmado con una prueba simple: Invoke-WebRequest a monitor.ehas.uk desde PowerShell en svr-dev falla con “No se puede establecer una relación de confianza para el canal seguro SSL/TLS” — un fallo de confianza de certificado, no de red ni de DNS. svr-dev tiene ESET Endpoint/Server Security corriendo (ESET Forwarder, ESET Service, ESET Firewall Helper) con su inspección SSL/TLS activa, que re-firma HTTPS local con un certificado propio y típicamente no soporta (o bloquea de frente) el handshake de upgrade de WebSocket. Se comparó con vm-mpro (mismo binario, misma Tarea Programada, mismo run-agent.ps1, mismo proxy WinHTTP — ninguno configurado) para descartar diferencia de configuración local: son idénticos: la única diferencia real es ESET.

Pendiente, no resuelto por esta sesión: agregar una excepción en ESET (para beszel-agent.exe o para el dominio/tráfico WebSocket de monitor.ehas.uk) — probablemente centralizado vía consola ESET PROTECT, no algo que se pueda tocar de forma segura por PowerShell remoto sin acceso a esa consola. El agente queda instalado y con HUB_URL=https://monitor.ehas.uk correcto, listo para conectar en cuanto se libere esa excepción.

Cómo se armó el hub sin usar el navegador

Beszel está construido sobre PocketBase. El flujo normal de alta (crear usuario admin, registrar cada sistema con su par de llaves/token) se hace desde el wizard web. Se automatizó por completo con variables de entorno y un archivo declarativo:

  • USER_EMAIL / USER_PASSWORD en el entorno del hub → la migración interna del hub (initial-settings.go) crea el superusuario y el usuario normal con esas credenciales en el primer arranque, sin pasar por el wizard.
  • beszel_data/config.yml (bind-mount) — retirado el 2026-08-16, ver “config.yml retirado” más abajo. Mientras existió, el hub sincronizaba este archivo en cada arranque y creaba el registro de cada sistema junto con su token de fingerprint con el valor que se le indicara, reemplazando el diálogo “Add System” de la UI — pero el sync borraba cualquier sistema que no estuviera listado en el archivo, la causa de los dos incidentes documentados abajo.
  • La llave pública SSH del hub (necesaria igual en modo WebSocket — el agente la usa para validar el handshake) se generó sola en beszel_data/id_ed25519 en el primer arranque; se leyó autenticando por API (POST /api/collections/users/auth-with-password con las credenciales de arriba, luego GET /api/beszel/info) en vez de extraerla del archivo, porque el contenedor no trae ssh-keygen ni usuario root en /etc/passwd.

config.yml retirado (2026-08-16) — los sistemas ya no dependen de un archivo en vm-main

Confirmado leyendo el handler real (internal/hub/config/config.go, función SyncSystems): el sync solo corre si el archivo existe — os.ReadFile falla, la función hace return nil de inmediato, sin tocar la base. Es decir, el riesgo de que un restart borre un sistema agregado por GUI/API (los dos incidentes de abajo) no es inherente a Beszel — es enteramente una consecuencia de que config.yml exista en beszel_data/. Sacándolo de ahí, cualquier sistema vive en la base de PocketBase como cualquier otro registro y sobrevive reinicios sin depender de ningún archivo ni de acceso a vm-main.

Se movió a ~/stacks/beszel/config.yml.bak (fuera de beszel_data/, que es lo único que el hub lee) — se conserva como referencia de los tokens que ya estaban en uso, no como algo que se vuelva a montar. Verificado end-to-end: tras el retiro, un docker restart beszel ya no imprime “Systems synced with config.yml” en el log, los 11 sistemas existentes siguen intactos, y un sistema de prueba creado por API (POST /api/collections/systems/records + POST /api/collections/fingerprints/records, mismo patrón que “Agregar un sistema por API” abajo) sobrevivió un segundo restart antes de borrarse. Con esto, la vía preferida de abajo deja de tener la advertencia de “no sobrevive un restart” — ahora sí es completa por sí sola, sin necesitar ningún paso adicional en config.yml.

Incidente 2026-08-16: renombre de dominio tumbó la flota, y las causas reales detrás

El renombre de hostnames descrito arriba (dashboard. → monitor., alta de monitor.ehas.uk) se hizo quitando dashboard.estebanalcocer.cloud del ingress del túnel — sin darse cuenta de que todos los agentes ya desplegados (los 10 de ese momento) seguían apuntando a ese hostname exacto en su HUB_URL. El resultado: la mayoría de la flota apareció offline en el dashboard (los dos que seguían “online” — GCP:vm-personal y TRV:ctunlinux — solo lo estaban porque su conexión WebSocket ya estaba abierta desde antes del cambio; una reconexión los habría tumbado igual). El registro DNS de dashboard.estebanalcocer.cloud nunca se había borrado, solo la regla de ingress — así que devolvía 404 en vez de fallar la resolución, y restaurar esa sola línea de ingress recuperó toda la flota sin tocar un solo agente, antes de migrarlos uno por uno a monitor.ehas.uk con calma. Lección aplicada arriba: los tres hostnames quedan activos permanentemente por esto mismo — un cambio de HUB_URL en el hub nunca debe asumirse instantáneo en los agentes.

Migrar cada agente reveló dos problemas de infraestructura preexistentes, ninguno causado por el cambio de dominio en sí — solo se hicieron visibles al necesitar tocar hosts que llevaban tiempo sin revisarse.

Bug de comandos SSH de doble salto: verificación falsa, no error visible

El patrón de acceso a la flota de Conkafecito/Trivasa es ssh vm-personal ssh <host-destino> "<comando>" (ver Acceso SSH entre VMs para el porqué de este doble salto). Si <comando> contiene ;, &&, | o saltos de línea sin escapar dentro de comillas que sobrevivan el salto, el cliente SSH del salto intermedio (vm-personal) reconstruye el comando remoto concatenando sus argumentos con espacios simples — perdiendo las comillas originales. El resultado: solo la primera sub-instrucción (hasta el primer operador) llega al host de destino; todo lo que sigue al operador se ejecuta en vm-personal, en silencio, sin error — porque casi cualquier comando de diagnóstico (hostname, systemctl status, journalctl) también es válido ahí, la salida parece plausible y no hay ninguna señal de que se ejecutó en el host equivocado.

Esto produjo una “verificación” falsa durante la migración: un comando de restart+status contra OCI_vm-playground pareció confirmar el cambio aplicado, pero en realidad el sed/systemctl restart corrió contra vm-personal (que ya tenía el HUB_URL correcto de una migración anterior en la misma sesión, así que el resultado coincidía por casualidad). Se detectó por accidente al comparar whoami (svr-dev\ealcocer, correcto) contra hostname (vm-personal, del mismo comando) en una prueba a svr-dev — una contradicción imposible si ambos hubieran corrido en el mismo host. vm-playground y ctunlinux se re-verificaron y re-corrigieron después con el patrón seguro.

Patrón seguro para múltiples comandos en el salto final: pasar el script completo por stdin a un bash -s en el host intermedio, nunca como argumento de línea de comandos con operadores sin escapar:

ssh vm-personal bash -s <<'EOF'
ssh -o BatchMode=yes -o ConnectTimeout=8 OCI_vm-playground 'comando1 && comando2 && comando3'
EOF

Acá vm-personal recibe el script completo por su entrada estándar y lo parsea como un shell real (comillas incluidas, no reconstruido por concatenación de argv) — el ssh interno sí preserva las comillas simples alrededor de 'comando1 && comando2 && comando3' como un solo argumento. Para hosts Windows, el mismo riesgo existe con PowerShell — ahí la mitigación fue codificar el script completo en Base64 (powershell -EncodedCommand <blob>), que por no tener espacios ni operadores nunca se ve afectado por la concatenación del salto intermedio.

NetBird: dos daemons compartiendo la misma tabla de ruteo del kernel

Con el hostname restaurado, cuatro hosts de Conkafecito (eri-sr250, vm-contpaq, vm-rds, vm-test, todos en 10.10.20.0/24) seguían sin responder por SSH desde vm-personal pese a que vm-dev (el routing peer de esa subred, ver NetBird) mostraba Connected con handshake reciente. Ping a cualquier IP de esa subred fallaba al 100%, incluida la propia IP local de vm-dev — la ruta estaba “Selected” en netbird routes list pero ip route show table netbird estaba completamente vacía.

Causa raíz: vm-personal corre dos daemons de NetBird en paralelo (netbird y netbird-conka, ver NetBird § Doble instancia) — cada uno con interfaz de kernel y fwmark de WireGuard propios, pero ambos comparten la misma tabla de ruteo fija del kernel (7120, nombre netbird en /etc/iproute2/rt_tables), hardcodeada en el binario sin flag de CLI para aislarla por instancia. Los dos procesos compiten por instalar rutas ahí y ninguno gana de forma consistente. systemctl restart netbird.service (el daemon dueño de la ruta de vm-dev) la reclamó y la ruta apareció — pero no es un fix permanente: si netbird-conka.service se reinicia después, puede volver a pisarla. Un aislamiento real (namespace de red separado por daemon) queda pendiente, evaluado pero no aplicado por el mayor alcance que implica tocar la red de vm-personal.

Agregar un sistema por API, sin SSH a vm-playground (vía preferida)

Las dos vías de arriba (Docker same-system en vm-playground, systemd nativo por SSH en el resto) asumen que la sesión que instala el agente tiene una ruta SSH hacia el host nuevo, y además hacia vm-playground para tocar config.yml y reiniciar el hub. ctunlinux (Trivasa) no cumple ninguna de las dos — es un host en otro dominio de acceso por completo, sin NetBird en ese momento y sin ningún alias en ningún ~/.ssh/config de la flota personal. Se resolvió sin tocar vm-playground en absoluto, hablando directo con la API del hub desde el propio ctunlinux:

  1. Password del hub — BESZEL_DASHBOARD_PASSWORD desde Infisical.
  2. Login — POST /api/collections/users/auth-with-password con {"identity": "<email de Esteban>", "password": "<de arriba>"} → token de sesión. El email no está guardado en Infisical (solo el password) — es el mismo correo personal de Esteban, ya conocido en la conversación.
  3. Llave pública del hub — GET /api/beszel/info con ese token, igual que en la sección de arriba.
  4. Crear el sistema — POST /api/collections/systems/records con {"name": "TRV:ctunlinux", "host": "ctunlinux", "port": "45876", "users": ["<id del usuario del paso 2>"]}. port no es el puerto por el que el hub llega al agente (la conexión es saliente, agente → hub) — es solo un campo del schema; se usó 45876 porque es el puerto default del agente, igual que en todos los demás sistemas.
  5. Token de emparejamiento — hallazgo nuevo, no vive en systems. El registro de systems (paso 4) no tiene campo token — se confirmó leyendo un registro existente completo por API antes de asumir el schema. El token vive en una colección separada, fingerprints ({fingerprint: string, system: <relation>, token: string}), con fingerprint vacío hasta que el agente conecta por primera vez y el hub lo rellena solo. Se creó a mano con POST /api/collections/fingerprints/records, {"system": "<id del paso 4>", "token": "<uuid4 generado localmente>"} — el mismo patrón que ya describía la sección de arriba para config.yml (“token de fingerprint con el valor que se le indique”), solo que por API en vez de por archivo.
  6. Guardar el token — BESZEL_AGENT_TOKEN_CTUNLINUX en Infisical, mismo patrón que el resto (POST /api/v3/secrets/raw/<key>, ver Gestión de secretos).
  7. Instalar el agente — el mismo script/comando de la sección de “Arquitectura por host” arriba, con la llave del paso 3 y el token del paso 5/6.

Confirmado end-to-end: beszel-agent.service activo en ctunlinux, y el registro en systems pasó de status: "pending" a status: "up" con métricas reales (GET /api/collections/systems/records/<id>) unos segundos después del systemctl start.

Esta es la vía preferida — y desde el 2026-08-16, la única vía — para agregar un sistema nuevo, incluso cuando sí hay ruta SSH a vm-main disponible — no depende de tocar el contenedor del hub (sin reinicio, sin ningún archivo que sincronizar), y el mismo patrón (login → crear systems → crear fingerprints → guardar token → instalar agente) es idéntico sin importar en qué host/dominio de acceso esté el sistema nuevo. Sobrevive un restart del contenedor sin ninguna acción adicional — ver “config.yml retirado” arriba.

No seguida al pie de la letra el 2026-08-16: svr-dev y la reparación de eri-sr250/vm-contpaq/vm-rds/vm-mpro/vm-test (incidente de arriba) se hicieron editando config.yml directamente, replicando el patrón que ya tenían esos cinco sistemas en el archivo — la recomendación de esta sección no se revisó antes de actuar. El docker compose up -d que fijó el APP_URL nuevo disparó otro SyncSystems y volvió a borrar ctunlinux (que seguía sin estar en config.yml) — segunda vez que pasaba exactamente lo mismo. Ese mismo día se retiró config.yml por completo (ver “config.yml retirado” arriba) — la vía de esta sección ya no tiene ninguna advertencia pendiente: es la única forma de agregar un sistema, y ya no compite con ningún archivo que la pueda deshacer.

Credenciales

Password de login y un token de registro por sistema están en Infisical (BESZEL_DASHBOARD_PASSWORD, BESZEL_AGENT_TOKEN_<HOST>), además de en ~/stacks/beszel/.env en vm-main (permisos 600, no versionado).

Prefijos de nombre por origen

El campo name de cada sistema lleva un prefijo según el origen de la máquina, separado con : (no -), para distinguirlas de un vistazo en el dashboard:

PrefijoOrigenSistemas actuales
ORA:Oracle CloudORA:vm-playground, ORA:vm-main, ORA:vm-backup
GCP:Google CloudGCP:vm-personal
WS:PC personal de Esteban (workstation)WS:t640-pop (nombre real del host, no pop-os)
CK:On-premise Conkafecito (Hyper-V, sr250)CK:eri-sr250, CK:vm-contpaq, CK:vm-rds, CK:vm-mpro, CK:vm-test
TRV:On-premise TrivasaTRV:ctunlinux (agregado 2026-08-09, vía API — ver arriba), TRV:svr-dev (agregado 2026-08-16, bloqueado por ESET — ver “Agentes Windows” arriba)

Histórico, ya no aplica desde que se retiró config.yml: mientras el sync existió, empareja registros por la clave name+host+port — cambiar name no actualizaba el registro in-place, hacía que se borrara el viejo y se creara uno nuevo (mismo token si se especificaba en el archivo, así que el agente seguía funcionando sin tocarlo, pero el historial de gráficas del sistema viejo se perdía). Pasó dos veces: al aplicar los prefijos con - el 2026-08-06, y otra vez al corregirlos a : el 2026-08-07. Renombrar un sistema por API (PATCH /api/collections/systems/records/<id>) sí actualiza in-place, sin este problema.

Fuera de alcance

svr-dev ya no está en esta lista — tiene ruta de red confirmada (ver “Agentes Windows” arriba), el bloqueo es ESET, no falta de acceso. WS:t640-pop quedó offline el 2026-08-16 por su propio peer NetBird en estado Connecting (no Connected) — problema de esa máquina/su túnel, no del hub ni del HUB_URL; no investigado más a fondo esta ronda.

Sin ruta de red desde vm-playground/vm-personal — misma limitación ya documentada en Glances: vm-ubuntu, raspberrypi (192.168.68.x), y ocs/svr-api2 (mismo ~/.ssh/config de vm-personal, subred 192.168.117.x, timeout). vm-biotime está en el ~/.ssh/config pero su peer de NetBird no responde. surface-wsl, minibook y termux tampoco tienen ruta SSH conocida — son dispositivos personales que no están en ningún ~/.ssh/config de la flota.

Seguridad

Igual que Glances: público sin autenticación adicional por ahora, decisión pendiente de revisar junto con el resto de paneles.

Véase también

  • Glances — otro panel de monitoreo de los mismos hosts; a diferencia de este, usa NetBird porque ahí el hub necesita llegar por SSH a cada agente
  • Túneles de Cloudflare — cómo se expone monitor.ehas.uk (y los alias dashboard./monitor.estebanalcocer.cloud)
  • Acceso SSH entre VMs — cómo se llegó a vm-main/vm-backup para instalar los agentes
  • Docker — contenedor del hub, en vm-main
  • Gestión de secretos — dónde viven BESZEL_DASHBOARD_PASSWORD y los BESZEL_AGENT_TOKEN_*
  • ctunlinux — el host de Trivasa donde se probó la vía por API, sin ruta SSH a vm-playground; también donde se perdió y recuperó el fingerprint dos veces
  • NetBird — la tabla de ruteo compartida entre netbird/netbird-conka que bloqueaba a 4 hosts de Conkafecito, sin relación con Beszel en sí
  • SSH config de la flota — organización por prefijo — IPs corregidas de la flota de Conkafecito usadas para migrar estos agentes