# shuma-daemon — el dueño de los Workspaces de shuma: sesiones PTY, paneles y el socket de admin # que consultan el gateway, el TUI y el shell. Es el que hace que `/shuma/*` sirva de algo. # # ── POR QUÉ ESTA RECETA (2026-09-16) ──────────────────────────────────────────────────────────── # Va en par con `shuma-gateway`: el gateway sin daemon es un puente a ninguna parte. Los dos corren # hoy en gioser desde binarios puestos a mano —el del daemon, además, desde un **inodo borrado**— y # la mudanza los reconstruye en vez de copiarlos (SDD 28 §6.34). # # ⚠ **Lo que esta receta NO resuelve, y hay que decirlo acá**: en gioser el daemon corre como # `sergio`, no como root, y el payload `Native` de una tarjeta de arje **no tiene campo de usuario** # (SDD 29 §4.0 quinquies). Declararlo sin más lo pondría a correr como root, que no es «perder una # opción» sino cambiar el sistema. La bajada de privilegio se decide al escribir la tarjeta, no acá. name = "shuma-daemon" version = "0.1.0" license = "MIT OR Apache-2.0" [source] repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git" commit = "23a292863f53b355c5c02d6185904f2c33d8ab42" cargo_vendor_dir = ".hammer-cargo-vendor" [build] compiler = "zig-cc" target = "x86_64-linux-musl" link = "static" flags = ["-p", "shuma-daemon", "--bin", "shuma-daemon"] # ── LA CUENTA (SDD 30) ────────────────────────────────────────────────────────────────────────── # Fuera de `hash_inputs`: declarar esto NO re-hashea shuma-daemon (control corrido, el hash no se # movió). # # ⚠ EN GIOSER CORRE COMO `sergio`, Y ESO NO SE PUEDE TRADUCIR SOLO. El payload `Native` de arje no # tiene campo de usuario (SDD 29 §4.0 quinquies), así que una tarjeta escrita «como estaba» lo # pondría de ROOT — y esto es un demonio que abre PTYs y ejecuta shells: correrlo de root no es # perder una opción, es entregar la máquina. La cuenta es propia y sin privilegio, y el descenso se # hace en el comando con `setuidgid`, igual que gitea. [[user]] name = "shuma" uid = 967 home = "/var/lib/shuma" # ⚠ Y LA SHELL NO ES UN DETALLE ACÁ. El default de `[[user]]` es `/bin/false`, que es lo correcto # para un demonio (gitea, squid) y **lo exactamente contrario** para éste: shuma-daemon existe para # abrir PTYs y lanzar shells. Con `/bin/false` el servicio arranca, se supervisa, contesta… y cada # pestaña que alguien abra muere al instante. Un fallo que no se ve al desplegar: se ve al usarlo. shell = "/bin/sh" # ── EL SERVICIO ───────────────────────────────────────────────────────────────────────────────── # Las guardas salen 78 NOMBRANDO EL ARREGLO. Es lo que hace la diferencia entre un servicio que # reintenta para siempre con «unknown user» y uno que dice qué falta: medido con gitea, cuya imagen # arrancaba perfecta y sin el servicio por el que existe. # # `XDG_RUNTIME_DIR` no es decoración: es donde el daemon pone su socket, y es por ese socket que el # gateway le habla. En gioser vale `/run/shuma`, medido en el entorno del proceso vivo. [[service]] label = "shuma-daemon" id = "01M2EKDA00SH0MADAEM0N7X4K2" exec = "/bin/busybox" argv = ["sh", "-c", "/bin/grep -q '^sergio:' /etc/passwd || { echo 'shuma-daemon: no existe el usuario `sergio` en /etc/passwd — la receta lo declara con [[user]]; la imagen lo compone con `takana users`' >&2; exit 78; }; mkdir -p /run/shuma /var/lib/shuma || exit 78; chown shuma:shuma /run/shuma /var/lib/shuma || exit 78; cd /home/sergio || exit 78; exec /usr/bin/setuidgid sergio /usr/bin/shuma-daemon"] envp = [["PATH", "/usr/bin:/bin"], ["HOME", "/home/sergio"], ["USER", "sergio"], ["XDG_RUNTIME_DIR", "/run/shuma"]] networking = "full" cgroup = "arje.slice/shuma-daemon" restart = { initial_ms = 1000, max_ms = 30000 } # ── ⚠ `shuma-askpass` NO VA EN ESTA CAJA, y conviene decirlo acá porque el daemon lo PIDE ──────── # Al arrancar, shuma-daemon avisa: «askpass: no encontré `shuma-askpass` … sudo/ssh pedirán la clave # por el TTY». Se intentó darle la receta (2026-09-16) y el resultado fue mejor que construirla: # # 1. **No construye**: su dependencia `atspi-common` muere con `custom attribute panicked — # message: File has no extension.` en el proc-macro `#[validate(signal: …)]`, que lee un # fichero en tiempo de compilación y no resuelve la ruta dentro del sandbox (`/src/...`). # 292 errores en cascada, todos hijos de ese pánico. # 2. **Y no hace falta**: su propio `Cargo.toml` la describe como «Mini-ventana Llimphi compatible # con SUDO_ASKPASS» — es una VENTANA (llimphi-ui, theme, widget-text-input, clipboard). En un # servidor sin pantalla no tiene dónde dibujarse, y las sesiones de shuma son PTYs: ahí el # prompt por TTY es el camino correcto, no una degradación. # # ⇒ el aviso del daemon es para el escritorio, no para el servidor. Si algún día hace falta acá, # primero hay que resolver el proc-macro de atspi, no reponer la receta. # ── ⚠ CORRE COMO `sergio`, NO COMO `shuma` (2026-09-17) ───────────────────────────────────────── # La cuenta `shuma` se creó cuando la caja no tenía usuario de la persona. Ahora sí, y shuma es su # CONSOLA: las pestañas que abre son sesiones suyas, y desde ahí lanza `claude`, que entra a la # jaula `claude-sergio` con SU memoria y SUS credenciales. Con el daemon corriendo como `shuma`, # cada terminal de la web habría sido de otro usuario que no es nadie — y `claude` habría buscado # una jaula `claude-shuma` que no existe.