Files
sausage/userland/init

World init

/bin/init.wasm owns unit policy. The host starts init without a conversation. The host restarts init after an exit and kills its descendants before the next start.

Init reads persistent units from /etc/systemd/system/*.service. It reads transient units from /run/systemd/transient/*.service. The host mounts /run in memory, so transient units disappear after a host restart.

Unit files use [Unit], [Service], and [Install] sections. Init supports dependency ordering, simple and oneshot services, environment variables, and restart policies. The default start limit permits five starts within ten seconds. A stop closes stdin. Init kills the process group after TimeoutStopSec, which defaults to ten seconds. When init receives EOF, it stops dependents before prerequisites.

Enable records are files under default.target.wants or multi-user.target.wants in the persistent unit directory. The [Install] section supplies WantedBy for systemctl enable. Init observes VFS changes and applies unit edits without daemon-reload. A change to a running unit's executable content restarts that unit. Init resolves bare executable names through PATH, which defaults to /usr/local/bin:/bin. Each directory tries the bare name before the .wasm suffix. Init watches those candidate paths and compares the resolved executable's content hash. After an overflow, init rescans definitions and executable hashes. It restarts only units with a changed definition or executable. Unrelated world writes do not enter these watcher queues. Init and request clients block on pollables, with timers for lifecycle deadlines.

Control protocol

The protocol uses UTF-8 JSON files. Writers create a temporary file, then rename it to the final path. Each request uses a unique identifier.

  1. The client watches /run/systemd/replies/<id> before it submits the request.
  2. The client writes /run/systemd/requests/<id>.json.
  3. Init reads the request and applies the action.
  4. Init writes /run/systemd/replies/<id> and removes the request.
  5. The client reads and removes the reply.

Request example:

{"action":"start","unit":"example.service"}

Actions are start, stop, and restart. A reply acknowledges the action. It does not imply that the service completed its start or stop. The control tools then wait for the requested state. A failed start returns code 1.

Reply example:

{"code":0,"text":""}

A missing unit returns code 5. An unknown action returns code 1. Clients read /run/systemd/state/<unit> for the current state:

{"state":"active","pid":42,"code":null}

States are inactive, activating, active, deactivating, and failed. The code field records the most recent exit status. systemctl is-active returns 3 for an inactive unit. systemctl is-failed returns 0 for a failed unit and 1 otherwise. daemon-reload returns 0 without an action.

Journal

Init drains each unit's stdout and stderr into /var/log/journal/<unit>.log. The cap is 1 MiB. Init keeps one rotated file with the .1 suffix. journalctl -u <unit> -n <count> prints the last lines. journalctl -f observes the journal file and prints appended bytes.

Process observation

sausage-spawn exposes Watcher, ChangeKind, and child exit pollables. A watcher matches each supplied path and all its descendants. Its pollable remains ready while changes remain pending. changes() returns and clears the pending changes. Each watcher filters paths before its independent queue holds at most 256 changes. An overflow event requires a rescan. Observers report successful VFS mutations, not direct host filesystem writes outside the VFS.