feat(arje): reemplaza systemd en máquina real con coexistencia GRUB
Flujo seguro de adopción: arje se instala como entrada GRUB
alternativa, no toca systemd ni /sbin/init. Booteás arje cuando
querés, volvés a systemd si rompe (rollback instantáneo desde el
menú).
Artefactos nuevos:
- scripts/install-arje-as-init.sh: instala binarios musl-static a
/usr/sbin/ y /usr/bin/, copia seed a /ente/seed.card.json, agrega
menuentry "arje" a /etc/grub.d/40_custom usando init=/sbin/ente-zero
con kernel + initrd nativos. NO cambia GRUB_DEFAULT. Idempotente
(regenera el bloque ARJE-MENUENTRY si existe).
- scripts/uninstall-arje.sh: revierte binarios + menuentry. Conserva
/ente/seed.card.json por si la editaste.
- seeds/arje-host.card.json: seed para máquina real con 15 cards:
tmpfiles + mount-fstab + swap-on + dbus-system + 11 compat shims +
dhcpcd + sshd + agetty. Validada.
- docs/arje-replace-systemd.md: filosofía vs systemd ("no acapara
porque no genera, sólo arranca lo declarado"), lista exhaustiva de
servicios systemd que NO deben migrarse (ModemManager, snapd, cups,
unattended-upgrades, etc.), tabla diferencial de UX vs systemd
(systemctl restart → kill PID, systemctl enable → editar seed),
checklist pre-primer-boot, instrucciones de rollback y cómo hacer
arje default sólo cuando estés seguro.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
# Reemplazar systemd con arje en una máquina real
|
||||
|
||||
> **Importante**: este flujo deja **systemd intacto** y agrega arje como
|
||||
> entrada GRUB alternativa. No es "destruir y reemplazar"; es "convivir
|
||||
> hasta confiar". Booteás arje cuando querés, volvés a systemd si rompe.
|
||||
|
||||
## 1. Estrategia
|
||||
|
||||
| componente | qué hacemos |
|
||||
| --------------------- | -------------------------------------------------------- |
|
||||
| `/sbin/init` | NO se toca (sigue siendo systemd). |
|
||||
| `/lib/systemd/*` | NO se toca. |
|
||||
| `kernel + initramfs` | reusamos los del host (firmware, módulos, root FS). |
|
||||
| `init=` en GRUB | nueva entrada apunta a `/sbin/ente-zero`. |
|
||||
| `GRUB_DEFAULT` | NO se cambia. Sigue arrancando systemd por default. |
|
||||
| `/ente/seed.card.json`| nueva — define qué arranca arje. |
|
||||
| `/usr/sbin/ente-*` | binarios musl-static del fractal. |
|
||||
|
||||
Booteo del kernel → initramfs nativo hace su trabajo (mountea root,
|
||||
carga módulos) → cuando llega el `switch_root`, en lugar de exec
|
||||
`/lib/systemd/systemd`, exec `/sbin/ente-zero`. Esto deja firmware y
|
||||
udev fuera del scope de arje (todavía).
|
||||
|
||||
## 2. Instalación
|
||||
|
||||
```bash
|
||||
# 1. (opcional) revisá la seed default que se va a copiar a /ente/
|
||||
$EDITOR seeds/arje-host.card.json
|
||||
|
||||
# 2. instalar
|
||||
sudo scripts/install-arje-as-init.sh
|
||||
|
||||
# 3. (opcional) bootear arje SÓLO en el próximo reboot (no cambia default)
|
||||
sudo grub-reboot "arje (init=/sbin/ente-zero) — kernel $(uname -r)"
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
Si algo rompe en arje: reset/poweroff → en el menú GRUB elegir la
|
||||
entrada default (systemd) → volvés a un sistema funcional. `arje` no
|
||||
toca configuración de systemd, así que el rollback es instantáneo.
|
||||
|
||||
Para **desinstalar**:
|
||||
|
||||
```bash
|
||||
sudo scripts/uninstall-arje.sh
|
||||
```
|
||||
|
||||
## 3. Filosofía vs systemd — y por qué arje no acapara
|
||||
|
||||
systemd arranca, por default, **todo lo que tiene un `.service` con
|
||||
`WantedBy=multi-user.target`**, recursivamente vía dependencias. Eso es
|
||||
opaco y crece con cada paquete instalado.
|
||||
|
||||
arje no tiene generadores, ni `WantedBy`, ni `Wants`, ni target trees.
|
||||
**Arranca exactamente lo declarado en `genesis: [...]` de la
|
||||
`seed.card.json`**, en el orden declarativo, con la `supervision` que
|
||||
declarás vos. Si no lo declaraste, no corre. Punto.
|
||||
|
||||
### 3a. Servicios que systemd arranca y arje NO debería migrar
|
||||
|
||||
Estos son los sospechosos típicos en Debian/Ubuntu/Arch. **No agregues
|
||||
ninguno a tu seed** salvo que sepas que lo usás:
|
||||
|
||||
| systemd unit | por qué saltearlo |
|
||||
| ------------------------------------ | ---------------------------------------- |
|
||||
| `ModemManager.service` | no tenés módem 3G/4G. |
|
||||
| `bluetooth.service` | si no usás bluetooth. |
|
||||
| `cups.service`, `cups-browsed` | si no imprimís. |
|
||||
| `avahi-daemon.service` | mDNS local. Ruido si no lo necesitás. |
|
||||
| `snapd.service` | si no usás snaps. |
|
||||
| `apt-daily.service`, `apt-daily-upgrade` | autoupdates — no son init. |
|
||||
| `unattended-upgrades.service` | corre tras boot, no init. |
|
||||
| `accounts-daemon.service` | UI helpers GNOME; no init. |
|
||||
| `colord.service` | calibración de color. No init. |
|
||||
| `geoclue.service` | localización. No init. |
|
||||
| `gdm.service`, `lightdm.service` | DM gráfico — agregalo SÓLO si querés GUI.|
|
||||
| `NetworkManager-wait-online.service` | espera red. arje no necesita "esperar". |
|
||||
| `systemd-timesyncd.service` | reemplaza con cron-like + ntpd one-shot. |
|
||||
| `systemd-machined.service` | reemplazado por `ente-machined-compat`. |
|
||||
| `systemd-logind.service` | reemplazado por `ente-logind-compat`. |
|
||||
| `systemd-resolved.service` | reemplazado por `ente-resolved-compat`. |
|
||||
| `systemd-hostnamed.service` | reemplazado por `ente-hostnamed-compat`. |
|
||||
| `systemd-timedated.service` | reemplazado por `ente-timedated-compat`. |
|
||||
| `systemd-localed.service` | reemplazado por `ente-localed-compat`. |
|
||||
| `systemd-journald.service` | reemplazado por `ente-journald-compat`. |
|
||||
| `systemd-tmpfiles-*.service` | reemplazado por `ente-tmpfiles-compat`. |
|
||||
| `systemd-binfmt.service` | reemplazado por `ente-binfmt-compat`. |
|
||||
| `polkitd.service` | reemplazado por `ente-polkit-compat`. |
|
||||
|
||||
Las últimas 12 ya están como Cards en `seeds/arje-host.card.json`. Las
|
||||
de la mitad de arriba **no** — no las agregues.
|
||||
|
||||
### 3b. Servicios que SÍ necesitás declarar (y que ya están en `arje-host.card.json`)
|
||||
|
||||
| Card label | reemplaza | binario |
|
||||
| ------------------ | -------------------------- | -------------------------------------------- |
|
||||
| `tmpfiles-boot` | `systemd-tmpfiles-setup` | `/usr/sbin/ente-tmpfiles-compat --boot` |
|
||||
| `mount-fstab` | `local-fs.target` | `/bin/mount -a` (one-shot) |
|
||||
| `swap-on` | `swap.target` | `/sbin/swapon -a` (one-shot) |
|
||||
| `dbus-system` | `dbus.service` | `/usr/bin/dbus-daemon --system --nofork` |
|
||||
| `compat-*` (×11) | shims D-Bus de systemd | `/usr/sbin/ente-*-compat` |
|
||||
| `network-dhcpcd` | `NetworkManager` / `networkd` | `/usr/sbin/dhcpcd -B` |
|
||||
| `sshd` | `ssh.service` | `/usr/sbin/sshd -D` |
|
||||
| `getty-tty1` | `getty@tty1.service` | `/sbin/agetty --noclear tty1 linux` |
|
||||
|
||||
15 entes. Compará: una instalación Debian fresh con GNOME desktop tiene
|
||||
**>180 unidades activas** tras `systemctl list-units --state=running`.
|
||||
|
||||
### 3c. Cómo agregar un servicio que falta
|
||||
|
||||
1. Encontrá el binario y los argumentos. Mirá el `.service` original:
|
||||
```
|
||||
systemctl cat <unit>
|
||||
```
|
||||
Mirá `ExecStart=` y reproducí.
|
||||
|
||||
2. Agregá una Card al `genesis` de `/ente/seed.card.json`:
|
||||
```json
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "<ULID nuevo, Crockford base32, no I L O U>",
|
||||
"label": "mi-servicio",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "outbound", "filesystem": "read-write", "ipc": { "allow": [] }, "processes": true },
|
||||
"soma": { ... idéntico al patrón de los otros ... },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/mi-bin", "argv": ["--foreground"], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 500, "max": 30000 } },
|
||||
"lifecycle": "daemon",
|
||||
"priority": "normal",
|
||||
"flow": { "input": [], "output": [] },
|
||||
"genesis": []
|
||||
}
|
||||
```
|
||||
**Importante**: `argv` tiene que tener el equivalente a `--foreground` o
|
||||
`-D` o `--no-fork`. Si el binario se daemoniza solo (fork+exit), arje
|
||||
no lo puede supervisar y caerá en loop de restart.
|
||||
|
||||
3. Validar:
|
||||
```bash
|
||||
seeds/validate.sh /ente/seed.card.json
|
||||
```
|
||||
|
||||
4. Reboot a arje. Verificar:
|
||||
```sh
|
||||
arje# brahman-status
|
||||
```
|
||||
|
||||
## 4. Diferencias de UX con systemd
|
||||
|
||||
| acción | systemd | arje |
|
||||
| ---------------------------- | ------------------------------------ | ------------------------------------------------------- |
|
||||
| Ver servicios activos | `systemctl list-units --state=running` | `brahman-status` + `busctl list-entes` |
|
||||
| Ver logs | `journalctl -u foo` | `ente-journalctl` (TODO en CLI; por ahora `dmesg`) |
|
||||
| Restart un servicio | `systemctl restart foo` | matar el PID (`brain` lo reanuda por `Supervision`) |
|
||||
| Habilitar/Deshabilitar | `systemctl enable/disable` | editar `/ente/seed.card.json` + reboot |
|
||||
| Ver dependencias | `systemctl list-dependencies foo` | `brahman-status` muestra references y flow matches |
|
||||
| Detectar fallas reincidentes | `systemctl status foo` → "failed" | `brainctl crystals` muestra patrones `EnteDied → …` |
|
||||
| socket activation | `.socket` unit | (no implementado todavía; ver flow + broker matching) |
|
||||
| user services | `--user` | (no implementado; arje es system-wide por ahora) |
|
||||
|
||||
## 5. Cosas que arje todavía NO hace que sí hace systemd
|
||||
|
||||
- **udev / hotplug**: arje captura uevents (vía `spawn_uevent_stream`),
|
||||
pero no hay reglas declarativas todavía. Para boot inicial, el
|
||||
initramfs nativo ya hizo el cold-plug, así que no es bloqueante.
|
||||
- **Timers** (cron-like): `ente-timer-compat` existe pero no está en la
|
||||
seed host por default. Agregalo si querés `*.timer` units migradas.
|
||||
- **Service generators**: no hay equivalente a `systemd-fstab-generator`
|
||||
ni `systemd-getty-generator`. Tu seed los declara explícitamente.
|
||||
- **Socket activation**: parcialmente — el broker matchea flow
|
||||
consumer↔producer, pero no hay aún listen-on-fd-handoff como
|
||||
`sd_listen_fds()`.
|
||||
- **User instances**: no hay todavía `arje --user`. Los procesos de
|
||||
usuario los lanza un getty/login estándar.
|
||||
|
||||
## 6. Checklist pre-primer-boot
|
||||
|
||||
- [ ] `seeds/arje-host.card.json` ajustada a tu hardware/red/users.
|
||||
- [ ] `seeds/validate.sh` → OK.
|
||||
- [ ] `/usr/bin/dbus-daemon` existe (de lo contrario los shims no se
|
||||
anuncian — `apt install dbus`).
|
||||
- [ ] `/usr/sbin/dhcpcd` o tu network stack preferido está instalado.
|
||||
- [ ] `/usr/sbin/sshd` instalado y `/etc/ssh/sshd_config` ok si querés
|
||||
poder entrar remoto si la consola falla.
|
||||
- [ ] `/sbin/agetty` instalado (`util-linux`) para tty1.
|
||||
- [ ] `sudo scripts/install-arje-as-init.sh` ejecutado.
|
||||
- [ ] `grub-reboot` apuntado a la entrada arje **sólo para el próximo
|
||||
boot** — no `grub-set-default`.
|
||||
- [ ] Listo para revertir vía menú GRUB si algo falla.
|
||||
|
||||
## 7. Cuando arje sea estable: hacerlo default
|
||||
|
||||
Cuando ya hayas booteado arje N veces sin problemas y querés que sea
|
||||
default:
|
||||
|
||||
```bash
|
||||
# Listar entradas
|
||||
sudo grep -E "^\s*menuentry " /boot/grub/grub.cfg | nl
|
||||
|
||||
# Ponerlo como default (usa el índice del menú o el title exacto)
|
||||
sudo grub-set-default "arje (init=/sbin/ente-zero) — kernel $(uname -r)"
|
||||
```
|
||||
|
||||
Mantené la entrada systemd como rescue. Si querés acortar la lista de
|
||||
units que systemd arrancaría si bootea de nuevo: `systemctl disable
|
||||
ModemManager bluetooth cups …` — los nombres de §3a son una guía.
|
||||
|
||||
## Apéndice — depurar el primer boot fallido
|
||||
|
||||
Si arje no levanta el primer boot:
|
||||
|
||||
1. Volver a GRUB → entrada systemd → bootea normal.
|
||||
2. `journalctl --boot=-1` (logs del intento previo).
|
||||
3. Buscar `ente-zero` o `Tarjeta Semilla`. Si nada → el ejecutable no
|
||||
se lanzó (kernel panic temprano, falta `init=` correcto, etc.).
|
||||
4. Si arrancó pero falló alguna Card: la próxima vez, antes de reboot:
|
||||
```bash
|
||||
sudo sed -i 's/console=tty1/console=tty1 ente.log=trace/' /etc/grub.d/40_custom
|
||||
sudo update-grub
|
||||
```
|
||||
y revisá `dmesg` desde systemd tras el reintento.
|
||||
Executable
+178
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env bash
|
||||
# install-arje-as-init.sh — instala arje como init alternativo en una
|
||||
# máquina real con systemd ya instalado, en coexistencia.
|
||||
#
|
||||
# ESTRATEGIA: arje NO reemplaza al systemd default. Se instala en
|
||||
# paralelo con su propia entrada GRUB. Booteás arje cuando querés,
|
||||
# volvés a systemd si algo no anda.
|
||||
#
|
||||
# QUÉ HACE:
|
||||
# 1. Compila musl-static todos los binarios del fractal.
|
||||
# 2. Copia binarios a /usr/sbin/ (init/shims) y /usr/bin/ (CLIs admin)
|
||||
# del rootfs vivo.
|
||||
# 3. Copia la seed a /ente/seed.card.json (default: arje-host.card.json).
|
||||
# 4. Crea menuentry "arje" en /etc/grub.d/40_custom usando init=/sbin/ente-zero
|
||||
# (conserva initramfs nativo → firmware, módulos kernel, root FS,
|
||||
# siguen funcionando exactamente igual).
|
||||
# 5. Ejecuta update-grub o grub-mkconfig según distro.
|
||||
#
|
||||
# QUÉ NO HACE:
|
||||
# - Tocar /sbin/init, /usr/lib/systemd/* (systemd queda intacto y default).
|
||||
# - Cambiar GRUB_DEFAULT (seguís booteando systemd por default).
|
||||
# - Cargar arje ahora. Lo elegís manualmente en el próximo boot.
|
||||
# - Habilitar servicios systemd que arje no necesita (eso es responsabilidad
|
||||
# tuya, ver docs/arje-replace-systemd.md §4).
|
||||
#
|
||||
# REVERTIR: sudo scripts/uninstall-arje.sh
|
||||
#
|
||||
# Uso:
|
||||
# sudo scripts/install-arje-as-init.sh [seed.card.json]
|
||||
#
|
||||
# seed default: seeds/arje-host.card.json
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SEED="${1:-seeds/arje-host.card.json}"
|
||||
TARGET="${ARJE_TARGET:-x86_64-unknown-linux-musl}"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$REPO_DIR"
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "[install-arje] hace falta root (modifica /usr/sbin, /etc/grub.d, /ente)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$SEED" ]; then
|
||||
echo "[install-arje] seed no encontrada: $SEED" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Verificar que el systemd default sigue siendo el init — querés saber
|
||||
# de qué te volvés capaz de regresar.
|
||||
if [ ! -e /sbin/init ] && [ ! -e /lib/systemd/systemd ] && [ ! -e /usr/lib/systemd/systemd ]; then
|
||||
echo "[install-arje] WARN: no detecto systemd en esta máquina." >&2
|
||||
echo " Si esta máquina ya corre arje, este script no es lo que querés." >&2
|
||||
echo " Continuá sólo si sabés lo que hacés." >&2
|
||||
read -r -p " ¿continuar? [y/N] " ans
|
||||
[ "$ans" = "y" ] || exit 3
|
||||
fi
|
||||
|
||||
echo "[install-arje] paso 1/5: compilar binarios musl-static"
|
||||
"$SCRIPT_DIR/build-arje-initrd.sh" "$SEED" /tmp/arje-noop.cpio.gz >/dev/null
|
||||
rm -f /tmp/arje-noop.cpio.gz
|
||||
BIN_DIR="$REPO_DIR/target/$TARGET/release"
|
||||
EX_DIR="$BIN_DIR/examples"
|
||||
|
||||
echo "[install-arje] paso 2/5: instalar binarios en /usr/sbin/ y /usr/bin/"
|
||||
install -m 0755 "$BIN_DIR/ente-zero" /usr/sbin/ente-zero
|
||||
for b in ente-echo ente-policy-provider \
|
||||
ente-logind-compat ente-hostnamed-compat ente-timedated-compat \
|
||||
ente-localed-compat ente-journald-compat ente-resolved-compat \
|
||||
ente-polkit-compat ente-machined-compat ente-systemd1-compat \
|
||||
ente-notify-compat ente-timer-compat ente-tmpfiles-compat \
|
||||
ente-binfmt-compat; do
|
||||
install -m 0755 "$BIN_DIR/$b" "/usr/sbin/$b"
|
||||
done
|
||||
for e in brahman-status busctl brainctl; do
|
||||
install -m 0755 "$EX_DIR/$e" "/usr/bin/$e"
|
||||
done
|
||||
|
||||
echo "[install-arje] paso 3/5: instalar seed en /ente/seed.card.json"
|
||||
mkdir -p /ente
|
||||
# Backup del seed previo (si lo hay) — nunca sobrescribimos sin guardar.
|
||||
if [ -f /ente/seed.card.json ]; then
|
||||
cp /ente/seed.card.json "/ente/seed.card.json.bak-$(date +%s)"
|
||||
fi
|
||||
install -m 0644 "$SEED" /ente/seed.card.json
|
||||
|
||||
echo "[install-arje] paso 4/5: detectar kernel para menuentry GRUB"
|
||||
# Reusamos el kernel del host (mismo vmlinuz que usa systemd). Detectamos
|
||||
# el current; si tenés varios, se elige el del uname.
|
||||
KVER="$(uname -r)"
|
||||
VMLINUZ=""
|
||||
INITRD=""
|
||||
for cand in "/boot/vmlinuz-$KVER" "/boot/vmlinuz" /boot/vmlinuz-*; do
|
||||
if [ -f "$cand" ]; then VMLINUZ="$cand"; break; fi
|
||||
done
|
||||
for cand in "/boot/initrd.img-$KVER" "/boot/initramfs-$KVER.img" \
|
||||
"/boot/initrd.img" /boot/initrd.img-* /boot/initramfs-*.img; do
|
||||
if [ -f "$cand" ]; then INITRD="$cand"; break; fi
|
||||
done
|
||||
|
||||
if [ -z "$VMLINUZ" ] || [ -z "$INITRD" ]; then
|
||||
echo "[install-arje] ERROR: no encontré vmlinuz o initrd nativo en /boot." >&2
|
||||
echo " Sin esos no se puede armar la entrada GRUB." >&2
|
||||
exit 4
|
||||
fi
|
||||
echo " kernel: $VMLINUZ"
|
||||
echo " initrd: $INITRD"
|
||||
|
||||
# El root device — leemos /proc/cmdline para reusarlo exactamente como
|
||||
# está en la entrada systemd actual.
|
||||
ROOT_OPT="$(awk -v RS=' ' '/^root=/' /proc/cmdline | tr -d '\n')"
|
||||
if [ -z "$ROOT_OPT" ]; then
|
||||
echo "[install-arje] WARN: no extraje root= de /proc/cmdline." >&2
|
||||
echo " Configurá manualmente la entrada GRUB con tu root device." >&2
|
||||
ROOT_OPT="root=/dev/sda1 # AJUSTAR"
|
||||
fi
|
||||
|
||||
echo "[install-arje] paso 5/5: agregar menuentry GRUB"
|
||||
CUSTOM=/etc/grub.d/40_custom
|
||||
# Si ya existe nuestro menuentry, lo reemplazamos (idempotente).
|
||||
if grep -q "BEGIN ARJE-MENUENTRY" "$CUSTOM"; then
|
||||
# Borrar el bloque previo.
|
||||
awk '/BEGIN ARJE-MENUENTRY/{f=1} /END ARJE-MENUENTRY/{f=0; next} !f' "$CUSTOM" \
|
||||
> "$CUSTOM.tmp" && mv "$CUSTOM.tmp" "$CUSTOM"
|
||||
fi
|
||||
|
||||
cat >> "$CUSTOM" <<EOF
|
||||
# BEGIN ARJE-MENUENTRY (generated by install-arje-as-init.sh)
|
||||
menuentry "arje (init=/sbin/ente-zero) — kernel $KVER" {
|
||||
insmod gzio
|
||||
insmod part_msdos
|
||||
insmod ext2
|
||||
linux $VMLINUZ $ROOT_OPT ro init=/sbin/ente-zero console=tty1 console=ttyS0,115200 panic=10
|
||||
initrd $INITRD
|
||||
}
|
||||
# END ARJE-MENUENTRY
|
||||
EOF
|
||||
chmod 0755 "$CUSTOM"
|
||||
|
||||
# Regenerar grub.cfg.
|
||||
if command -v update-grub >/dev/null 2>&1; then
|
||||
echo " ejecutando update-grub"
|
||||
update-grub
|
||||
elif command -v grub-mkconfig >/dev/null 2>&1; then
|
||||
echo " ejecutando grub-mkconfig"
|
||||
grub-mkconfig -o /boot/grub/grub.cfg
|
||||
else
|
||||
echo "[install-arje] WARN: no encontré update-grub ni grub-mkconfig." >&2
|
||||
echo " Regenerá grub.cfg manualmente." >&2
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
[install-arje] HECHO.
|
||||
|
||||
systemd sigue siendo tu init default — esta máquina arranca systemd
|
||||
salvo que elijas explícitamente "arje" en GRUB.
|
||||
|
||||
- binarios: /usr/sbin/ente-* y /usr/bin/{brahman-status,busctl,brainctl}
|
||||
- seed activa: /ente/seed.card.json (origen: $SEED)
|
||||
- menuentry: /etc/grub.d/40_custom (regenerá grub.cfg si lo editás)
|
||||
|
||||
Para arrancar arje al próximo boot UNA SOLA VEZ (sin cambiar default):
|
||||
|
||||
sudo grub-reboot "arje (init=/sbin/ente-zero) — kernel $KVER"
|
||||
sudo reboot
|
||||
|
||||
Para revertir (quita binarios + menuentry):
|
||||
|
||||
sudo scripts/uninstall-arje.sh
|
||||
|
||||
Antes del primer boot real, leé docs/arje-replace-systemd.md §3
|
||||
("Servicios systemd que arje NO arranca") para que NO te quedes sin
|
||||
red, sin sshd o sin filesystems montados.
|
||||
EOF
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# uninstall-arje.sh — revierte lo que install-arje-as-init.sh hizo.
|
||||
#
|
||||
# - Borra /usr/sbin/ente-* y /usr/bin/{brahman-status,busctl,brainctl}.
|
||||
# - Borra el bloque ARJE-MENUENTRY de /etc/grub.d/40_custom.
|
||||
# - Regenera grub.cfg.
|
||||
# - NO toca /ente/seed.card.json (querés conservar customización).
|
||||
# - NO toca /sbin/init ni systemd.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "[uninstall-arje] hace falta root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[uninstall-arje] removiendo binarios"
|
||||
rm -f /usr/sbin/ente-zero
|
||||
for b in ente-echo ente-policy-provider \
|
||||
ente-logind-compat ente-hostnamed-compat ente-timedated-compat \
|
||||
ente-localed-compat ente-journald-compat ente-resolved-compat \
|
||||
ente-polkit-compat ente-machined-compat ente-systemd1-compat \
|
||||
ente-notify-compat ente-timer-compat ente-tmpfiles-compat \
|
||||
ente-binfmt-compat; do
|
||||
rm -f "/usr/sbin/$b"
|
||||
done
|
||||
for e in brahman-status busctl brainctl; do
|
||||
rm -f "/usr/bin/$e"
|
||||
done
|
||||
|
||||
echo "[uninstall-arje] limpiando menuentry de /etc/grub.d/40_custom"
|
||||
CUSTOM=/etc/grub.d/40_custom
|
||||
if [ -f "$CUSTOM" ] && grep -q "BEGIN ARJE-MENUENTRY" "$CUSTOM"; then
|
||||
awk '/BEGIN ARJE-MENUENTRY/{f=1} /END ARJE-MENUENTRY/{f=0; next} !f' "$CUSTOM" \
|
||||
> "$CUSTOM.tmp" && mv "$CUSTOM.tmp" "$CUSTOM"
|
||||
chmod 0755 "$CUSTOM"
|
||||
fi
|
||||
|
||||
if command -v update-grub >/dev/null 2>&1; then
|
||||
update-grub
|
||||
elif command -v grub-mkconfig >/dev/null 2>&1; then
|
||||
grub-mkconfig -o /boot/grub/grub.cfg
|
||||
fi
|
||||
|
||||
echo "[uninstall-arje] hecho. /ente/seed.card.json conservado (borralo a mano si querés)."
|
||||
@@ -0,0 +1,249 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0M0",
|
||||
"lineage": null,
|
||||
"label": "arje.seed.host",
|
||||
"provides": ["Spawn", "Journal"],
|
||||
"requires": [],
|
||||
"permissions": {
|
||||
"networking": "full",
|
||||
"filesystem": "read-write",
|
||||
"ipc": { "allow": ["wit-v1", "dbus-v1"] },
|
||||
"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/zero", "cpu_weight": null, "io_weight": null },
|
||||
"cpu_affinity": null
|
||||
},
|
||||
"payload": "Virtual",
|
||||
"supervision": "OneShot",
|
||||
"lifecycle": "daemon",
|
||||
"priority": "critical",
|
||||
"flow": { "input": [], "output": [] },
|
||||
"genesis": [
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0T1",
|
||||
"label": "tmpfiles-boot",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "none", "filesystem": "read-write", "ipc": { "allow": [] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-tmpfiles-compat", "argv": ["--boot"], "envp": [] } },
|
||||
"supervision": "OneShot", "lifecycle": "oneshot", "priority": "critical",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0F1",
|
||||
"label": "mount-fstab",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "none", "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/boot","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/bin/mount", "argv": ["-a"], "envp": [] } },
|
||||
"supervision": "OneShot", "lifecycle": "oneshot", "priority": "critical",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0S1",
|
||||
"label": "swap-on",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "none", "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/boot","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/sbin/swapon", "argv": ["-a"], "envp": [] } },
|
||||
"supervision": "OneShot", "lifecycle": "oneshot", "priority": "normal",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0DB",
|
||||
"label": "dbus-system",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "loopback", "filesystem": "read-write", "ipc": { "allow": ["dbus-v1"] }, "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/bus","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/bin/dbus-daemon", "argv": ["--system", "--nofork"], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 200, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "critical",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0H1",
|
||||
"label": "compat-hostnamed",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "loopback", "filesystem": "read-only", "ipc": { "allow": ["dbus-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-hostnamed-compat", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "normal",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0T2",
|
||||
"label": "compat-timedated",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "loopback", "filesystem": "read-only", "ipc": { "allow": ["dbus-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-timedated-compat", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "normal",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0J1",
|
||||
"label": "compat-journald",
|
||||
"provides": ["Journal"], "requires": [],
|
||||
"permissions": { "networking": "none", "filesystem": "read-write", "ipc": { "allow": ["dbus-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-journald-compat", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "high",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0Y1",
|
||||
"label": "compat-logind",
|
||||
"provides": ["LegacyLogind"], "requires": [],
|
||||
"permissions": { "networking": "loopback", "filesystem": "read-write", "ipc": { "allow": ["dbus-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-logind-compat", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "high",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0R1",
|
||||
"label": "compat-resolved",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "outbound", "filesystem": "read-write", "ipc": { "allow": ["dbus-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-resolved-compat", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "normal",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0P1",
|
||||
"label": "compat-polkit",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "loopback", "filesystem": "read-only", "ipc": { "allow": ["dbus-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-polkit-compat", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "normal",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0PP",
|
||||
"label": "policy-provider",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "none", "filesystem": "read-only", "ipc": { "allow": ["wit-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-policy-provider", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "normal",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0SY",
|
||||
"label": "compat-systemd1",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "loopback", "filesystem": "read-write", "ipc": { "allow": ["dbus-v1"] }, "processes": false },
|
||||
"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/compat","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/ente-systemd1-compat", "argv": [], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "high",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0NW",
|
||||
"label": "network-dhcpcd",
|
||||
"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/dhcpcd", "argv": ["-B"], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 500, "max": 60000 } },
|
||||
"lifecycle": "daemon", "priority": "high",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0SS",
|
||||
"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/ssh","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/usr/sbin/sshd", "argv": ["-D"], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 200, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "high",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
},
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "01J8YVKZH0M0M0M0M0M0M0M0G1",
|
||||
"label": "getty-tty1",
|
||||
"provides": [], "requires": [],
|
||||
"permissions": { "networking": "none", "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/getty","cpu_weight":null,"io_weight":null},
|
||||
"cpu_affinity": null },
|
||||
"payload": { "Native": { "exec": "/sbin/agetty", "argv": ["--noclear", "tty1", "linux"], "envp": [] } },
|
||||
"supervision": { "Restart": { "initial": 100, "max": 30000 } },
|
||||
"lifecycle": "daemon", "priority": "high",
|
||||
"flow": { "input": [], "output": [] }, "genesis": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user