Files
takana/scripts/servidor/claude-caja.sh
T
SergioandClaude Opus 5 e7b77ff657 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>
2026-09-17 18:31:30 +00:00

39 lines
2.3 KiB
Bash
Executable File

#!/bin/sh
# 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`. El camino que sí anda es
# pedírselo al ANFITRIÓN por ssh:
#
# 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:
#
# 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}" "$@"