Devuan and various systemd-free Linux distributions provide alternative init systems. runit is among the most barebones and lightest. Having a small code base makes it easier to maintain and also audit for bugs and security issues. It is able to run on other Unices like *BSD, MacOSX, etc., as well. In this article, I am going to cover the basics of the runit init scheme with Devuan as a base. However, most concepts and commands should be the same for other distributions. You may refer to the references at the end for learning in more detail.
Working Mechanism
According to the official documentaion, runit is an init scheme with service supervision. That means it handle automatic starting of services during boot, as well as monitoring and restarting them. Conforming to the UNIX philosophy, runit consists of various small tools and binaries (albeit not to the extent of being bloated *ahem* systemd *ahem*) for interacting with it and other daemons.
Like with most init systems, the kernel loads the first process – /sbin/init
which is provided by the runit-init(8) program. It then replaces itself with runit(8). runit is what performs the system’s booting, running and shutting down and it does so in three stages:
- Stage 1:
The system performs the one-time initialization tasks through/etc/runit/1
. We get an emergency shell if this stage fails. - Stage 2:
runit starts/etc/runit/2
which handles the runlevels through runsvdir(8). This is the stage our system stays in when it’s running. We can also give the Ctrl+Alt+Delete reboot request at this stage. - Stage 3:
If/etc/runit/2
returns without errors, which happens during system halt or reboot, runit starts/etc/runit/3
. The shutdown tasks are performed in stage 3.
Runlevels
A standard installation of runit has 2 runlevels, default
and single
. A runlevel directory contains symlinks to other service directories. Most tasks are performed and most services are started in the default
runlevel. But we can make our own runlevels by creating a new folder in/etc/runit/runsvdir/
and symlinking our desired services to that runlevel. My Devuan installation has two other runlevels created.
Runit changes the runlevels by switching the directory the runsvdir
program is running in. This is handled by the runsvchdir
command.
For example, to switch to the single
user runlevel:# runsvchdir single
We can also ask runit to start in a specific runlevel during bootup instead of the default
. We can do so by appending the runitdir=name
kernel parameter. Obviously, the runlevel name
should exist i.e. a directory must be available at /etc/runit/runsvdir
with that name.
For example, to directly boot to the single-user mode (i.e. the single
runlevel), we can append runitdir=single
to the kernel parameter.
In GRUB, we can do this by hitting the e
key while highlighting an entry at the bootloader menu.
Hitting Ctrl+X
will make the system boot with the given parameters, effectively getting us into single-user mode.
Managing Services
A service directory contains files and necessary scripts to manage the daemon. Service directories are located in the /etc/sv
directory.
These service directories must be symlinked to /etc/service
otherwise runit
won’t be able to access them.
Creating the symlink in /etc/service
will essentially enable
it so that it’s started at boot time. We can disable
a service by creating a file named down
inside the service directory.
Although runit has several programs, we usually only need to interact with the sv
command. The syntax is equivalent to systemd‘s systemctl
command.
Starting a service:
# sv start <service_name>
Stopping it:
# sv stop <service_name>
Restarting or reloading a service:
# sv restart <service_name>
Check the status of a service:
# sv status <service_name>
There’s also rewrite of the sv
command in Rust called rsv
. However, I am not going to cover it in this article. Please check the link among the references below.
References: