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. |
