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 with the
selected SquashFS image. forge soft-reboot first checks that the image,
shutdown hook, cleanup service, and static helper tools are available, then
hands control to dinit. After /usr has been replaced, dinit 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 /usr, but not /opt; a release
that changes /opt, or 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.