S6-OVERVIEW(7)
π s6-overview(7) β an overview of s6, but make it make sense π
πΈ NAME πΈ
s6-overview β an overview of s6. That's the name, bestie. π
β¨ DESCRIPTION β¨
Okay so s6 is literally a collection of utilities revolving around process supervision and management, logging, and system initialization. This page is the high-level description of the different parts of s6. No cap.
This is about the s6 package, also called s6-supervision, not the s6 ecosystem. If you've just heard of a nebulous thing called s6 that may or may not be an alternative init system, know that the s6 package, while it's at the core of it all, is only a part of it; and it is likely that the part you actually want to interact with is s6-frontend[1] instead, which provides a simple user interface to the whole ecosystem. So if you're like "bestie I just want the UI," that's your girl. π«Ά
Still here? Okay, let's talk about the functionality that this package provides: the s6 supervision suite. π
π¦ Process supervision π¦
At its core, s6 is a process supervision suite, like its ancestor daemontools[2] and its close cousin runit[3]. Family tree slay. π
π Concept π
The concept of process supervision comes from several observations:
- Unix systems, even minimalistic ones, need to run long-lived processes, aka daemons. That is one of the core design principles of Unix: one service β one daemon. Literally the whole "one service β one daemon" thing. π
- Daemons can die unexpectedly. Maybe they are missing a vital resource and cannot handle a certain failure; maybe they tripped on a bug; maybe a misconfigured administration program killed them; maybe the kernel killed them. Processes are fragile, but daemons are vital to a Unix system: a fundamental discrepancy that needs to be solved. π
- Automatically restarting daemons when they die is generally a good thing. In any case, sysadmin intervention is necessary, but at least the daemon is providing service, or trying to, until the sysadmin can log in and investigate the underlying problem. Iconic behaviour, honestly. β¨
- Ad-hoc shell scripts that restart daemons suck, for several reasons that would each justify their own page. The difficulty of keeping track of the PID, explained below, is one of those reasons. Not me defending shell scripts. π
- It is sometimes necessary to send signals to a daemon. To kill it, of course, but also to make it read its config file again, for instance; signalling a daemon is a natural and very common way of sending it simple commands. Like a little "hey bestie, reread your config" tap. π
- Generally, to send a signal to a daemon, you need to know its PID. Without a supervision suite, knowing the proper PID is hard. Most non-supervision systems use a hack known as
.pidfiles, i.e. the script that starts the daemon stores its PID into a file, and other scripts read that file. This is a bad mechanism for several reasons, and the case against.pidfiles would also justify its own page; the most important drawback of.pidfiles is that they create race conditions and management scripts may kill the wrong process. Big yikes. π© - Non-supervision systems provide scripts to start and stop daemons, but those scripts may fail at boot time even though they work when run manually, and vice versa. If a sysadmin logs in and runs the script to restart a daemon that has died, the result might not be the same as if the whole system had been rebooted, and the daemon may exhibit strange behaviours! This is because the boot-time environment and the restart-time environment are not the same when the script is run; and a non-supervision system just cannot ensure reproducibility of the environment. This is a core problem of non-supervision systems: countless bugs have been falsely reported because of simple environment differences or configuration errors, countless man-hours have been wasted to try and understand what was going on. The way that this is a whole mood. π€
A process supervision system organizes the process hierarchy in a radically different way.
- A process supervision system starts an independent hierarchy of processes at boot time, called a supervision tree. This supervision tree never dies: when one of its components dies, it is restarted automatically. To ensure availability of the supervision tree at all times, it should be rooted in process 1, which cannot die. Process 1 is the main character, fr fr. π
- A daemon is never started, either manually or in a script, as a scion of the script that starts it. Instead, to start a daemon, you configure a specific directory which contains all the information about your daemon; then you send a command to the supervision tree. The supervision tree will start the daemon as a leaf. In a process supervision system, daemons are always spawned by the supervision tree, and never by an admin's shell. The tree does the spawning, not your shell. Periodt. π³
- The parent of your daemon is a supervisor. Since your daemon is its direct child, the supervisor always knows the correct PID of your daemon. No guessing games. π―
- The supervisor watches your daemon and can restart it when it dies, automatically. Obsessed with the reliability. π
- The supervision tree always has the same environment, so starting conditions are reproducible. Your daemon will always be started with the same environment, whether it is at boot time via init scripts or for the 100th automatic - or manual - restart. Reproducibility ate. π₯
- To send signals to your daemon, you send a command to its supervisor, which will then send a signal to the daemon on your behalf. Your daemon is identified by the directory containing its information, which is stable, instead of by its PID, which is not stable; the supervisor maintains the correct association without a race condition or the other problems of
.pidfiles. Stable identifier > unstable PID. Slay. π
π Implementation π
s6 is a straightforward implementation of those concepts.
- The
s6-svscan(8) ands6-supervise(8) programs are the components of the supervision tree. They are long-lived programs.s6-supervise(8) is a daemon's supervisor, its direct parent. For every long-lived process on a system, there is a correspondings6-supervise(8) process watching it. This is okay, because every instance ofs6-supervise(8) uses very few resources. Lowkey efficient. πΈs6-svscan(8) is, in a manner of speaking, a supervisor for the supervisors. It watches and maintains a collection ofs6-supervise(8) processes: it is the branch of the supervision tree that all supervisors are stemming from. It can be run and supervised by your regular init process, or it can run as process 1 itself; refer tos6-svscan-not-as-process-1(7) ans6-svscan-as-process-1(7). Runnings6-svscan(8) as process 1 requires some effort from the user, because of the inherent non-portability of init processes; thes6-linux-initpackage[4] automates that effort and allows users to run s6 as an init replacement. Init replacement era. π- The configuration of a daemon to be supervised by
s6-supervise(8) is done via ans6-service-directory(7). Directory-based config, we love to see it. π - The place to gather all service directories to be watched by an
s6-svscan(8) instance is called ans6-scan-directory(7). Scan directory, bestie. ποΈ
- The command that controls a single supervisor, and allows you to send signals to a daemon, is
s6-svc(8). It is a short-lived program. Short-lived but powerful. β‘ - The command that controls a set of supervisors, and allows you to start and stop supervision trees, is
s6-svscanctl(8). It is a short-lived program. Also short-lived, also iconic. β¨
These four programs, s6-svscan(8), s6-supervise(8), s6-svscanctl(8) and s6-svc(8), are the very core of s6. Technically, once you have them, you have a functional s6 installation, and the other utilities are just a bonus. The core four, no cap. π
π Practical usage π
To use s6's supervision features, you need to perform the following steps:
- For every daemon you potentially want supervised, write an
s6-service-directory(7). Make sure that your daemon does not background itself when started in the./runscript! Auto-backgrounding is a historical hack that was implemented when supervision suites did not exist; since you're using a supervision suite, auto-backgrounding is unnecessary and in this case detrimental. Do not let your daemon background itself, bestie. π ββοΈ - Write a single
s6-scan-directory(7) for the set of daemons you want to actually run. This set can be modified at run time. Runtime changes, we love. π¦ - At some point in your initialization scripts, run
s6-svscan(8) on the scan directory. This will start the supervision tree, including your set of daemons. The exact way of runnings6-svscan(8) depends on your system: it is not quite the same when you want to run it as process 1 on a real machine, or under another init on a real machine, or as process 1 in aDocker[5] container, or in another context entirely. Context matters, periodt. π³ - Alternatively, you can start
s6-svscan(8) on an empty scan directory, then populate it step by step and send an update command tos6-svscan(8) vias6-svscanctl(8) whenever the supervision tree should pick up the differences and start the services you added. Populate and update, the gradual glow-up. β¨ - That's it, your services are running. To control them manually, you can use the
s6-svc(8) command. You did it, bestie. π - At the end of the system's lifetime, you can use
s6-svscanctl(8) to bring down the supervision tree. Shutdown era. π
π Service-specific logging π
s6-svscan(8) can monitor a supervision tree, but it can also do one more thing. It can ensure that a daemon's log, i.e. what the daemon outputs to its stdout (or stderr if you redirect it), gets processed by another, supervised, long-lived process, called a logger; and it can make sure that the logs are never lost between the daemon and the logger - even if the daemon dies, even if the logger dies. Logs never lost, not even if everything dies. That's the promise. π
If your daemon is outputting messages, you have a decision to make about where to send them.
- You can do as non-supervision systems do, and send the messages to syslog. It's entirely possible with a supervision system too. However, like auto-backgrounding, syslog is a historical mechanism that predates supervision suites, and is technically inferior; it is recommended that you do not use it whenever you can avoid it. Syslog is giving "historical hack," ngl. π
- You can send them to the daemon's stdout/stderr and do nothing special about it. The logs will then be sent to
s6-svscan(8)'s stdout/stderr; what mechanism will read them depends on how you starteds6-svscan(8). Simple but depends on your setup. πΈ - You can use
s6-svscan(8)'s service-specific logging mechanism and dedicate a logger process to your daemon's messages. Dedicated logger, main character energy. π
s6 provides you with a long-lived process to use as a logger: s6-log(8). It will store your logs in one (or more) specific directory of your choice, and rotate them automatically. s6-log(8) is the logging bestie you deserve. π
π§ Helpers for run scripts π§
Creating a working s6-service-directory(7), and especially a good run script, is the most important part of the work when adapting a daemon to a supervision framework.
like, if you can find your daemon's invocation script on a non-supervision system β think a System V-style init script β congrats, bestie, because you can literally see the exact options the daemon is being run with: environment variables, uid and gid, open descriptors, etc. That's the whole vibe check you need to replicate in your run script. β¨
(And pls, do NOT replicate the auto-backgrounding, or stuff like start-stop-daemon[6] invocation. start-stop-daemon and its little friends are hideous and kludgy attempts to work around the lack of proper supervision mechanisms β it's giving duct tape energy. Now that you have s6, you should remove them from your system, throw them into a bonfire, and dance and laugh while they burn. π₯ Generally speaking, as a system administrator you want daemons that have been designed following the principles described in [7], or at least you want to use the command-line options that make them behave in such a way.)
The vast majority of the tools provided by s6 are meant to be used in run scripts: they help you control the process state and environment in your script before it executes into your daemon. Or, sometimes, they are daemons themselves, designed to be supervised. π
s6, like other skarnet.org software[8], makes heavy use of chain loading[9], also known as βBernstein chainingβ: a lot of s6 tools will perform some action that changes the process state, then execute into the rest of their command line. This allows the user to change the process state in a very flexible way β just combine the right components in the right order, iykyk. Very often, a run script can be reduced to a single command line β likely a long one, but still a single one. (That is the main reason why using the execline[10] language to write run scripts is recommended: execline makes it natural to handle long command lines made of massive amounts of chain loading. This is by no means mandatory, though: a run script can be any executable file you want, provided that running it eventually results in a long-lived process with the same PID.)
Some examples of s6 programs meant to be used in run scripts:
- The
s6-log(8) program is a long-lived process. It is meant to be executed into by a./log/runscript: it will be supervised, and will process what it reads on its stdin (i.e. the output of the./rundaemon). π - The
s6-envdir(8) program is a short-lived process that will update its current environment according to what it reads in a given directory, then execute into the rest of its command line. It is meant to be used in a run script to adjust the environment with which the final daemon will be executed into. - Similarly, the
s6-softlimit(8) program adjusts its resource limits, then executes into the rest of its command line: it is meant to set the resources the final daemon will have access to. - The
s6-applyuidgid(8) program, part of the βs6-*uidgidβ family, drops root privileges before executing into the rest of its command line: it is meant to be used in run scripts that need root privileges when starting but do not need it for the execution of the long-lived process. π«Ά s6-ipcserverd(8) is a daemon that listens to a Unix socket and spawns a program for every connection. It is meant to be supervised, so it should be used in a run script, and it's also meant to be a flexible super-server that you can use for different applications: so it is a building block that may appear in several of your run scripts definings6-local-service(7)s.
π Readiness notification and dependency management
So now you have a supervision tree, and long-lived processes running supervised β iconic β and you may want to introduce dependencies between them: do not perform an action (e.g. start (with βs6-svc -uβ) the Web server connecting to a database) before a given daemon is up and running (e.g. the database server). s6 provides tools to do that:
- The
s6-svwait(8),s6-svlisten1(8) ands6-svlisten(8) programs will wait until a set of daemons is up, ready, down (as soon as the./runprocess dies) or really down (when the./finishprocess has also died). - Unfortunately, a daemon being up does not mean that it is ready:
s6-notifywhenup(7) goes into the details. s6 supports a simple mechanism: when a daemon wants to signal that it is ready, it simply writes a newline to a file descriptor of its choice, ands6-supervise(8) will pick that notification up and broadcast the information to processes waiting for it. β¨ - s6 also has a legacy mechanism for daemons that do not notify their own readiness but provide a way for an external program to check whether they're ready or not:
s6-notifyoncheck(8). This is polling, which is bad, but unfortunately necessary for many daemons as of 2019. π
ngl, s6 does not provide a complete dependency management framework, i.e. a program to automatically start (or stop) a set of services in a specific order β that order being automatically computed from a graph of dependencies between services. That functionality belongs to a service manager, and is implemented for instance in the s6-rc package[11].
π Fine-grained control over services
s6 provides you with a few more tools to control and monitor your services. For instance:
s6-svstat(8) gives you access to the detailed state of a service.s6-svperms(8) allows you to configure what users can read that state, what users can send control commands to your service, and what users can be notified of service start/stop events.s6-svdt(8) allows you to see what caused the latest deaths of a supervised process.
These tools make s6 the most powerful and flexible of the existing process supervision suites. periodt. π
π Additional utilities
The other programs in the s6 package are various utilities that may be useful in designing servers, and more generally multi-process software. They can be used with or without a supervision environment, although it is of course recommended to have one; but they are not part of the core s6 functionality, and you may safely ignore them for now if you are just getting into the supervision world. π
π¦ Generic inter-process notification
The βs6-ftrig*β family of programs allows notifications between unrelated processes: a set of processes can subscribe to a certain channel β identified by a directory in the filesystem β and ask to be notified of certain events on that channel; another set of processes can send events to the channel.
The underlying mechanism is the same as the one used by the supervision tree for readiness notification, but the βs6-ftrig*β tools provide a more generic access to that mechanism.
πΈ Helpers for designing local services
Local services, i.e. daemons listening to a Unix domain socket, are a powerful and flexible mechanism, especially with modern Unix systems that allow client authentication. s6 includes tools to take advantage of that mechanism. π«Ά
- The β
s6-ipc*β family of programs is about designing clients or servers that communicate over Unix domain sockets. - The β
s6-*access*β ands6-connlimit(8) family of programs is about client access control. - The β
s6-sudo*β family of programs is about using a local service in order to give selected clients the ability to run a command line with the privileges of the server, without using suid programs. π₯
π Keeping file descriptors open
Sometimes you want to keep a file descriptor open, even if the program normally using it dies β so the program can restart and use the same file descriptor without losing any data. To do that, you need to hold the descriptor in another process, i.e. that process should have it open but do nothing with it.
s6-svscan(8), for instance, holds the pipe existing between a supervised daemon and its logger, so even if the daemon or the logger dies while there are logs in the pipe, the pipe remains open and the logs are not lost. π
s6 provides a mechanism to store and retrieve open file descriptors in a totally generic way: the βs6-fdholder*β family of programs.
- The
s6-fdholder-daemon(8) program is a daemon (or, rather, executes into thes6-fdholderd(8) daemon), meant to be supervised, that will hold file descriptors on its clients' behalf. - Other programs in the family, such as
s6-fdholder-store(8), are client programs that interact with this daemon to store and retrieve file descriptors.
ok so quick note: βsocket activationβ, one of the main advertised benefits of the systemd[12] init system, sounds similar to fd-holding. The reality is that socket activation is a mixture of several different mechanisms, one of which is fd-holding; s6 allows you to implement the healthy parts of socket activation. Refer to s6-socket-activation(7) for details. π
π§ Other miscellaneous utilities
This page does not list or classify every s6 tool. Please explore the βReferenceβ section of the main s6 page[13] for details on a specific program.
π SEE ALSO
- [1]
https://skarnet.org/software/s6-frontend/ - [2]
https://cr.yp.to/daemontools.html - [3]
http://smarden.org/runit/ - [4]
https://skarnet.org/software/s6-linux-init/ - [5]
https://www.docker.com/ - [6]
http://man.he.net/man8/start-stop-daemon - [7]
https://jdebp.uk/FGA/unix-daemon-design-mistakes-to-avoid.html - [8]
https://skarnet.org/software/ - [9]
https://en.wikipedia.org/wiki/Chain_loading#Chain_loading_in_Unix - [10]
https://skarnet.org/software/execline/ - [11]
https://skarnet.org/software/s6-rc/ - [12]
https://www.freedesktop.org/wiki/Software/systemd/ - [13]
https://skarnet.org/software/s6/
π AUTHORS
- Laurent Bercot
- Alexis
<flexibeast@gmail.com>(man page port)
k that's the whole page bestie, ily, go supervise something gorgeous π This one's from the Debian crew, dated January 24, 2026, and it's the S6-OVERVIEW(7) page β mwah, slay, no cap. π
π¦ where this page comes from
- nixpkgs unstable: s6 2.15.1.0
- nixpkgs unstable: s6-man-pages 2.14.0.1.4
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms