Why Ironforge uses dinit
Ironforge uses dinit because its desktop and network services need an explicit startup order, and because dinit can restart userspace without restarting the kernel.
Why SysV init stopped fitting
Early versions of Ironforge used SysV init and /etc/inittab. That was adequate
while boot mostly meant starting long-running programs that could be treated as
independent processes. It became fragile as the desktop stack grew.
D-Bus, PipeWire, WirePlumber, Wi-Fi association, and DHCP do not merely need to be launched. Each service must start only after its prerequisites are running or ready. A flat list of commands does not express those relationships. Keeping the ordering in shell scripts would instead spread polling, retries, and process supervision across the boot sequence.
Dinit keeps the init system small while making the service relationships explicit.
The startup graph
The current service definitions encode the important paths through boot:
| Area | Ordered services | Why the order matters |
|---|---|---|
| Hardware | early-setup → udevd → udev-coldplug |
The device manager must be running before devices are triggered and allowed to settle. |
| Network | udev-coldplug → wpa_supplicant → wifi-ready → dhcpcd |
The wireless device must exist, Wi-Fi must associate, and only then can DHCP request an address. |
| Audio | dbus → pipewire → pipewire-pulse and wireplumber |
PipeWire starts after D-Bus and waits for seat management; its compatibility server and session manager start after PipeWire. |
| Desktop | D-Bus, seatd, PipeWire, and device coldplug → desktop session |
The graphical session starts only after the services it uses have completed startup. |
Hard depends-on relationships keep required services running. Softer
waits-for relationships provide ordering where a failed prerequisite does not
have to block the rest of the system. Independent branches can still start in
parallel.
Long-running services such as D-Bus, PipeWire, WirePlumber, wpa_supplicant,
and dhcpcd are also configured for automatic restart. Ordering, failure
handling, and supervision therefore live beside each service definition rather
than in one growing startup script.
Soft reboot
Dinit can perform a soft reboot: it stops user-space services, runs the Ironforge shutdown hook, and starts dinit again with the original boot-time arguments. The kernel remains running.
Ironforge uses that shutdown window to replace the mounted /usr and /opt
with the pair selected through /var/ironforge/images/current.
forge soft-reboot checks that both images, the shutdown hook, cleanup service,
and static helper tools are available, then hands control to dinit. The hook
mounts both new images before replacing the live mounts and restores the old
mounts if the switch fails. Dinit then starts the service graph again against
the new userspace.
This is what makes the Ironforge goal of avoiding reboots except for kernel
upgrades practical. A soft reboot refreshes both /usr and /opt; a kernel
update still requires a normal reboot. See
Release layout and updates for the release-level rules.
The trade-off
Dinit needs more service definitions than the old /etc/inittab, but those
files document the real boot contract. The extra structure replaces implicit
timing assumptions with dependencies that can be inspected, restarted, and
tested independently.