la cuenta de sergio en la caja, su jaula propia, y shuma corriendo como él
Pedido: «crea mi cuenta sergio con la clave tawasuyu, desde ahí abrir los claudes como lo estoy
haciendo acá con shuma sobre los proyectos».
· cuenta `sergio` uid 1001 (el mismo que en gioser), home /home/sergio, clave verificada
· su propia jaula `claude-sergio`, que concede SU home —su `.claude`: credenciales y memoria— y
NO el de root. Con la instancia de root, sergio moría en «bwrap: Can't mkdir /root/.claude»
· `claude` elige instancia por usuario; `PROY=/otra/ruta claude` abre el agente sobre otro proyecto
· shuma-daemon y shuma-gateway pasan a correr como `sergio`, no como la cuenta de servicio `shuma`:
shuma es su CONSOLA, y cada pestaña que abre tiene que ser una sesión suya — si no, `claude`
buscaría una jaula `claude-shuma` que no existe
⚠ NO se eleva con doas/sudo: en esta caja el setuid NO TOMA («doas: Operation not permitted», con
NoNewPrivs 0 y `/` sin nosuid — queda como deuda entender por qué). No hace falta: `qorpa run`
levanta la jaula con user namespaces y anda sin privilegio, siempre que el directorio de la
instancia sea del usuario.
⚠ Y un detalle que costó una vuelta: sin `shift 2`, el HOME y el proyecto que el lanzador pasa como
posicionales se cuelan COMO ARGUMENTOS del agente — la primera sesión se abrió con el prompt
«/home/sergio», y el agente contestó, con razón, que eso es una ruta y no un comando.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -55,8 +55,8 @@ shell = "/bin/sh"
|
||||
label = "shuma-daemon"
|
||||
id = "01M2EKDA00SH0MADAEM0N7X4K2"
|
||||
exec = "/bin/busybox"
|
||||
argv = ["sh", "-c", "/bin/grep -q '^shuma:' /etc/passwd || { echo 'shuma-daemon: no existe el usuario `shuma` 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 /var/lib/shuma || exit 78; exec /usr/bin/setuidgid shuma /usr/bin/shuma-daemon"]
|
||||
envp = [["PATH", "/usr/bin:/bin"], ["HOME", "/var/lib/shuma"], ["USER", "shuma"], ["XDG_RUNTIME_DIR", "/run/shuma"]]
|
||||
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 }
|
||||
@@ -76,3 +76,10 @@ restart = { initial_ms = 1000, max_ms = 30000 }
|
||||
#
|
||||
# ⇒ 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.
|
||||
|
||||
@@ -48,8 +48,15 @@ flags = ["-p", "shuma-gateway", "--bin", "shuma-gateway"]
|
||||
label = "shuma-gateway"
|
||||
id = "01M2EKDA00SH0MAGATEWAY4K21"
|
||||
exec = "/bin/busybox"
|
||||
argv = ["sh", "-c", "/bin/grep -q '^shuma:' /etc/passwd || { echo 'shuma-gateway: falta el usuario `shuma` — lo declara recipes/shuma-daemon.toml' >&2; exit 78; }; test -s /var/lib/shuma/.config/shuma/gateway-token || { echo 'shuma-gateway: falta /var/lib/shuma/.config/shuma/gateway-token (32 B) — viene de ~/.config/shuma/gateway-token del origen; si generás uno nuevo, los clientes emparejados dejan de entrar' >&2; exit 78; }; cd /var/lib/shuma || exit 78; exec /usr/bin/setuidgid shuma /usr/bin/shuma-gateway"]
|
||||
envp = [["PATH", "/usr/bin:/bin"], ["HOME", "/var/lib/shuma"], ["USER", "shuma"], ["XDG_RUNTIME_DIR", "/run/shuma"]]
|
||||
argv = ["sh", "-c", "/bin/grep -q '^sergio:' /etc/passwd || { echo 'shuma-gateway: falta el usuario `sergio` — lo declara recipes/shuma-daemon.toml' >&2; exit 78; }; test -s /home/sergio/.config/shuma/gateway-token || { echo 'shuma-gateway: falta /home/sergio/.config/shuma/gateway-token (32 B) — viene de ~/.config/shuma/gateway-token del origen; si generás uno nuevo, los clientes emparejados dejan de entrar' >&2; exit 78; }; cd /home/sergio || exit 78; exec /usr/bin/setuidgid sergio /usr/bin/shuma-gateway"]
|
||||
envp = [["PATH", "/usr/bin:/bin"], ["HOME", "/home/sergio"], ["USER", "sergio"], ["XDG_RUNTIME_DIR", "/run/shuma"]]
|
||||
networking = "full"
|
||||
cgroup = "arje.slice/shuma-gateway"
|
||||
restart = { initial_ms = 1000, max_ms = 30000 }
|
||||
|
||||
# ── ⚠ 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.
|
||||
|
||||
@@ -2,19 +2,37 @@
|
||||
# claude — entrar al agente en esta caja. El CLI es glibc y la caja es musl: corre enjaulado
|
||||
# (ADR 0015), con el repo, el store, el lab, la memoria y las llaves concedidos y nada más.
|
||||
#
|
||||
# ── UNA JAULA POR PERSONA, Y SIN PRIVILEGIO ─────────────────────────────────────────────────────
|
||||
# `root` usa la instancia `claude`; cada usuario usa `claude-<usuario>`. No es purismo: la instancia
|
||||
# concede el HOME de quien entra —su `.claude`, o sea sus credenciales y su memoria— y una sola
|
||||
# instancia obligaría a compartirlo. Medido: con la instancia de root, `sergio` muere en
|
||||
# `bwrap: Can't mkdir /root/.claude: Permission denied`.
|
||||
#
|
||||
# ⚠ Y NO se eleva con `doas`/`sudo`: en esta caja **el setuid no toma** («doas: Operation not
|
||||
# permitted», con `NoNewPrivs: 0` y `/` sin `nosuid` — queda como deuda entender por qué). No hace
|
||||
# falta: `qorpa run` levanta la jaula con user namespaces y anda **sin privilegio**, siempre que el
|
||||
# directorio de la instancia sea del usuario.
|
||||
#
|
||||
# ⚠ LOS BUILDS NO CORREN DENTRO DE LA JAULA. `takana build` levanta su propio bwrap y ahí falla con
|
||||
# «Can't mount proc on /proc» aunque la instancia declare `nesting = true` (un `bwrap --proc /proc`
|
||||
# a mano SÍ funciona adentro: lo que falla es el userns anidado que arma el sandbox del build).
|
||||
# El camino que sí anda —y el que el agente debe usar— es pedírselo al ANFITRIÓN por ssh:
|
||||
# «Can't mount proc on /proc» aunque la instancia declare `nesting = true`. El camino que sí anda es
|
||||
# pedírselo al ANFITRIÓN por ssh:
|
||||
#
|
||||
# ssh -p 22022 -i /root/.ssh/github5 root@127.0.0.1 \
|
||||
# 'cd /opt/takana && flock -o work/.farm-build.lock takana --store /store build <receta>'
|
||||
# ssh -p 22022 root@127.0.0.1 'cd /opt/takana && flock -o work/.farm-build.lock takana build <r>'
|
||||
set -eu
|
||||
|
||||
_yo="$(id -un)"
|
||||
_hogar="${HOME:-/root}"
|
||||
_inst="claude"
|
||||
[ "$_yo" != "root" ] && _inst="claude-$_yo"
|
||||
|
||||
# El `cd` no es comodidad: la memoria del agente se indexa POR RUTA DE TRABAJO. Desde `/` —que es
|
||||
# donde `qorpa run` deja el shell— la sesión usa el proyecto `-` y el agente empieza sin saber nada
|
||||
# aunque su memoria esté en disco. `PROY` permite abrir el agente sobre OTRO proyecto:
|
||||
#
|
||||
# Comprobado el 2026-09-17: así se selló `sof-firmware` desde dentro de la jaula.
|
||||
# ⚠ EL `cd` NO ES COMODIDAD: la memoria del agente se indexa POR RUTA DE TRABAJO. Arrancando desde
|
||||
# `/` —que es donde `qorpa run` deja el shell— la sesión usa el proyecto `-` y el agente **empieza
|
||||
# sin saber nada**, aunque sus 163 ficheros de memoria estén en disco. Desde `/opt/takana` usa
|
||||
# `-opt-takana`, que es donde se renombró la memoria que vino de gioser (allá el repo era
|
||||
# `/mnt/vvv/takana`). Comprobado: preguntado por el logo, contesta «martillo 7×7, cuatro colores
|
||||
# exactos», que es exactamente lo que dice su memoria.
|
||||
exec takana qorpa run claude -- sh -c '''cd /opt/takana && exec env HOME=/root TERM="${TERM:-xterm-256color}" /work/claude-cli/2.1.240 "$@"''' -- "$@"
|
||||
# PROY=/opt/tawasuyu claude
|
||||
# ⚠ El `shift 2` no es adorno: sin él, el HOME y el proyecto que se pasan como posicionales se
|
||||
# cuelan COMO ARGUMENTOS del agente. Medido: la primera versión abrió la sesión con el prompt
|
||||
# «/home/sergio», y el agente contestó —con razón— que eso es una ruta, no un comando.
|
||||
exec takana qorpa run "$_inst" -- sh -c \
|
||||
'hogar="$1"; proy="$2"; shift 2; cd "$proy" && exec env HOME="$hogar" TERM="${TERM:-xterm-256color}" /work/claude-cli/2.1.240 "$@"' \
|
||||
_ "$_hogar" "${PROY:-/opt/takana}" "$@"
|
||||
|
||||
Reference in New Issue
Block a user