From be4de986bef3409a6d4108ccadbcf28436c862c1 Mon Sep 17 00:00:00 2001 From: sergio Date: Sat, 23 May 2026 01:56:31 +0000 Subject: [PATCH] =?UTF-8?q?feat(seed):=20arje-prod=20levanta=20red=20+=20s?= =?UTF-8?q?shd,=20as=C3=AD=20se=20puede=20entrar=20por=20SSH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sin systemd ni NetworkManager, arje-zero quedaba sin red y sin sshd: útil como bare init, inútil para sacar logs de una VPS sin pegado en la consola web. Dos Cards nuevas en el seed prod: - `net-up`: corre `/usr/sbin/arje-net-up` (script nuevo en scripts/), que pone up todas las interfaces y arranca `dhclient -d` en foreground sobre la primera no-loopback. Fallback a dhcpcd o busybox-udhcpc si dhclient no está. Crea de paso /run/sshd y /var/empty/sshd para que sshd no tenga que pelearlos. Restart supervisión. - `sshd`: corre `/usr/sbin/sshd -D -e` (foreground + log a stderr). Usa las host keys que Fedora ya tenía. Restart supervisión. El install script copia arje-net-up.sh a /usr/sbin/arje-net-up. Prerequisito en el host (no automatizable desde acá): si la VPS no tiene un cliente DHCP (Fedora Cloud trae sólo NetworkManager por defecto), el script duerme con el link up y no obtiene IPv4. En ese caso instalar antes del próximo boot: `dnf install dhcp-client`. Co-Authored-By: Claude Opus 4.7 --- scripts/arje-net-up.sh | 60 +++++++++++++++++++++++++++++++++ scripts/install-arje-as-init.sh | 3 ++ seeds/arje-prod.card.json | 32 ++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100755 scripts/arje-net-up.sh diff --git a/scripts/arje-net-up.sh b/scripts/arje-net-up.sh new file mode 100755 index 0000000..1682bee --- /dev/null +++ b/scripts/arje-net-up.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# arje-net-up — sube las interfaces de red y prepara los directorios de +# runtime que servicios "systemd-aware" (sshd, etc.) esperan que +# alguien les haya creado. Reemplaza parcialmente lo que +# systemd-networkd + tmpfiles harían en un boot normal de Fedora. +# +# Modelo: DHCP en foreground sobre la primera interfaz no-loopback. +# arje lo supervisa con Restart, así que si dhclient muere se relanza. +# IPv6 vía RA lo maneja el kernel solo al subir el link. + +set -u + +# Directorios que servicios sin systemd necesitan poblados. +mkdir -p /run/sshd # PID file de sshd +mkdir -p /var/empty/sshd # privsep chroot + +# Up todas las interfaces "reales". Se excluyen las virtuales obvias. +for sysiface in /sys/class/net/*; do + [ -d "$sysiface" ] || continue + name="$(basename "$sysiface")" + case "$name" in + lo|sit*|tun*|tap*|veth*|docker*|br-*|cni*|virbr*) continue ;; + esac + ip link set "$name" up 2>/dev/null || true +done + +# DHCP en foreground sobre la primera interfaz real encontrada. +iface="" +for sysiface in /sys/class/net/*; do + [ -d "$sysiface" ] || continue + name="$(basename "$sysiface")" + case "$name" in + lo|sit*|tun*|tap*|veth*|docker*|br-*|cni*|virbr*) continue ;; + esac + iface="$name" + break +done + +if [ -z "$iface" ]; then + echo "[arje-net-up] no encontré interfaces — durmiendo" >&2 + exec sleep infinity +fi + +echo "[arje-net-up] interfaz elegida: $iface" +if command -v dhclient >/dev/null 2>&1; then + # `-d` = foreground (sin daemonizar), `-v` = más verbose en stderr. + echo "[arje-net-up] dhclient -d -v $iface" + exec dhclient -d -v "$iface" +elif command -v dhcpcd >/dev/null 2>&1; then + # `-B` = foreground (no daemonize) en dhcpcd. + echo "[arje-net-up] dhcpcd -B $iface" + exec dhcpcd -B "$iface" +elif command -v udhcpc >/dev/null 2>&1; then + # busybox udhcpc — `-f` foreground. + echo "[arje-net-up] udhcpc -f -i $iface" + exec udhcpc -f -i "$iface" +else + echo "[arje-net-up] sin cliente DHCP — mantengo el link up (SLAAC) y duermo" >&2 + exec sleep infinity +fi diff --git a/scripts/install-arje-as-init.sh b/scripts/install-arje-as-init.sh index a913797..d9b378c 100755 --- a/scripts/install-arje-as-init.sh +++ b/scripts/install-arje-as-init.sh @@ -101,6 +101,9 @@ done for e in brahman-status busctl brainctl; do install -m 0755 "$EX_DIR/$e" "/usr/bin/$e" done +# Helper sh que levanta la red y crea los dirs de runtime que sshd +# espera. Lo invoca el Card `net-up` del seed. +install -m 0755 "$SCRIPT_DIR/arje-net-up.sh" /usr/sbin/arje-net-up echo "[install-arje] paso 3/5: instalar seed en /ente/seed.card.json" mkdir -p /ente diff --git a/seeds/arje-prod.card.json b/seeds/arje-prod.card.json index 4568459..8d1fd84 100644 --- a/seeds/arje-prod.card.json +++ b/seeds/arje-prod.card.json @@ -270,6 +270,38 @@ "lifecycle": "daemon", "priority": "low", "flow": { "input": [], "output": [] }, "genesis": [] }, + { + "schema_version": 1, + "id": "01J8YVKZQ0M0M0M0M0M0M0M0N0", + "lineage": null, + "label": "net-up", + "provides": [], "requires": [], + "permissions": { "networking": "full", "filesystem": "read-write", "ipc": { "allow": [] }, "processes": true }, + "soma": { "namespaces": {"mount":false,"pid":false,"net":false,"uts":false,"ipc":false,"user":false,"cgroup":false}, + "rlimits": {"mem_bytes":null,"nproc":null,"nofile":null}, + "cgroup": {"path":"ente.slice/net","cpu_weight":null,"io_weight":null}, + "cpu_affinity": null }, + "payload": { "Native": { "exec": "/usr/sbin/arje-net-up", "argv": [], "envp": [["PATH", "/usr/sbin:/usr/bin:/sbin:/bin"]] } }, + "supervision": { "Restart": { "initial": 500, "max": 30000 } }, + "lifecycle": "daemon", "priority": "critical", + "flow": { "input": [], "output": [] }, "genesis": [] + }, + { + "schema_version": 1, + "id": "01J8YVKZQ0M0M0M0M0M0M0M0S0", + "lineage": null, + "label": "sshd", + "provides": [], "requires": [], + "permissions": { "networking": "full", "filesystem": "read-write", "ipc": { "allow": [] }, "processes": true }, + "soma": { "namespaces": {"mount":false,"pid":false,"net":false,"uts":false,"ipc":false,"user":false,"cgroup":false}, + "rlimits": {"mem_bytes":null,"nproc":null,"nofile":null}, + "cgroup": {"path":"ente.slice/sshd","cpu_weight":null,"io_weight":null}, + "cpu_affinity": null }, + "payload": { "Native": { "exec": "/usr/sbin/sshd", "argv": ["-D", "-e"], "envp": [["PATH", "/usr/sbin:/usr/bin:/sbin:/bin"]] } }, + "supervision": { "Restart": { "initial": 1000, "max": 60000 } }, + "lifecycle": "daemon", "priority": "high", + "flow": { "input": [], "output": [] }, "genesis": [] + }, { "schema_version": 1, "id": "01J8YVKZQ0M0M0M0M0M0M0M0G0",