s6-frontend
Software
skarnet.org
s6-frontend: an overview
Concepts
s6-frontend does not come with any innovating concepts — it's just a series
of user-friendly wrappers around various commands in the s6 ecosystem, hiding
the details of various options and installation directories. For instance:
- Instead of running s6-svc -r /run/service/foobar, you run
s6 process restart foobar
- Instead of running s6-rc -d change foobar, you run
s6 live stop foobar
- Instead of running s6-rc-init /run/service && s6-rc change default
at boot time, you run s6 system boot
The most innovating change comes from the
repo commands, in the
version of s6-rc that is released at the
same time as the first release of s6-frontend. The goals of the repo commands, which
are wrapped by the s6 repository and
s6 set commands, are:
- To provide a framework for distributions and system administrators to organize their
text-format source definition directories, by defining places where service definitions
should be stored
- To allow local administrators to tailor what services they want to see in
their live database, by providing intermediaries between the service stores and
the live database called offline sets.
- With s6 set mask, an administrator
can make it so a service, though defined in a store, will not appear in the service
database at all. Unmasked services appear in the live database, but are only started
at boot time when they are enabled (or essential, but that property
is best set in the service definition itself and never overridden).
- To allow easy replacement of the current live database by a set that has been
worked on.
Contents of the s6-frontend package
The s6-frontend package does not itself contain much. The only binary
that users will interact with directly is the
s6 binary, which is a wrapper around the
s6-frontend binary (which users
should not have to call directly), which is itself a wrapper around
various commands of the s6 ecosystem that users also need to have
installed in order for s6-frontend to work. That means:
- s6, the package,
not the command: a process supervisor. Yes, the
s6 binary is provided by the s6-frontend
package (this package) and not the s6 package. Because the "s6" name,
which was originally meant for "the supervision system", evolved to mean
"the skarnet.org ecosystem of programs", and s6 was the natural
name to use for a command interfacing with all of it.
- s6-rc: a service manager
working on top of the s6 process supervisor.
- optionally, s6-linux-init:
a set of programs to make a Linux system boot and use
s6-svscan, the cornerstone
of the s6 process supervisor, as pid 1. This makes s6 a full init system, by
eliminating the need to pair s6 with something like busybox init, sysvinit,
openrc-init or systemd, which provide a pid 1.
- Future packages may be added to the ecosystem to add functionality,
for instance: a package with turnkey essential service definitions that downstream
can use, a package to handle namespaces and cgroups, a package to handle
capabilities, etc.
Installing s6-frontend
In addition to the s6-frontend package and its dependencies, in order to
make use of the s6 command, you will need
service definitions in the s6-rc source format
describing various services that can run on a machine — long-running
daemons, one-shot scripts, and "bundles" aliasing to a group of these services.
If you are running s6-frontend from a distribution, the packages that provide
these services should already have them defined, and the service definition
directories should already be available in some pre-configured
stores. Your
distribution should also have pre-installed everything you need in order
for you to be able to use the s6 command to
control the system. However, if you are installing s6-frontend manually, or are
the person building the distribution, here is what you need to do:
- Define one or more places where your service directories will
be hosted: it's the equivalent of /etc/init.d for OpenRC or sysv-rc,
the place where they store their scripts; or the equivalent of the places where
systemd looks for its unit files, namely:
/etc/systemd/system.control,
/run/systemd/system.control,
/run/systemd/transient,
/run/systemd/generator.early,
/etc/systemd/system,
/etc/systemd/system.attached,
/run/systemd/system,
/run/systemd/system.attached,
/run/systemd/generator,
/usr/local/lib/systemd/system,
/usr/lib/systemd/system, and
/run/systemd/generator.late.
- Yes, we think systemd might be overdoing it just a little.
But who are we to criticize if it works for them? 🤭
- We recommend having two or three stores: one for packages
installed by the package manager, one for local modifications, and possibly
one that is managed by the distribution outside of any package. The default
store list for s6-frontend is
/usr/share/s6-frontend/s6-rc/sources:/etc/s6-frontend/s6-rc/sources,
which means that the package manager should install service definition
directories in /usr/share/s6-frontend/s6-rc/sources, and that
administrators should do their local modifications in
/etc/s6-frontend/s6-rc/sources. You can modify this store list
at build time with the --storelist configure option, or after
installation in the s6-frontend configuration file, see below.
- Then you need the service definitions themselves.
- Service definitions for a given daemon such as e.g. sshd should
be written by the distribution that packages sshd and provided by the
package manager when it installs sshd. (The definitions could be provided by
the sshd upstream, but service definitions are policy not
mechanism and we think policy is the realm of distributions, not
software authors.)
- Essential services, i.e. how to boot a machine and bring it to
the state where it can accept logins and run services provided by packages,
should be provided by the distribution in a specific package.
- systemd comes with a big list of unit files: it provides some policy
itself.
- OpenRC also comes with a set of basic services: it provides some policy
itself as well.
- s6-frontend does not provides policy, but work is underway to
write these since basic service files are essential for people to use it. When
complete they will be provided in a separate package. In the meantime, you can
find service definitions contributed by the community pretty much everywhere
s6-rc is used. The s6-rc package comes with some example service definitions
as well; if you want to try out s6-frontend outside of a real installation,
we recommend downloading the
demo stores and put them in your storelist.
Define a configuration file,
located at /etc/s6-frontend.conf unless you modified the default at
build time. If you have gone with all the defaults for all the packages in the s6
ecosystem, the configuration file can basically be empty; but you will probably
at least want to define the storelist variable.
Once your configuration file is ready, and all your services are in the
store, you need to initialize the repository:
s6 repository init. This command
will create the repository and make a reference database with all the services
in your stores. If it succeeds, congratulations! Your stores are consistent,
i.e. they define a full set of services that can be used by the s6-rc service manager.
Check that the default states of the service are what you want with
s6 set status. If they're not, make the
changes you need with various s6 set commands.
Once you're happy with the set, commit your changes with
s6 set commit. This will make an s6-rc
compiled service database.
Install this service database as the one that will be run at boot time.
This is done by s6 live install --init.
Note that the --init option should only be given for this first installation
when the machine isn't managed by s6-rc yet.
Make sure your init system will actually boot the service database you have
just installed. The command that should be run at boot time is:
s6 system boot. Check the link to see
how to configure your init system to run it.
If everything is ready, reboot the machine. Congratulations! It is now
running under a full s6 init system.
If you are using s6-linux-init,
the way to reboot your system will be
s6 system reboot from now on.
Comparison with OpenRC
One of the design goals of s6-frontend is to provide a user interface to service
management that is comparable to the one provided by OpenRC and should be
similar in everyday usage barring the following differences.
The fundamental difference between s6-frontend and OpenRC is that OpenRC always
works on live services, the ones that are currently running on the
user's machine. It only has one live database, comprising several
"runlevels" (sets of services meant to be run together), and manages its
dependency tree dynamically. On the other hand, s6-frontend (and, more accurately,
the s6-rc service manager and its
repo commands),
separates the notion of live database and of working set
entirely. The working set is worked on offline, without
impacting the current machine state. You can start and stop
live services, but you can only enable or disable
— or mask — services on the working set. Enabling a
service means that next time you boot on the service database you are
working on, that service will be automatically started.
Once you have worked on a set of services you can replace the live
database with it; the old live database disappears entirely, and your
working set (well, a copy of it) is now live.
A corollary of that is that s6-frontend does not have runlevels. It does
not need them. The default bundle specifies what services should
be started at boot; other bundles (in the sense of s6-rc) can be defined
in the stores, and the user can start and stop them at will, as well as
start and stop individual services, dependencies notwithstanding. By
default all the services are accessible in the live database but the
user can choose to exclude certain services by masking them in
a working set and then installing that set.
The following table shows some equivalencies between s6-frontend and OpenRC;
it is not meant to be exhaustive but to show a representative enough sample of
the kind of commands that can be worked with.
| OpenRC command |
s6-frontend equivalent |
Notes |
| rc-service foobar start |
s6 live start foobar |
Starts a service in the live database. |
| rc-service foobar status |
s6 live status foobar or s6 process status foobar |
s6 process status foobar only works if foobar is a longrun,
in which case it will give detailed information on its supervised instance. |
| rc-status default |
s6 live status or s6 set status |
s6 live status shows the status of the current live database,
s6 set status the status of the offline working set. |
| rc-update add foobar |
s6 set enable foobar |
Enable service foobar in the offline working set. |
| rc-update del foobar |
s6 set disable foobar |
Disable service foobar in the offline working set. |
| rc-update show |
s6 set status |
Shows the enabled, disabled and masked services, but to make the
changes effective, the user needs to run s6 set commit then
s6 live install. |
| openrc sysinit && openrc boot && openrc default |
s6 system boot |
The existence of the sysinit and boot runlevels are a
historical wart that OpenRC still has to deal with; s6-frontend does not. |
| reboot |
reboot or s6 system reboot |
Just like OpenRC's reboot command will only work if the system
is using openrc-init, s6 system reboot command will only work
if the system is using s6-linux-init. |