gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Definiciones

granja: vps-setup soporta Fedora/LXC además de Debian/Ubuntu

Un LXC prestado (dev.gioser.net, Fedora 44, 6 núcleos, 196 G) pasa a ser el worker
mientras esté disponible; el camino Debian queda intacto para seguir abriendo
workers efímeros en Hetzner.

Cambios:
- familia detectada por gestor de paquetes (apt | dnf5/dnf) con sus equivalencias
  (build-essential -> gcc/g++/make, libssl-dev -> openssl-devel, uidmap ->
  shadow-utils, xz-utils -> xz).
- el veredicto de userns deja de ser "escribí el sysctl" y pasa a ser "unshare -Umr
  funciona de verdad": en un contenedor el sysctl es read-only y no hace falta,
  porque el userns lo concede el host. Si no se puede crear, aborta: sin eso la caja
  no puede ser worker.
- swapon degrada a AVISO RUIDOSO en vez de abortar. En LXC devuelve Operation not
  permitted (medido) y no hay forma desde dentro; el swap lo da el host. Se dice
  explícito que sin swap el techo de RAM es duro y el OOM killer no avisa antes.
- documenta los dos pasos que una caja virgen necesita del hub y que la golden
  escondía: instalar rsync a mano, y que el HUB EMPUJE el lab ya verificado en vez
  de que el worker lo baje del Storage Box (el worker no debe tener secretos).

Validado provisionando dev.gioser.net de cero: hammer compila, el lab extrae y
verifica por sha256, y el toolchain queda "idéntico al lock (108 paquetes)".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4

853853d9198ee1a19b56610795f9bc0be351b238 · por Sergio · (hace 1 mes) · padre 52b923953 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

1 archivos · +86 −16

diff --git a/scripts/farm/vps-setup.sh b/scripts/farm/vps-setup.sh
index 19c6d88e..51edaac0 100755
--- a/scripts/farm/vps-setup.sh
+++ b/scripts/farm/vps-setup.sh
@@ -1,40 +1,98 @@
 #!/usr/bin/env bash
-# vps-setup.sh — provisiona un WORKER de granja hammer en un VPS Debian/Ubuntu fresco.
+# vps-setup.sh — provisiona un WORKER de granja hammer en un VPS o LXC fresco.
+#
+# DOS FAMILIAS SOPORTADAS, detectadas por gestor de paquetes:
+#   · apt  → Debian/Ubuntu: los workers efímeros de Hetzner (`farm-up.sh`, imagen golden).
+#   · dnf  → Fedora: el LXC prestado `dev.gioser.net` (2026-08-28), que reemplaza al worker
+#            de pago mientras esté disponible. NO se retira el camino Debian: la capacidad de
+#            abrir workers en Hetzner se conserva intacta.
 #
 # Modelo hub-and-spoke: el LAPTOP es el hub (tiene la clave de firma + gitea). El worker
 # NO toca gitea ni firma nada — sólo construye la cola `recipes/incoming/` y sella al store
 # local (PROMOTE=0). El hub le rsync-ea código+cola y le baja el store con `farm-sync.sh`.
 #
 # El hub corre esto por SSH tras rsync-ear el repo a $HAMMER_DIR. Idempotente (re-correr
-# actualiza in-place). Necesita root (apt + sysctl + swap + systemd).
+# actualiza in-place). Necesita root (paquetes + systemd).
+#
+# ── LO QUE UN CONTENEDOR NO DEJA HACER, Y NO ES UN FALLO ─────────────────────────────────────
+# En LXC `sysctl -w` es read-only y `swapon` devuelve `Operation not permitted` (medido en
+# dev.gioser.net, 2026-08-28). Los dos pasos degradan a aviso en vez de abortar:
+#   · sysctl: en Fedora los userns no están capados de fábrica, así que no hace falta.
+#   · swap:   NO se puede crear desde dentro. Si la caja va justa de RAM, el swap lo tiene que
+#             dar el HOST (en Proxmox es el parámetro `swap:` del contenedor). Un `swapon` que
+#             falla se avisa RUIDOSO, porque sin swap un build Rust grande no se pone lento:
+#             lo mata el OOM killer.
 #
 # Uso (en el VPS, como root):   HAMMER_DIR=/opt/hammer ./scripts/farm/vps-setup.sh
+#
+# ── CAJA FRESCA (no golden): DOS PASOS DEL HUB ANTES DE ESTO ────────────────────────────────
+# La imagen golden de Hetzner ya trae rsync y el lab horneados. Una caja virgen, no:
+#
+#   1. `rsync` no está instalado ⇒ no se puede subir el repo con rsync. Huevo y gallina:
+#        ssh root@caja 'dnf install -y rsync git'   # o apt-get install -y rsync git
+#
+#   2. El lab (`.dev-fs/`) lo EMPUJA EL HUB, no lo baja el worker. `lab-image.sh --traer`
+#      tira del Storage Box y eso exige credenciales — que el worker NO debe tener (modelo
+#      hub-and-spoke: compute puro, sin secretos). El hub le manda el tarball ya verificado
+#      y el worker lo re-verifica por sha256 al extraerlo:
+#        rsync -a .dev-fs/lab-image.tar.zst  caja:/opt/hammer/.dev-fs/lab-<SHA>.tar.zst
+#        rsync -a .dev-fs/tools/             caja:/opt/hammer/.dev-fs/tools/
+#      Mandar `tools/` entero (zig 0.13.0 + 0.16.0 + go) y no dejar que se descarguen solos
+#      evita el zig-skew: el worker usa EXACTAMENTE las versiones del hub.
 set -euo pipefail
 
 HAMMER_DIR="${HAMMER_DIR:-/opt/hammer}"
 cd "$HAMMER_DIR"
 
-echo "==> 1. deps del sistema (apt)"
-export DEBIAN_FRONTEND=noninteractive
-apt-get update -q
-apt-get install -y -q git build-essential curl pkg-config libssl-dev \
-    bubblewrap rsync ca-certificates uidmap xz-utils
+# ── detección de familia ────────────────────────────────────────────────────────────────────
+if command -v apt-get >/dev/null 2>&1; then PKG=apt
+elif command -v dnf5 >/dev/null 2>&1; then PKG=dnf; DNF=dnf5
+elif command -v dnf   >/dev/null 2>&1; then PKG=dnf; DNF=dnf
+else echo "!! ni apt ni dnf: familia no soportada" >&2; exit 1
+fi
+echo "==> 0. familia detectada: $PKG  ($(. /etc/os-release 2>/dev/null; echo "${PRETTY_NAME:-?}"))"
+
+echo "==> 1. deps del sistema ($PKG)"
+if [ "$PKG" = apt ]; then
+    export DEBIAN_FRONTEND=noninteractive
+    apt-get update -q
+    apt-get install -y -q git build-essential curl pkg-config libssl-dev \
+        bubblewrap rsync ca-certificates uidmap xz-utils
+else
+    # Equivalencias Fedora. `build-essential` no existe: gcc/g++/make sueltos.
+    # uidmap → shadow-utils (trae newuidmap/newgidmap); xz-utils → xz; libssl-dev → openssl-devel.
+    $DNF install -y -q git gcc gcc-c++ make curl pkgconf-pkg-config openssl-devel \
+        bubblewrap rsync ca-certificates shadow-utils xz tar findutils
+fi
 
-echo "==> 2. user namespaces para bwrap (Debian/Ubuntu los capan por defecto)"
-sysctl -w kernel.unprivileged_userns_clone=1 2>/dev/null || true
-sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 2>/dev/null || true
-cat > /etc/sysctl.d/99-hammer-userns.conf <<'EOF'
+echo "==> 2. user namespaces para bwrap"
+# Debian/Ubuntu los capan de fábrica; Fedora no. En un contenedor `sysctl -w` es read-only y
+# esto no importa, porque el userns lo concede el HOST. Todo el paso es best-effort.
+if [ "$PKG" = apt ]; then
+    sysctl -w kernel.unprivileged_userns_clone=1 2>/dev/null || true
+    sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 2>/dev/null || true
+    cat > /etc/sysctl.d/99-hammer-userns.conf <<'EOF'
 kernel.unprivileged_userns_clone=1
 kernel.apparmor_restrict_unprivileged_userns=0
 EOF
-sysctl --system >/dev/null 2>&1 || true
+    sysctl --system >/dev/null 2>&1 || true
+fi
+# El veredicto no es el sysctl: es que el userns REALMENTE se pueda crear. Se comprueba.
+if ! unshare -Umr true 2>/dev/null; then
+    echo "!! FATAL: no se pueden crear user namespaces sin privilegios." >&2
+    echo "   Sin esto el sandbox del lab (bwrap --unshare-all) no arranca y esta caja no" >&2
+    echo "   puede ser worker. En LXC lo habilita el host." >&2
+    exit 1
+fi
+echo "   userns: OK"
 
 echo "==> 2b. bubblewrap con soporte overlay (el de la distro suele ser viejo/sin overlayfs)"
 # El sandbox del lab usa `bwrap --overlay-src --tmp-overlay`; bubblewrap <0.10 (p.ej. el 0.9.0 de
 # Ubuntu 24.04) responde "Unknown option --overlay-src". Compilamos 0.11.2 a /usr/local/bin (gana
 # el PATH de systemd) si el instalado no lo soporta.
 if ! bwrap --help 2>&1 | grep -q overlay-src; then
-    apt-get install -y -q meson ninja-build libcap-dev
+    if [ "$PKG" = apt ]; then apt-get install -y -q meson ninja-build libcap-dev
+    else $DNF install -y -q meson ninja-build libcap-devel; fi
     BWV=0.11.2
     curl -sL "https://github.com/containers/bubblewrap/releases/download/v${BWV}/bubblewrap-${BWV}.tar.xz" -o /tmp/bwrap.tar.xz
     ( cd /tmp && rm -rf "bubblewrap-${BWV}" && tar xf bwrap.tar.xz && cd "bubblewrap-${BWV}" \
@@ -45,10 +103,22 @@ if ! bwrap --help 2>&1 | grep -q overlay-src; then
 fi
 
 echo "==> 3. swap 16G (8GB de RAM es justo para builds Rust con JOBS=2)"
+# En un contenedor esto FALLA por diseño (swapon exige CAP_SYS_ADMIN del host). No se aborta,
+# pero se avisa fuerte: sin swap el límite de RAM es duro y el OOM killer no avisa antes.
 if ! swapon --show 2>/dev/null | grep -q /swapfile; then
-    fallocate -l 16G /swapfile 2>/dev/null || dd if=/dev/zero of=/swapfile bs=1M count=16384 status=none
-    chmod 600 /swapfile; mkswap /swapfile >/dev/null; swapon /swapfile
-    grep -q '/swapfile' /etc/fstab || echo '/swapfile none swap sw 0 0' >> /etc/fstab
+    if fallocate -l 16G /swapfile 2>/dev/null || dd if=/dev/zero of=/swapfile bs=1M count=16384 status=none; then
+        chmod 600 /swapfile; mkswap /swapfile >/dev/null 2>&1
+        if swapon /swapfile 2>/dev/null; then
+            grep -q '/swapfile' /etc/fstab || echo '/swapfile none swap sw 0 0' >> /etc/fstab
+            echo "   swap activo: $(swapon --show=NAME,SIZE --noheadings | tr '\n' ' ')"
+        else
+            rm -f /swapfile
+            echo "   ⚠ SIN SWAP: el kernel no deja activarlo (normal en LXC)."
+            echo "     RAM disponible: $(free -g | awk '/Mem/{print $2}') G — es un techo DURO."
+            echo "     Un build Rust grande que se pase NO se pone lento: lo mata el OOM killer."
+            echo "     Si hace falta más, lo da el host (en Proxmox: parámetro 'swap:' del contenedor)."
+        fi
+    fi
 fi
 
 echo "==> 4. rust host toolchain (para buildear el binario hammer)"