Soularr: plan de identidad para la UI — 20 octubre 2026¶
Avance del 22 de octubre: código central instalado, identidad pendiente¶
La lectura de las 13:04 CEST identificó el controlador central de CT212 como
la versión e64bbba, sin el perfil soularr-auth-v1 preparado en fuente.
A las 13:15:59 se actualizó únicamente /usr/local/bin/homelab-ctl al código
exacto de main <REDACTED>, con copia privada
durable de la versión anterior en el nodo y readback completo. Propietario,
permisos 0755, boot, ancestros y filesystem local se comprobaron antes/después.
No se ejecutó el controlador, install.sh o sync; no se leyeron tokens ni
se cambiaron rutas, contenedores o servicios.
Este paso instala una capacidad opt-in; no activa autenticación. Siguen pendientes las identidades permitidas de Pocket ID, el cliente dedicado y su callback, la admisión de consumidores/ACL IPv4 e IPv6 y la transición del proxy con login real, conservando worker, datos y puertos previstos. La mera presencia del literal del perfil no demuestra su comportamiento desplegado.
PR158 también corrige una
indicación peligrosa: sync --dry-run puede crear o actualizar caché local;
no debe usarse como lectura pasiva aunque no despliegue rutas. La revisión del
instalador incluyó ocho casos locales en Python 3.12/3.14: colisiones y
sustitución de temporales, deriva, fallos de fsync y señales de cancelación.
Recibo privado de instalación soularr-controller-code-install-dzh4bhx_/native.json,
SHA a320fd37…. Una lectura independiente a las 13:17:55–57 confirmó código,
metadatos y boot exactos, con FDs cerrados y cero ejecución del controlador;
recibo soularr-controller-independent-code-326n54tz/native.json, SHA 7e995059….
Ninguna de estas lecturas acredita la activación del proxy.
Contexto de la propuesta del 20 de octubre¶
Propuesta sin cambios de configuración/runtime. Continúa el hallazgo LAN del 19 octubre, no es nuevo. Solo fuentes locales y upstream oficial; sin SSH, HTTP de producto, config privada, env, secretos, Vera, login o despertares. No se repitió el runtime conocido de las 18:26 del 20 octubre.
Conclusión y evidencia¶
Upstream no ofrece actualmente autenticación nativa y no se ha encontrado un adaptador OIDC reutilizable en las fuentes revisadas. No hay arreglo seguro de una variable: desactivar UI, cerrar 8265 o bind loopback rompería accesos. Se propone ensayar un proxy OIDC estándar delante del editor, conservando puerto, hostname y worker. No se instala un componente para completar esta auditoría.
Fuente Compose: ~/Dev/homelab-stacks, HEAD b1ae78c, limpio y sin AGENTS
propio al revisar. ~/stacks no existe en este Mac. Propietario conocido:
VM208 /home/monxas/stacks/media/compose.yaml.
Upstream oficial consultado el 20 octubre, commit
<REDACTED>,
del 6 octubre: AST de
webui/webui.py
solo contiene decoradores route, sin hook/middleware/import de identidad.
GET/POST config y DELETE de importaciones siguen sin gate propio.
run.sh
ofrece WEBUI_ENABLED/WEBUI_PORT, sin variables de identidad. No se ejecutó código
upstream ni descargó imagen nueva.
Revisión de Ansible del worktree container-monitor-errors-20261020, en especial
roles/caddy_lxc, y fuentes de homelab-stacks (excluyendo env, config privada,
appdata y dependencias): no aparecen despliegues OAuth2 Proxy, Authelia,
Tinyauth o caddy-security. El rol describe plugins Cloudflare DNS y Sablier.
El snippet WP-Pulse conserva una referencia histórica forward_auth Pocket ID;
no es un adaptador válido. El mismo archivo y reference/cf-access.md explican
que Pocket ID no ofrece /forward-auth. No reutilizar ese patrón ni inferir
que está activo; este trabajo no modifica WP-Pulse.
Dependencias y consumidores encontrados en fuentes¶
| Relación | Consecuencia |
|---|---|
| Navegador → Caddy .40/.41/VIP → VM208:8265 | Conservar hostname, TLS y ambos proxies |
| Navegador LAN → VM208:8265 | El puerto también debe conducir al gate |
| WAN → Cloudflare Access → Caddy | Mantener Access; no cubre LAN |
| Worker → Lidarr/slskd | depends_on en Compose; preservar red media, credenciales y pipeline |
| Datos | Conservar /home/monxas/appdata/soularr:/data y /mnt/nfs_media/downloads/soulseek:/downloads, RW actuales |
| Calendario | SCRIPT_INTERVAL=1800; no convertir worker a lazy ni añadir cron |
En fuentes tracked de homelab-stacks, 8265 aparece solo en media/compose.yaml y reverse-proxy/managed.caddy. No apareció otro consumidor entrante automatizado en las fuentes de infraestructura revisadas. No acredita todos los clientes: marcadores/dispositivos y tareas sin versionar siguen pendientes. El worker consulta Lidarr/slskd; eso no exige que estos llamen a su UI.
Opción concreta para intervención posterior¶
OAuth2 Proxy como reverse proxy completo evita modificar el binario Caddy o inventar autenticación en Flask. Referencias oficiales: OIDC y configuración. No se selecciona tag mutable ni se generan secretos en este plan. Al introducir una dependencia, seguir la guía existente de altas, no un instalador paralelo.
- Inventariar consumidores humanos/automatismos de puerto, hostname y rutas; reconciliar fuente desplegada con Compose local y conservar hashes/rollback. No solicitar GET config para descubrir clientes.
- Preparar candidato aislado con versión/digest fijado y contrato. Medir RAM/CPU; dependencias nuevas: Pocket ID, DNS y TLS para discovery/callback. Caída del proxy/IdP bloquea UI sin parar worker. El candidato inicial puede usar cookies cifradas, sin DB/Redis nuevo.
- Cliente OIDC exclusivo, callback exacta
https://soularr.monxas.casa/oauth2/callback, identidades autorizadas explícitas, sin comodín de email. Secretos en almacenes privados existentes. Comprobar issuer/audience/nonce/state y PKCE S256 con la versión elegida. Cookies Secure, HttpOnly y host-only; no transmitir tokens del IdP al backend sin necesidad. - Mantener host:8265, publicado por el proxy. Retirar solo publicación host
de Soularr; backend sigue en red media para Lidarr/slskd. Proxy alcanza
http://soularr:8265por una red acotada, sin mounts de datos/socket Docker. Preservar imagen Soularr, mounts y SCRIPT_INTERVAL. La red media continúa siendo límite de confianza: no pretende aislar otro contenedor comprometido. - Mover tunnel.hostname del backend al proxy: un dueño de ruta. Declarar puerto
interno/publicado del proxy según renderer; no copiar 8265 como puerto interno
si escucha en 4180. Caddy puede conservar upstream host
.208:8265, ahora con gate. Preparar render/diff sin editar managed.caddy generado ni ejecutar sync como inspección. Ambas fuentes deben converger sin alterar rutas ajenas. - Entrada por IP conduce al hostname TLS; probar Host arbitrario, redirección
abierta y cabeceras falsas. Proteger static,
/stream, config y métodos mutadores por el mismo gate; no crear bypass por comodidad. Cerrar solo el puerto o autenticar solo Caddy dejaría otras rutas de elusión. - Fixture aislada sin credenciales/descargas: GET/POST/DELETE ficticios y SSE. Probar anónimo, autorizado/no autorizado, cookie inválida, CSRF, callback adulterado, cabeceras falsificadas y bypass LAN/IPv6; reconexión stream y UI. Si proxy/app no cubren CSRF/Origin necesarios en la versión elegida, resolver mediante mecanismos estándar antes de desplegar, no inferir cobertura de OIDC.
- Solo tras revisar candidato: transición de puerto/labels sin backend público, recreación acotada conservando datos/imagen/políticas, ambos Caddy/VIP/edge y acceso humano real. No provocar descargas como prueba. Rollback comprende Compose, proxy, labels y cliente; volver al previo restaura la UI LAN sin gate.
Cierre y límites¶
UI accesible con identidad LAN/WAN y sin bypass host:8265; usuario no autorizado no obtiene config/logs ni cambia importaciones; pipeline/datos previos intactos. Reutilizar service_contracts/service_routes, sin cron ni plataforma nueva de observación. Login personal permanece pendiente hasta probarlo realmente.
Se ha preparado un candidato inactivo con configuración y fixture local. OAuth2 Proxy y Caddy oficiales prueban OIDC sintético firmado, PKCE/nonce, allowlist, Origin y SSE de dos eventos. No son pruebas de productos reales. El candidato sigue bloqueado para despliegue por clientes desconocidos, integración única de renderer/ACL, recursos y validación de Pocket ID pendientes.
20-10-2026: integración del perfil en fuente, sin despliegue¶
Se prepara tunnel.access_profile=soularr-auth-v1 en el renderer central
services/homelab-ctl/homelab-ctl.py. La fuente de instalación
services/homelab-ctl/install.sh copia ese fichero a /usr/local/bin/homelab-ctl
en CT212; el README del componente documenta que VM208 quedó con control local
y reenvía las operaciones de rutas al controlador central. Esto acredita el
propietario en fuente; no demuestra que el runtime CT212 contenga este cambio.
No se modifica scripts/homelab-ctl.py ni se ejecuta el instalador.
El perfil admite únicamente Soularr, VM208:8265 y no lazy; genera el mismo handle del candidato con Origin exacto para POST/PUT/PATCH/DELETE y eliminación explícita de las cinco cabeceras documentadas. Perfil vacío/desconocido, propietario/destino inválido, ruta static con perfil y duplicados del hostname protegido bloquean la generación antes de escritura, sin elegir un dueño por orden. La proyección de inventario/cache conserva la etiqueta; las rutas sin perfil mantienen sus bytes. No se introduce un mecanismo genérico de snippets.
Pruebas locales aisladas cubren esos contratos y comparan el bloque con el candidato. El binario oficial Caddy2.11.7 ya disponible adapta el resultado y se comprueban sus matchers/orden/headers JSON; esto es parseo offline, no prueba de peticiones ni validación del plugin/runtime de los dos Caddy. El workflow existente service-contract-tests amplía sus paths y ejecuta los tests del renderer central en Python3.10/3.12, antes fuera de sus dos directorios discover.
Sigue inactivo: no se cambian labels/Compose/firewall, cliente Pocket ID, credenciales ni recursos. Antes de desplegar siguen siendo necesarias la reconciliación y aplicación coordinada del overlay preparado, ACL IPv4/IPv6 sin bypass, inventario de consumidores directos, configuración privada/identidades elegidas, permisos del UID y validaciones reales de login y presupuesto N1. El gate OIDC no sustituye al gate Origin de la aplicación.
20-10-2026: transición Compose preparada, todavía inactiva¶
El overlay candidato
ya conserva worker, imagen, intervalo1800, mounts y dependencias media, y
traslada el único puerto host8265 y hostname al proxy interno4180 con perfil
soularr-auth-v1. Cinco pruebas estructurales pasan con cada CLI local
Compose v2.35.1-desktop.1 y5.5.1, incluido el merge de la fuente local sin
modificarla ni copiarla. El recibo de validación
registra alcance y límites; no acredita Compose desplegado ni acceso real.
El overlay no participa en la configuración activa. Su perfil sólo controla el proxy: combinar el archivo ya elimina puertos/labels del worker, y solicitar explícitamente el proxy puede arrancarlo sin activar antes el perfil. No se incluye ni se ha ejecutado una orden de despliegue. La red interna nueva acota sus dos miembros, pero conservar la red media deja acceso directo al backend desde sus pares. Siguen pendientes clientes/automatismos, ACL y ese límite de confianza, Pocket ID, permisos, recuperación y recursos/N1. No se ha cambiado runtime, firewall, renderer instalado ni contratos activos.