gioser

tawasuyu/brahman

Rust 459TOML 177Markdown 49JSON 176207 Sutichaykuna

⎇ 6588d0ed6c355a57194a34a488c1ff2b3d8eb6b3 docs/arje-replace-systemd.md Markdown · 221 siq'ikuna · 11.1 KB Ñawpa willay ch'uya

refactor(naming): A1 — ente→arje, vista→revista, pluma→fana b83d40a83 · sergio ·

1# Reemplazar systemd con arje en una máquina real
2
3> **Importante**: este flujo deja **systemd intacto** y agrega arje como
4> entrada GRUB alternativa. No es "destruir y reemplazar"; es "convivir
5> hasta confiar". Booteás arje cuando querés, volvés a systemd si rompe.
6
7## 1. Estrategia
8
9| componente            | qué hacemos                                              |
10| --------------------- | -------------------------------------------------------- |
11| `/sbin/init`          | NO se toca (sigue siendo systemd).                       |
12| `/lib/systemd/*`      | NO se toca.                                              |
13| `kernel + initramfs`  | reusamos los del host (firmware, módulos, root FS).      |
14| `init=` en GRUB       | nueva entrada apunta a `/sbin/arje-zero`.                |
15| `GRUB_DEFAULT`        | NO se cambia. Sigue arrancando systemd por default.      |
16| `/ente/seed.card.json`| nueva — define qué arranca arje.                         |
17| `/usr/sbin/arje-*`    | binarios musl-static del fractal.                        |
18
19Booteo del kernel → initramfs nativo hace su trabajo (mountea root,
20carga módulos) → cuando llega el `switch_root`, en lugar de exec
21`/lib/systemd/systemd`, exec `/sbin/arje-zero`. Esto deja firmware y
22udev fuera del scope de arje (todavía).
23
24## 2. Instalación
25
26```bash
27# 1. (opcional) revisá la seed default que se va a copiar a /ente/
28$EDITOR seeds/arje-host.card.json
29
30# 2. instalar
31sudo scripts/install-arje-as-init.sh
32
33# 3. (opcional) bootear arje SÓLO en el próximo reboot (no cambia default)
34sudo grub-reboot "arje (init=/sbin/arje-zero) — kernel $(uname -r)"
35sudo reboot
36```
37
38Si algo rompe en arje: reset/poweroff → en el menú GRUB elegir la
39entrada default (systemd) → volvés a un sistema funcional. `arje` no
40toca configuración de systemd, así que el rollback es instantáneo.
41
42Para **desinstalar**:
43
44```bash
45sudo scripts/uninstall-arje.sh
46```
47
48## 3. Filosofía vs systemd — y por qué arje no acapara
49
50systemd arranca, por default, **todo lo que tiene un `.service` con
51`WantedBy=multi-user.target`**, recursivamente vía dependencias. Eso es
52opaco y crece con cada paquete instalado.
53
54arje no tiene generadores, ni `WantedBy`, ni `Wants`, ni target trees.
55**Arranca exactamente lo declarado en `genesis: [...]` de la
56`seed.card.json`**, en el orden declarativo, con la `supervision` que
57declarás vos. Si no lo declaraste, no corre. Punto.
58
59### 3a. Servicios que systemd arranca y arje NO debería migrar
60
61Estos son los sospechosos típicos en Debian/Ubuntu/Arch. **No agregues
62ninguno a tu seed** salvo que sepas que lo usás:
63
64| systemd unit                         | por qué saltearlo                        |
65| ------------------------------------ | ---------------------------------------- |
66| `ModemManager.service`               | no tenés módem 3G/4G.                    |
67| `bluetooth.service`                  | si no usás bluetooth.                    |
68| `cups.service`, `cups-browsed`       | si no imprimís.                          |
69| `avahi-daemon.service`               | mDNS local. Ruido si no lo necesitás.    |
70| `snapd.service`                      | si no usás snaps.                        |
71| `apt-daily.service`, `apt-daily-upgrade` | autoupdates — no son init.            |
72| `unattended-upgrades.service`        | corre tras boot, no init.                |
73| `accounts-daemon.service`            | UI helpers GNOME; no init.               |
74| `colord.service`                     | calibración de color. No init.           |
75| `geoclue.service`                    | localización. No init.                   |
76| `gdm.service`, `lightdm.service`     | DM gráfico — agregalo SÓLO si querés GUI.|
77| `NetworkManager-wait-online.service` | espera red. arje no necesita "esperar".  |
78| `systemd-timesyncd.service`          | reemplaza con cron-like + ntpd one-shot. |
79| `systemd-machined.service`           | reemplazado por `arje-machined-compat`.  |
80| `systemd-logind.service`             | reemplazado por `arje-logind-compat`.    |
81| `systemd-resolved.service`           | reemplazado por `arje-resolved-compat`.  |
82| `systemd-hostnamed.service`          | reemplazado por `arje-hostnamed-compat`. |
83| `systemd-timedated.service`          | reemplazado por `arje-timedated-compat`. |
84| `systemd-localed.service`            | reemplazado por `arje-localed-compat`.   |
85| `systemd-journald.service`           | reemplazado por `arje-journald-compat`.  |
86| `systemd-tmpfiles-*.service`         | reemplazado por `arje-tmpfiles-compat`.  |
87| `systemd-binfmt.service`             | reemplazado por `arje-binfmt-compat`.    |
88| `polkitd.service`                    | reemplazado por `arje-polkit-compat`.    |
89
90Las últimas 12 ya están como Cards en `seeds/arje-host.card.json`. Las
91de la mitad de arriba **no** — no las agregues.
92
93### 3b. Servicios que SÍ necesitás declarar (y que ya están en `arje-host.card.json`)
94
95| Card label         | reemplaza                  | binario                                      |
96| ------------------ | -------------------------- | -------------------------------------------- |
97| `tmpfiles-boot`    | `systemd-tmpfiles-setup`   | `/usr/sbin/arje-tmpfiles-compat --boot`      |
98| `mount-fstab`      | `local-fs.target`          | `/bin/mount -a` (one-shot)                   |
99| `swap-on`          | `swap.target`              | `/sbin/swapon -a` (one-shot)                 |
100| `dbus-system`      | `dbus.service`             | `/usr/bin/dbus-daemon --system --nofork`     |
101| `compat-*` (×11)   | shims D-Bus de systemd     | `/usr/sbin/arje-*-compat`                    |
102| `network-dhcpcd`   | `NetworkManager` / `networkd` | `/usr/sbin/dhcpcd -B`                     |
103| `sshd`             | `ssh.service`              | `/usr/sbin/sshd -D`                          |
104| `getty-tty1`       | `getty@tty1.service`       | `/sbin/agetty --noclear tty1 linux`          |
105
10615 entes. Compará: una instalación Debian fresh con GNOME desktop tiene
107**>180 unidades activas** tras `systemctl list-units --state=running`.
108
109### 3c. Cómo agregar un servicio que falta
110
1111. Encontrá el binario y los argumentos. Mirá el `.service` original:
112   ```
113   systemctl cat <unit>
114   ```
115   Mirá `ExecStart=` y reproducí.
116
1172. Agregá una Card al `genesis` de `/ente/seed.card.json`:
118   ```json
119   {
120     "schema_version": 1,
121     "id": "<ULID nuevo, Crockford base32, no I L O U>",
122     "label": "mi-servicio",
123     "provides": [], "requires": [],
124     "permissions": { "networking": "outbound", "filesystem": "read-write", "ipc": { "allow": [] }, "processes": true },
125     "soma": { ... idéntico al patrón de los otros ... },
126     "payload": { "Native": { "exec": "/usr/sbin/mi-bin", "argv": ["--foreground"], "envp": [] } },
127     "supervision": { "Restart": { "initial": 500, "max": 30000 } },
128     "lifecycle": "daemon",
129     "priority": "normal",
130     "flow": { "input": [], "output": [] },
131     "genesis": []
132   }
133   ```
134   **Importante**: `argv` tiene que tener el equivalente a `--foreground` o
135   `-D` o `--no-fork`. Si el binario se daemoniza solo (fork+exit), arje
136   no lo puede supervisar y caerá en loop de restart.
137
1383. Validar:
139   ```bash
140   seeds/validate.sh /ente/seed.card.json
141   ```
142
1434. Reboot a arje. Verificar:
144   ```sh
145   arje# brahman-status
146   ```
147
148## 4. Diferencias de UX con systemd
149
150| acción                       | systemd                              | arje                                                    |
151| ---------------------------- | ------------------------------------ | ------------------------------------------------------- |
152| Ver servicios activos        | `systemctl list-units --state=running` | `brahman-status` + `busctl list-entes`               |
153| Ver logs                     | `journalctl -u foo`                  | `arje-journalctl` (TODO en CLI; por ahora `dmesg`)      |
154| Restart un servicio          | `systemctl restart foo`              | matar el PID (`brain` lo reanuda por `Supervision`)     |
155| Habilitar/Deshabilitar       | `systemctl enable/disable`           | editar `/ente/seed.card.json` + reboot                  |
156| Ver dependencias             | `systemctl list-dependencies foo`    | `brahman-status` muestra references y flow matches      |
157| Detectar fallas reincidentes | `systemctl status foo` → "failed"    | `brainctl crystals` muestra patrones `EnteDied → …`     |
158| socket activation            | `.socket` unit                       | (no implementado todavía; ver flow + broker matching)   |
159| user services                | `--user`                             | (no implementado; arje es system-wide por ahora)        |
160
161## 5. Cosas que arje todavía NO hace que sí hace systemd
162
163- **udev / hotplug**: arje captura uevents (vía `spawn_uevent_stream`),
164  pero no hay reglas declarativas todavía. Para boot inicial, el
165  initramfs nativo ya hizo el cold-plug, así que no es bloqueante.
166- **Timers** (cron-like): `arje-timer-compat` existe pero no está en la
167  seed host por default. Agregalo si querés `*.timer` units migradas.
168- **Service generators**: no hay equivalente a `systemd-fstab-generator`
169  ni `systemd-getty-generator`. Tu seed los declara explícitamente.
170- **Socket activation**: parcialmente — el broker matchea flow
171  consumer↔producer, pero no hay aún listen-on-fd-handoff como
172  `sd_listen_fds()`.
173- **User instances**: no hay todavía `arje --user`. Los procesos de
174  usuario los lanza un getty/login estándar.
175
176## 6. Checklist pre-primer-boot
177
178- [ ] `seeds/arje-host.card.json` ajustada a tu hardware/red/users.
179- [ ] `seeds/validate.sh` → OK.
180- [ ] `/usr/bin/dbus-daemon` existe (de lo contrario los shims no se
181      anuncian — `apt install dbus`).
182- [ ] `/usr/sbin/dhcpcd` o tu network stack preferido está instalado.
183- [ ] `/usr/sbin/sshd` instalado y `/etc/ssh/sshd_config` ok si querés
184      poder entrar remoto si la consola falla.
185- [ ] `/sbin/agetty` instalado (`util-linux`) para tty1.
186- [ ] `sudo scripts/install-arje-as-init.sh` ejecutado.
187- [ ] `grub-reboot` apuntado a la entrada arje **sólo para el próximo
188      boot** — no `grub-set-default`.
189- [ ] Listo para revertir vía menú GRUB si algo falla.
190
191## 7. Cuando arje sea estable: hacerlo default
192
193Cuando ya hayas booteado arje N veces sin problemas y querés que sea
194default:
195
196```bash
197# Listar entradas
198sudo grep -E "^\s*menuentry " /boot/grub/grub.cfg | nl
199
200# Ponerlo como default (usa el índice del menú o el title exacto)
201sudo grub-set-default "arje (init=/sbin/arje-zero) — kernel $(uname -r)"
202```
203
204Mantené la entrada systemd como rescue. Si querés acortar la lista de
205units que systemd arrancaría si bootea de nuevo: `systemctl disable
206ModemManager bluetooth cups …` — los nombres de §3a son una guía.
207
208## Apéndice — depurar el primer boot fallido
209
210Si arje no levanta el primer boot:
211
2121. Volver a GRUB → entrada systemd → bootea normal.
2132. `journalctl --boot=-1` (logs del intento previo).
2143. Buscar `arje-zero` o `Tarjeta Semilla`. Si nada → el ejecutable no
215   se lanzó (kernel panic temprano, falta `init=` correcto, etc.).
2164. Si arrancó pero falló alguna Card: la próxima vez, antes de reboot:
217   ```bash
218   sudo sed -i 's/console=tty1/console=tty1 ente.log=trace/' /etc/grub.d/40_custom
219   sudo update-grub
220   ```
221   y revisá `dmesg` desde systemd tras el reintento.

arje-replace-systemd.md

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

componentequé hacemos
/sbin/initNO se toca (sigue siendo systemd).
/lib/systemd/*NO se toca.
kernel + initramfsreusamos los del host (firmware, módulos, root FS).
init= en GRUBnueva entrada apunta a /sbin/arje-zero.
GRUB_DEFAULTNO se cambia. Sigue arrancando systemd por default.
/ente/seed.card.jsonnueva — define qué arranca arje.
/usr/sbin/arje-*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/arje-zero. Esto deja firmware y udev fuera del scope de arje (todavía).

2. Instalación

# 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/arje-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:

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 unitpor qué saltearlo
ModemManager.serviceno tenés módem 3G/4G.
bluetooth.servicesi no usás bluetooth.
cups.service, cups-browsedsi no imprimís.
avahi-daemon.servicemDNS local. Ruido si no lo necesitás.
snapd.servicesi no usás snaps.
apt-daily.service, apt-daily-upgradeautoupdates — no son init.
unattended-upgrades.servicecorre tras boot, no init.
accounts-daemon.serviceUI helpers GNOME; no init.
colord.servicecalibración de color. No init.
geoclue.servicelocalización. No init.
gdm.service, lightdm.serviceDM gráfico — agregalo SÓLO si querés GUI.
NetworkManager-wait-online.serviceespera red. arje no necesita "esperar".
systemd-timesyncd.servicereemplaza con cron-like + ntpd one-shot.
systemd-machined.servicereemplazado por arje-machined-compat.
systemd-logind.servicereemplazado por arje-logind-compat.
systemd-resolved.servicereemplazado por arje-resolved-compat.
systemd-hostnamed.servicereemplazado por arje-hostnamed-compat.
systemd-timedated.servicereemplazado por arje-timedated-compat.
systemd-localed.servicereemplazado por arje-localed-compat.
systemd-journald.servicereemplazado por arje-journald-compat.
systemd-tmpfiles-*.servicereemplazado por arje-tmpfiles-compat.
systemd-binfmt.servicereemplazado por arje-binfmt-compat.
polkitd.servicereemplazado por arje-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 labelreemplazabinario
tmpfiles-bootsystemd-tmpfiles-setup/usr/sbin/arje-tmpfiles-compat --boot
mount-fstablocal-fs.target/bin/mount -a (one-shot)
swap-onswap.target/sbin/swapon -a (one-shot)
dbus-systemdbus.service/usr/bin/dbus-daemon --system --nofork
compat-* (×11)shims D-Bus de systemd/usr/sbin/arje-*-compat
network-dhcpcdNetworkManager / networkd/usr/sbin/dhcpcd -B
sshdssh.service/usr/sbin/sshd -D
getty-tty1getty@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:

    {
      "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:

    seeds/validate.sh /ente/seed.card.json
    
  4. Reboot a arje. Verificar:

    arje# brahman-status
    

4. Diferencias de UX con systemd

acciónsystemdarje
Ver servicios activossystemctl list-units --state=runningbrahman-status + busctl list-entes
Ver logsjournalctl -u fooarje-journalctl (TODO en CLI; por ahora dmesg)
Restart un serviciosystemctl restart foomatar el PID (brain lo reanuda por Supervision)
Habilitar/Deshabilitarsystemctl enable/disableeditar /ente/seed.card.json + reboot
Ver dependenciassystemctl list-dependencies foobrahman-status muestra references y flow matches
Detectar fallas reincidentessystemctl 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

6. Checklist pre-primer-boot

7. Cuando arje sea estable: hacerlo default

Cuando ya hayas booteado arje N veces sin problemas y querés que sea default:

# 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/arje-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 arje-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:
    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.