s6-linux-init
Software
skarnet.org

# Quickstart and FAQ for s6-linux-init

## Quickstart

1. Install all the s6-linux-init dependencies:
   - skalibs
   - execline
   - s6
2. Save and remove your old `/etc/s6-linux-init` directory, if you have one.
3. Install s6-linux-init itself.
4. Save your old `/sbin/init`, `/sbin/telinit`, `/sbin/shutdown`, `/sbin/halt`, `/sbin/poweroff` and `/sbin/reboot` binaries.
5. Make sure you have a `/run` directory.
6. Edit the scripts in `/etc/s6-linux-init/skel`.
7. Check that your devtmpfs is automounted by your kernel at boot time. If it is not, add the `-d /dev` option to the `s6-linux-init-maker` command line below.
8. As root, run:

            rm -rf /tmp/blah
            s6-linux-init-maker -1 -G "/sbin/getty 38400 tty1" /tmp/blah
            rm -rf /etc/s6-linux-init/current
            mv /tmp/blah /etc/s6-linux-init/current
            cp -a /etc/s6-linux-init/current/bin/* /sbin/

9. Reboot. Warning: use your old reboot command, that you saved, not the new one that has just been created by `s6-linux-init-maker`, because you're still running on your old init system and need to use a reboot command that matches it.
10. After the reboot: congratulations! your machine is now running a s6-based init system.
11. To shut the machine down, use `/sbin/shutdown`, `/sbin/halt`, `/sbin/poweroff` or `/sbin/reboot` as usual.

## FAQ

### How do I convert a runit setup to a s6 one ?

A runit and a s6 setup are very similar. There are just three things you need to pay attention to:

- runsv supports customized controls, whereas s6-supervise does not. Fortunately, very few services use the customized control feature of runit; and s6 supports customizing the termination signal to a process via the down-signal file, which can replace 99% of the legit uses of customized control. So, you should check your service directories for `control/` subdirectories, and adapt them depending on how your service handles controls. If a service does not use customized controls, you don't need to make any change and the service will run under s6-supervise as is.
- The interface of svlogd, runit's logger, is different from the interface of s6-log, s6's logger. Namely, svlogd reads a config file in its log directory, while s6-log reads its configuration on its command line. If you have logging services that use svlogd, you should read their configuration in their logdir, and translate it to the proper s6-log invocation.
- And, finally, the init process. Understanding how s6-linux-init works may seem daunting, but using it really is a lot simpler than it looks.

In a runit setup, you have the runit program running as pid 1, and sequentially spawning `/etc/runit/1`, then `/etc/runit/2` which contains the invocation of runsvdir, and finally `/etc/runit/3` at shutdown time when runsvdir is dead.

In a s6 setup that you have booted via s6-linux-init, the scanner, s6-svscan (the equivalent of runsvdir), runs as pid 1, very early, and remains there for the whole lifetime of the machine. At boot time, the `/etc/s6-linux-init/current/scripts/rc.init` script is run, with the supervision tree already in place; when it exits, the system is supposed to be in a fully-booted, stable state. At shutdown time (on receipt of a shutdown command), the `/etc/s6-linux-init/current/scripts/rc.shutdown` script is run, with the supervision tree still in place; when it exits, the filesystems will be unmounted and the machine will be rebooted and/or stopped.

So, the quickest way to port a runit setup to a s6-linux-init one is to:

- Copy your `/etc/runit/1` to `/etc/s6-linux-init/current/scripts/rc.init`. The only thing you should remove here is the creation of `/run`, because s6-linux-init has already mounted a tmpfs on `/run`. But basically all the rest should stay.
- Also copy the parts of `/etc/runit/2`, if any, that come before the runsvdir invocation, to `/etc/s6-linux-init/current/scripts/rc.init`.
- At the end of `/etc/s6-linux-init/current/scripts/rc.init`, symlink all your runit service directories to `/run/service`, and call `s6-svscanctl -a /run/service`. This will start and supervise all the services that you have symlinked, the way the original runsvdir invocation would have.
- Copy your `/etc/runit/3` to `/etc/s6-linux-init/current/scripts/rc.shutdown`, removing the parts that unmount the filesystems and reboot the machine.

Once you have done that, you have a literal translation of your runit system into a s6 system, and it should boot, and work, albeit in a non-idiomatic, unoptimized way. If you don't want to overwrite your `/sbin/init` binary, you can boot with `init=/etc/s6-linux-init/current/bin/init` as a kernel command line argument to reach the s6-linux-init entry point.

Further work to make the setup prettier can include:

- Identifying daemons you run in `/etc/s6-linux-init/current/scripts/rc.init` and making them early services instead.
- Or, more idiomatically, analyze your whole boot sequence in `/etc/s6-linux-init/current/scripts/rc.init` and the daemons in your runit service directories, and convert the boot sequence so it can be handled by a service manager, for instance s6-rc.

Colin Booth has a series of posts on Reddit that go into more detail on how to use a Void Linux distribution, which natively uses runit, with the s6 ecosystem instead; there are step-by-step tutorials as well as turnkey solutions, and it is recommended reading even if you do not use Void.