tawasuyu

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…

red en metal: de udhcpc/ifconfig/route a dhcpcd/ip — y el adduser que NO se migra

Los dos guiones de WiFi que corren DENTRO de la imagen (metal-iso.sh y
cosmic/metal-desktop-image.sh) usaban cuatro applets que salen del defconfig:
udhcpc, ifconfig, route y el guión de hooks que udhcpc necesita. Los usos eran
básicos —subir la interfaz, pedir IP, poner ruta y resolv.conf— así que van a las
herramientas ya declaradas en `base`: `ip` de iproute2 y `dhcpcd`.

Y el cambio arregla algo de paso, no sólo sustituye: dhcpcd queda de daemon
RENOVANDO el lease. Una de las dos causas medidas el 2026-08-06 de que el enlace
se cayera solo a mitad de una depuración remota era precisamente que `udhcpc -q`
pedía la dirección una vez y nadie la renovaba. El bloque wifi-keep que lo
mitigaba sigue (la otra causa, el AP que olvida clientes ociosos, no se toca).

`adduser` de alta-usuario.sh NO se migra, y esa es la decisión, no una omisión:
`useradd` es de shadow y su modelo nativo es escribir /etc/shadow — el fichero
cuya creación dejó a la caja sin aceptar ni la clave de root, con los ocho
dominios caídos ~20 min (SDD 28 §6.51). El script tiene un guardián explícito
para cazar justo eso. Cambiar el applet por la herramienta «buena» reintroduce el
fallo que el guardián existe para atrapar ⇒ `adduser` queda indultado en el
defconfig junto a setuidgid, switch_root, halt, poweroff y reboot. El día que la
caja adopte shadow de verdad se revisa entero.

⚠ Sin probar en metal: no tengo la laptop acá. El cambio es de una línea por
guión y las dos herramientas están en los 7 perfiles, pero quien lo arranque en
hardware que mire `ip -4 addr show` antes de dar la red por buena.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

87d34b95fe0117471875e6db30f20055baa20f87 · ruwaq Sergio · (1 killa ñawpaq) · tayta 29c244612 · kay commitpi sach'ata qhaway

Semántico sayk'uy

Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.

3 qillqakuna · +27 −22

diff --git a/scripts/cosmic/metal-desktop-image.sh b/scripts/cosmic/metal-desktop-image.sh
index 9b698162..acb65bc6 100755
--- a/scripts/cosmic/metal-desktop-image.sh
+++ b/scripts/cosmic/metal-desktop-image.sh
@@ -270,23 +270,12 @@ while [ $i -lt 40 ]; do
     i=$((i + 1)); sleep 1
 done
 [ "$ST" = COMPLETED ] || echo "   ⚠ no asoció (wpa_state=${ST:-?}). 4WAY_HANDSHAKE=clave; SCANNING=no ve la red"
-cat > /tmp/udhcpc.script <<'US'
-#!/bin/sh
-case "$1" in
-  bound|renew)
-    ifconfig "$interface" "$ip" netmask "${subnet:-255.255.255.0}"
-    [ -n "$router" ] && route add default gw "${router%% *}" dev "$interface" 2>/dev/null
-    [ -n "$dns" ] && { : > /etc/resolv.conf; for d in $dns; do echo "nameserver $d" >> /etc/resolv.conf; done; }
-    ;;
-esac
-exit 0
-US
-chmod +x /tmp/udhcpc.script
-# Tres intentos: el AP a veces no contesta el primer DISCOVER justo tras asociar.
-for t in 1 2 3; do
-    udhcpc -i "$IF" -n -q -s /tmp/udhcpc.script && break
-    echo "   DHCP intento $t sin respuesta, reintento…"; sleep 3
-done
+# DHCP con `dhcpcd` (2026-09-22). Antes era `udhcpc` de busybox + un guión de hooks propio que
+# llamaba a `ifconfig` y `route` — tres applets que salen del defconfig. `dhcpcd` hace las tres
+# cosas (dirección, ruta por defecto, /etc/resolv.conf) sin hooks, reintenta solo cuando el AP no
+# contesta el primer DISCOVER, y **se queda renovando el lease**: eso elimina una de las dos causas
+# del bloque de abajo, donde `udhcpc -q` pedía la dirección una vez y nadie la renovaba.
+dhcpcd "$IF" || echo "   DHCP sin respuesta tras los reintentos de dhcpcd"
 ip -4 addr show "$IF" | grep -w inet \
   || echo "sin IPv4. Mirá 'wpa_cli -i $IF status': si wpa_state=COMPLETED el problema es DHCP, no la clave"
 echo "== desde el laptop:  ssh -i ~/.ssh/hammer-metal root@<la IP de arriba> =="
@@ -296,7 +285,8 @@ chmod 0755 "$MERGED/usr/bin/wifi-up"
 # ── el enlace WiFi se caía solo y cortaba la depuración a mitad ─────────────────────────────────
 # Medido el 2026-08-06 depurando la OptiPlex por SSH sobre un hotspot: la máquina desaparecía de la
 # red cada pocos minutos. Dos causas que se suman, y ninguna es «la WiFi anda mal»:
-#   - `udhcpc -q` (el que usa wifi-up) pide la dirección UNA vez y termina: nadie renueva el lease.
+#   - `udhcpc -q` (el que usaba wifi-up) pedía la dirección UNA vez y terminaba: nadie renovaba el
+#     lease. ✅ RESUELTO el 2026-09-22 al migrar a `dhcpcd`, que se queda de daemon renovando.
 #   - el AP olvida a los clientes ociosos y deja de contestar ARP ⇒ «No route to host» desde fuera,
 #     mientras la máquina se cree perfectamente conectada. El síntoma engaña: no hay nada en dmesg.
 # El ping periódico resuelve las dos a la vez — detecta la caída Y mantiene viva la entrada en el AP.
diff --git a/scripts/metal-iso.sh b/scripts/metal-iso.sh
index 68d637b7..b7e4fb12 100755
--- a/scripts/metal-iso.sh
+++ b/scripts/metal-iso.sh
@@ -62,7 +62,7 @@ scripts/metal-firmware.sh "$AUG"
 mkdir -p "$AUG/usr/sbin"
 cp "$WPADIR"/wpa_supplicant "$WPADIR"/wpa_cli "$WPADIR"/wpa_passphrase "$AUG/usr/sbin/"
 
-# 4) helper de conexión WiFi (busybox ip/udhcpc + wpa_supplicant)
+# 4) helper de conexión WiFi (iproute2 + dhcpcd + wpa_supplicant)
 cat > "$AUG/usr/bin/wifi-connect" <<'WC'
 #!/bin/sh
 # wifi-connect SSID [PASSPHRASE] — asocia el WiFi y pide IP por DHCP.
@@ -75,7 +75,7 @@ for d in /sys/class/net/*; do
 done
 [ -n "$IF" ] || { echo "no hay interfaz wireless (¿cargó iwlwifi? revisá 'dmesg | grep iwlwifi')"; exit 1; }
 echo "==> interfaz: $IF"
-ip link set "$IF" up 2>/dev/null || ifconfig "$IF" up
+ip link set "$IF" up
 if [ -n "$PSK" ]; then
   wpa_passphrase "$SSID" "$PSK" > /tmp/wpa.conf
 else
@@ -85,8 +85,14 @@ pkill wpa_supplicant 2>/dev/null || true
 wpa_supplicant -B -i "$IF" -c /tmp/wpa.conf -D nl80211
 echo "==> asociando… (espera unos segundos; 'wpa_cli status' para ver el estado)"
 sleep 4
-udhcpc -i "$IF" -q -n || udhcpc -i "$IF"
-echo "==> listo. IP:"; ip addr show "$IF" 2>/dev/null | grep -w inet || ifconfig "$IF"
+# `dhcpcd` configura IP, ruta por defecto y /etc/resolv.conf él solo —no hace falta guión de
+# hooks— y se queda de daemon RENOVANDO el lease. Reemplaza al `udhcpc` de busybox (2026-09-22):
+# `dhcpcd` está declarado en el perfil `base` y `udhcpc` sale del defconfig.
+# ⚠ Sin `-1` a propósito: `udhcpc -q` pedía la dirección UNA vez y nadie renovaba el lease, que es
+# una de las dos causas medidas de que el enlace se cayera solo a mitad de una depuración remota
+# (ver el bloque `wifi-keep` de scripts/cosmic/metal-desktop-image.sh, 2026-08-06).
+dhcpcd "$IF"
+echo "==> listo. IP:"; ip addr show "$IF" | grep -w inet
 WC
 chmod +x "$AUG/usr/bin/wifi-connect"
 
diff --git a/scripts/servidor/alta-usuario.sh b/scripts/servidor/alta-usuario.sh
index ca7d21ae..820fc48e 100755
--- a/scripts/servidor/alta-usuario.sh
+++ b/scripts/servidor/alta-usuario.sh
@@ -12,6 +12,15 @@
 # Entonces el alta correcta acá es: crear la cuenta, dejar el hash donde el login lo lee, y
 # **comprobar que quien podía entrar sigue pudiendo** antes de darse por satisfecho.
 #
+# ⚠ Y por eso este `adduser` NO se migra a `useradd` (2026-09-22). El plan de botar busybox migra
+# los llamadores de applets a las herramientas declaradas —`ip` por `ifconfig`, `dhcpcd` por
+# `udhcpc`— porque esos usos son básicos. Éste no lo es: `useradd` es de `shadow`, y su modelo
+# NATIVO es escribir en `/etc/shadow`, que es justo el fichero que tumbó la caja. Cambiar el applet
+# por la herramienta «buena» reintroduciría el fallo que el guardián de abajo existe para cazar.
+# `adduser` queda INDULTADO en el defconfig de busybox por esta razón, junto a `setuidgid`,
+# `switch_root`, `halt`, `poweroff` y `reboot`. El día que la caja adopte shadow de verdad, esto se
+# revisa entero — no antes, y no de paso.
+#
 # Lo demás es lo que hace falta para «tener poder sobre la máquina, a mano y con claude»:
 #   · `/etc/sudoers.d/<u>`   — root a mano (el `sudo` de acá SÍ es setuid; `doas` no funciona)
 #   · `/etc/sub{u,g}id`      — sin rango, un userns anidado no puede mapear uid 0 y `takana build`