3339fb009c
El rename ente→arje dejó referencias stale al binario PID 1 y a los shims. Los nombres reales (verificados con cargo metadata) son todos arje-*: arje-zero, los 14 arje-*-compat, arje-echo, arje-policy-provider, arje-bus, arje-brain. - build-arje-initrd.sh, install-arje-as-init.sh, uninstall-arje.sh, run-arje-qemu.sh: `-p ente-*` → `-p arje-*`, paths /sbin/arje-zero y /usr/sbin/arje-*, RUST_LOG arje_zero=info. - seeds/arje-prod y arje-host: los exec `/usr/sbin/ente-*-compat` apuntaban a binarios que no existirían tras instalar — corregidos a `/usr/sbin/arje-*`. (validate.sh no chequea exec, por eso «validaban» igual; al boot real habrían fallado.) Intactos a propósito: `/ente/` (directorio canónico de la Semilla) y `ente.slice/*` (jerarquía cgroup). Las 3 seeds validan. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
238 lines
9.0 KiB
Bash
Executable File
238 lines
9.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# build-arje-initrd.sh — empaqueta arje-zero + shims compat + Tarjeta Semilla
|
|
# en un initramfs CPIO+gzip listo para arrancar bajo QEMU o como /init real.
|
|
#
|
|
# Toolchain: musl-static por default. arje-zero es PID 1; cualquier
|
|
# dependencia dinámica (libgcc_s, libc.so.6, ld-linux) que no esté en el
|
|
# initramfs produce kernel panic. Compilar contra musl elimina el problema
|
|
# completamente — un solo ELF estático.
|
|
#
|
|
# Layout del initrd resultante:
|
|
# /init → wrapper sh que exec /sbin/arje-zero
|
|
# /sbin/arje-zero → PID 1 (musl-static)
|
|
# /usr/sbin/arje-*-compat → shims systemd (musl-static)
|
|
# /usr/sbin/arje-echo, arje-policy-provider
|
|
# /ente/seed.card.json → Tarjeta Semilla
|
|
# /bin/{sh,ls,cat,...} → busybox-static (recomendado)
|
|
# /dev, /proc, /sys, /run → puntos de montaje (arje-zero los monta)
|
|
#
|
|
# Uso:
|
|
# scripts/build-arje-initrd.sh [seed.card.json] [out.cpio.gz]
|
|
#
|
|
# seed default: seeds/arje-prod.card.json
|
|
# out default: out/arje.initrd.cpio.gz
|
|
#
|
|
# Env:
|
|
# ARJE_TARGET triple de cargo (default: x86_64-unknown-linux-musl).
|
|
# Para glibc dinámica usar x86_64-unknown-linux-gnu — en
|
|
# ese caso hay que vendorear libgcc_s.so.1 + libc.so.6 +
|
|
# ld-linux-x86-64.so.2 manualmente o el kernel paniquea.
|
|
# BUSYBOX_BIN path a un busybox-static. Default: busca `busybox` en PATH.
|
|
# EXTRA_BINS binarios extra a copiar (deben ser estáticos), space-separated.
|
|
#
|
|
# Requisitos del host:
|
|
# - rust toolchain con el target musl instalado:
|
|
# rustup target add x86_64-unknown-linux-musl
|
|
# - musl-gcc para algunos crates con build.rs C (sled, etc.):
|
|
# Debian/Ubuntu: apt install musl-tools
|
|
# Alpine: apk add musl-dev gcc
|
|
# Arch: pacman -S musl
|
|
# - cpio, gzip.
|
|
# - busybox-static (recomendado, opcional):
|
|
# Debian/Ubuntu: apt install busybox-static
|
|
# Alpine: (busybox viene built-in)
|
|
|
|
set -euo pipefail
|
|
|
|
SEED="${1:-seeds/arje-prod.card.json}"
|
|
OUT="${2:-out/arje.initrd.cpio.gz}"
|
|
TARGET="${ARJE_TARGET:-x86_64-unknown-linux-musl}"
|
|
BUSYBOX_BIN="${BUSYBOX_BIN:-$(command -v busybox 2>/dev/null || true)}"
|
|
EXTRA_BINS="${EXTRA_BINS:-}"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
cd "$REPO_DIR"
|
|
|
|
if [ ! -f "$SEED" ]; then
|
|
echo "[build-initrd] seed no encontrada: $SEED" >&2
|
|
exit 2
|
|
fi
|
|
|
|
# Chequeo del target: si es musl, debe estar instalado. Mensaje accionable
|
|
# cuando falta — la causa #1 de fracaso al primer intento.
|
|
if [[ "$TARGET" == *-musl ]]; then
|
|
RUSTLIB="$(rustc --print sysroot 2>/dev/null)/lib/rustlib/$TARGET"
|
|
if [ ! -d "$RUSTLIB" ]; then
|
|
cat >&2 <<EOF
|
|
[build-initrd] target musl no instalado: $TARGET
|
|
|
|
Instalalo con uno de:
|
|
|
|
# Si tenés rustup:
|
|
rustup target add $TARGET
|
|
|
|
# Si tu rust viene del paquete del sistema (Debian/Ubuntu):
|
|
apt install rustup && rustup default stable && rustup target add $TARGET
|
|
|
|
Y asegurate de tener musl-gcc para los crates con build.rs C:
|
|
|
|
apt install musl-tools # Debian/Ubuntu
|
|
apk add musl-dev gcc # Alpine
|
|
pacman -S musl # Arch
|
|
|
|
Si querés saltar musl (NO recomendado para PID 1, te dará kernel panic
|
|
por libgcc_s.so.1 faltante a menos que la vendorees):
|
|
|
|
ARJE_TARGET=x86_64-unknown-linux-gnu scripts/build-arje-initrd.sh
|
|
EOF
|
|
exit 5
|
|
fi
|
|
fi
|
|
|
|
# 1. Build release de arje-zero y todos los compat shims con el target elegido.
|
|
echo "[build-initrd] cargo build --release --target $TARGET de arje-zero + shims"
|
|
cargo build --release --target "$TARGET" \
|
|
-p arje-zero \
|
|
-p arje-echo \
|
|
-p arje-logind-compat \
|
|
-p arje-hostnamed-compat \
|
|
-p arje-timedated-compat \
|
|
-p arje-localed-compat \
|
|
-p arje-journald-compat \
|
|
-p arje-resolved-compat \
|
|
-p arje-polkit-compat \
|
|
-p arje-machined-compat \
|
|
-p arje-systemd1-compat \
|
|
-p arje-notify-compat \
|
|
-p arje-timer-compat \
|
|
-p arje-tmpfiles-compat \
|
|
-p arje-binfmt-compat \
|
|
-p arje-policy-provider
|
|
|
|
# 1b. Build de las CLI de administración. Son `[[example]]` de sus crates
|
|
# respectivos — un solo binario cada una, sin estado propio.
|
|
echo "[build-initrd] cargo build --release --target $TARGET de CLIs admin"
|
|
cargo build --release --target "$TARGET" \
|
|
--example brahman-status -p brahman-admin \
|
|
--example busctl -p arje-bus \
|
|
--example brainctl -p arje-brain
|
|
|
|
BIN_DIR="target/$TARGET/release"
|
|
EX_DIR="target/$TARGET/release/examples"
|
|
|
|
# 2. Validar la seed. validate.sh corre el binario del host (release plain),
|
|
# sólo verifica el schema — independiente del target.
|
|
if ! seeds/validate.sh "$SEED" >/dev/null 2>&1; then
|
|
echo "[build-initrd] seed inválida: $SEED" >&2
|
|
exit 3
|
|
fi
|
|
|
|
# 3. Sanity check: si compilamos musl, los ELF deben ser ESTÁTICOS.
|
|
# Si quedó alguno con interpreter dinámico, el kernel paniquea.
|
|
if [[ "$TARGET" == *-musl ]] && command -v file >/dev/null 2>&1; then
|
|
bad=0
|
|
for b in "$BIN_DIR/arje-zero" "$BIN_DIR/arje-echo"; do
|
|
[ -f "$b" ] || continue
|
|
if file "$b" | grep -q "dynamically linked"; then
|
|
echo "[build-initrd] WARN: $b quedó DYNAMIC (esperábamos static):" >&2
|
|
file "$b" >&2
|
|
bad=$((bad + 1))
|
|
fi
|
|
done
|
|
if [ "$bad" -gt 0 ]; then
|
|
echo "[build-initrd] abortando — un binario PID-1 dinámico paniquea el kernel" >&2
|
|
exit 6
|
|
fi
|
|
fi
|
|
|
|
# 4. Stage root del initrd.
|
|
STAGE="$(mktemp -d -t arje-initrd.XXXXXX)"
|
|
trap 'rm -rf "$STAGE"' EXIT
|
|
mkdir -p "$STAGE"/{bin,sbin,usr/bin,usr/sbin,etc,ente,proc,sys,dev,run,tmp,sys/fs/cgroup}
|
|
|
|
# 5. Copiar binarios arje.
|
|
install -m 0755 "$BIN_DIR/arje-zero" "$STAGE/sbin/arje-zero"
|
|
for b in arje-echo arje-policy-provider \
|
|
arje-logind-compat arje-hostnamed-compat arje-timedated-compat \
|
|
arje-localed-compat arje-journald-compat arje-resolved-compat \
|
|
arje-polkit-compat arje-machined-compat arje-systemd1-compat \
|
|
arje-notify-compat arje-timer-compat arje-tmpfiles-compat \
|
|
arje-binfmt-compat; do
|
|
install -m 0755 "$BIN_DIR/$b" "$STAGE/usr/sbin/$b"
|
|
done
|
|
|
|
# 5b. CLIs de administración → /usr/bin (no /usr/sbin: no son services).
|
|
for e in brahman-status busctl brainctl; do
|
|
install -m 0755 "$EX_DIR/$e" "$STAGE/usr/bin/$e"
|
|
done
|
|
|
|
# 6. Userspace mínimo. Con binarios musl-static no necesitamos vendorear
|
|
# libc/ld-linux. Las dos rutas:
|
|
# (a) busybox-static apuntado por $BUSYBOX_BIN → 1 binario, todo simlink.
|
|
# (b) sin busybox → copiar /bin/sh + sus deps via ldd. Sólo seguro si el
|
|
# /bin/sh del host es estático (ej. dash en algunos distros NO lo es).
|
|
if [ -n "$BUSYBOX_BIN" ] && [ -x "$BUSYBOX_BIN" ]; then
|
|
echo "[build-initrd] usando busybox-static: $BUSYBOX_BIN"
|
|
# Validar que el busybox es realmente estático (causa frecuente de panic).
|
|
if command -v file >/dev/null 2>&1 && \
|
|
file "$BUSYBOX_BIN" | grep -q "dynamically linked"; then
|
|
echo "[build-initrd] ERROR: $BUSYBOX_BIN es dinámico — necesitás busybox-static" >&2
|
|
echo " apt install busybox-static # Debian/Ubuntu" >&2
|
|
exit 7
|
|
fi
|
|
install -m 0755 "$BUSYBOX_BIN" "$STAGE/bin/busybox"
|
|
( cd "$STAGE/bin" && for app in sh ls cat mount umount mkdir cp mv \
|
|
echo grep sed awk ps kill sleep insmod modprobe poweroff reboot \
|
|
sysctl dmesg ip ifconfig; do
|
|
ln -sf busybox "$app"
|
|
done )
|
|
else
|
|
echo "[build-initrd] WARN: sin busybox-static — vendoreando /bin/sh + libs via ldd"
|
|
echo " Esto es FRÁGIL. Instalá busybox-static y reintentá:"
|
|
echo " apt install busybox-static # Debian/Ubuntu"
|
|
copy_lib() {
|
|
local lib="$1"
|
|
[ -f "$lib" ] || return 0
|
|
local dest="$STAGE${lib}"
|
|
mkdir -p "$(dirname "$dest")"
|
|
cp -L "$lib" "$dest"
|
|
}
|
|
for b in /bin/sh /bin/ls /bin/cat /bin/mount /bin/umount /bin/mkdir; do
|
|
[ -x "$b" ] || continue
|
|
cp -L "$b" "$STAGE${b}"
|
|
while read -r lib; do copy_lib "$lib"; done < <(
|
|
ldd "$b" 2>/dev/null | awk '{ for (i=1;i<=NF;i++) if ($i ~ /^\//) print $i }'
|
|
)
|
|
done
|
|
fi
|
|
|
|
# 7. Tarjeta Semilla. Path canónico en prod: /ente/seed.card.json
|
|
install -m 0644 "$SEED" "$STAGE/ente/seed.card.json"
|
|
|
|
# 8. /init wrapper. El kernel pasa control a /init; nosotros invocamos
|
|
# arje-zero como PID 1 real con su env mínimo.
|
|
cat > "$STAGE/init" <<'EOF'
|
|
#!/bin/sh
|
|
# arje /init — kernel → este script → arje-zero (PID 1 lo hereda via exec)
|
|
export PATH=/usr/sbin:/usr/bin:/sbin:/bin
|
|
export RUST_LOG="${RUST_LOG:-arje_zero=info,brahman_handshake=info,info}"
|
|
# arje-zero monta /proc /sys /dev /sys/fs/cgroup él mismo.
|
|
exec /sbin/arje-zero
|
|
EOF
|
|
chmod 0755 "$STAGE/init"
|
|
|
|
# 9. Binarios extra a vendorear (deben ser estáticos).
|
|
if [ -n "$EXTRA_BINS" ]; then
|
|
for b in $EXTRA_BINS; do
|
|
[ -x "$b" ] || { echo "[build-initrd] EXTRA_BINS: $b no existe"; exit 4; }
|
|
install -m 0755 "$b" "$STAGE/usr/sbin/$(basename "$b")"
|
|
done
|
|
fi
|
|
|
|
# 10. Empaquetar CPIO + gzip. Formato newc (estándar para Linux initramfs).
|
|
mkdir -p "$(dirname "$OUT")"
|
|
( cd "$STAGE" && find . -print0 | cpio -o -H newc --null --quiet ) | gzip -9 > "$OUT"
|
|
echo "[build-initrd] generado: $OUT ($(du -h "$OUT" | cut -f1))"
|
|
echo "[build-initrd] target: $TARGET"
|