Runit service supervision and systemd unit compatibility limits
0 reputation · 02 Sept 2025, 15:22 UTC
0 reputation · 02 Sept 2025, 15:22 UTC
Artix Linux provides the runit init system as a lightweight alternative to systemd, utilizing a supervise daemon model to manage services via run scripts located in /service. This architecture enables parallel startup and fast boot times by avoiding the complex dependency trees found in larger init systems.
A technical challenge arises when integrating software packages designed specifically for systemd unit files. Since runit does not natively parse these units, administrators must manually create run scripts or utilize third-party conversion tools to ensure service persistence and supervision.
Given the structural differences between these two systems, what are the documented limits for automating the conversion of systemd units to runit scripts? Is there a standardized method to maintain service dependencies when migrating from a systemd-centric package to a runit environment?
29275 reputation · 02 Sept 2025, 23:49 UTC
There is no standardized, fully automated method that preserves complete systemd unit semantics when converting to runit scripts. Existing converters handle only basic ExecStart/ExecStop translation and lose declarative dependency directives (Wants, Requires, PartOf, Conflicts, After/Before). Dependency ordering in runit must be implemented manually through run-script sequencing or external orchestration.
.service, .socket, .timer, or .target files.systemd2runit or distribution helpers (e.g., Artix's systemd2runit package) emit a minimal run script and optional finish/check scripts. They do not translate:# systemd directives with no runit equivalent
Wants=, Requires=, PartOf=, Conflicts=
After=, Before= (ordering only)
ConditionPathExists=, ConditionKernelVersion=
MemoryLimit=, CPUQuota=, IOWeight= (cgroup v2)
DynamicUser=, PrivateTmp=, ProtectSystem=
Restart=on-failure (runit supervise restarts unconditionally)
StandardOutput=journal (runit logs via svlogd)
/service is supervised independently. There is no built-in dependency graph; sv up starts services in filesystem order unless you script otherwise.systemctl list-unit-files --type=service --state=enabled and capture each unit with systemctl cat <unit>.systemd2runit <unit>) to produce /etc/sv/<name>/run. Review every line.run script, add a sv wait or sv check loop for each prerequisite before exec.systemd-run --scope equivalents via cgexec, prlimit, or kernel boot parameters.PrivateTmp=yes to a per-service TMPDIR in run; map ProtectSystem=strict to bind mounts or namespaces via unshare wrappers.Restart=on-failure, write a finish script that exits 0 only on clean shutdown signals.ln -s /etc/sv/<name> /service/ then sv up <name>. Verify with sv status <name> and sv log <name>.| Approach | How It Works | Trade-off |
|---|---|---|
Run-script sv wait chains |
Each run blocks on sv check dep1 && sv check dep2 before exec. |
Explicit, visible in script; adds boot latency if overused. |
Stage directories (e.g., /etc/runit/1, 2, 3) |
Boot stages run sequentially; services in stage N start after stage N-1 completes. | Coarse-grained; fits traditional runit layouts (Void, Artix). |
| External orchestrator (s6-rc, nosh, or custom) | Declare a dependency graph once; tool expands to runit-compatible scripts. | Adds another layer; defeats runit minimalism for some admins. |
systemctl show <unit> output against the final run script for every directive.cat /proc/<pid>/cgroup matches intended slice.sv down <name>; sv up <name> and observe restart behavior.run state without manual intervention.Are you migrating a complete host (all services) or only select packages that lack runit-native scripts? A full-host migration justifies investing in a stage-based or orchestrator approach; a few packages are faster to hand-script individually.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.