netup: levantar el LOOPBACK — nadie lo hacía, y el síntoma era un timeout de 30 s

En un sistema con systemd u OpenRC el init levanta `lo`. Con arje-zero no lo hacía **nadie**.

Medido en la caja de producción el 2026-09-10:

    ip -o link show lo   =>  lo: <LOOPBACK> DOWN      (y CERO direcciones)
    caddy escuchando en 0.0.0.0:80
    curl http://127.0.0.1/index.json  =>  timeout de 30 s

No «connection refused», que se diagnostica en un minuto: un CUELGUE, que parece del servidor. Se
descubrió intentando que la caja instalara un paquete de su propio repo — o sea que el primer
servicio que habló con 127.0.0.1 fue también el primero en chocarse.

Cualquier cosa que use loopback fallaba igual: un backend detrás de un proxy, un socket TCP entre
demonios, un repo local. Va en `netup` porque es quien configura la red, y no es fatal: si ya estaba
levantado los errores son EEXIST y no deben tumbar el arranque.

Probado en un netns, en los dos estados: antes `lo: <LOOPBACK>` con 0 direcciones; después
`lo: <LOOPBACK,UP,LOWER_UP>` con `inet 127.0.0.1/8 scope host`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
This commit is contained in:
Sergio
2026-09-10 21:33:46 +00:00
co-authored by Claude Opus 5
parent 9bc518899e
commit 36be67fa9c
+21
View File
@@ -32,6 +32,27 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
println!("netup: interfaz {iface} (index {ifindex}, mac {})", fmt_mac(mac));
let mut nl = netlink::Netlink::open()?;
// ── EL LOOPBACK, PRIMERO. Nadie más lo levanta. ──────────────────────────────────────────
// En un sistema con systemd/OpenRC esto lo hace el init; con arje-zero no lo hacía NADIE, y
// `lo` quedaba `DOWN` y sin dirección. Medido el 2026-09-10 en la caja de producción: caddy
// escuchando en `0.0.0.0:80` y `curl http://127.0.0.1/` **con TIMEOUT de 30 s** — no
// "connection refused", que se diagnostica en un minuto, sino un cuelgue que parece del
// servidor. Cualquier servicio que hable con 127.0.0.1 (un repo local, un backend detrás de un
// proxy, un socket TCP entre demonios) fallaba igual.
//
// Va acá porque `netup` es el que configura la red, y no es fatal: si ya estaba levantado, los
// errores son EEXIST y no deben tumbar el arranque.
if let Ok(lo) = read_sysfs_int("lo", "ifindex") {
let lo = lo as i32;
if let Err(e) = nl.link_up(lo) {
eprintln!("netup: aviso, no pude levantar lo: {e}");
}
if let Err(e) = nl.add_addr(lo, [127, 0, 0, 1], 8) {
eprintln!("netup: aviso, no pude direccionar lo: {e}");
}
}
nl.link_up(ifindex)?;
// Esperar el carrier (virtio/e1000 lo levantan en ms, pero damos margen).
wait_carrier(&iface, std::time::Duration::from_secs(5));