S6-USERTREE-MAKER(8)

πŸ“¦ version 2.15.1.0, in nixpkgs unstable

πŸ’– s6-usertree-maker(8) πŸ’–

okay so bestie, this is a section 8 man page β€” a System Manager's Manual situation β€” and today's main character is s6-usertree-maker. she's here to make your users their very own supervision trees and honestly? iconic.


✨ NAME ✨

s6-usertree-maker β€” creates an s6-service-directory(7) that implements a service, and that service runs an s6-svscan(8) process which is owned by a given user, running on an s6-scan-directory(7) that belongs to that same user 🫢


🌸 SYNOPSIS 🌸

s6-usertree-maker [-d userscandir] [-p path]
                  [-E envdir [-e var -e var ...]]
                  [-r service/logger[/pipeline]] [-l loguser]
                  [-t stamptype] [-n nfiles] [-s filesize] [-S maxsize]
                  [-P prefix] user logdir dir

πŸ¦‹ DESCRIPTION πŸ¦‹

s6-usertree-maker is basically the admin's bestie when you're deploying systems where every single user gets their own supervision subtree, rooted in the main supervision tree (the one owned by root). no cap, it's giving delegation πŸ’…

okay and alternatively? s6-usertree-maker can also create source definition directories for the s6-rc[1] service manager. so it's versatile. we love a multi-talented queen.

so what does it actually do: s6-usertree-maker creates an s6-service-directory(7) in dir, and that directory launches a supervision tree as user user, on the s6-scan-directory(7) called userscandir, with a catch-all logger that logs the tree's output via s6-log(8) into the logdir directory. caught every last crumb of output. obsessed.

the trick here β€” the whole reason this works so nicely β€” is that execline[2] scripts are way easier to generate programmatically and to harden than shell scripts. so s6-usertree-maker only gets built if s6 is built with execline support, i.e. if the --disable-execline switch has not been given to configure. if you disabled execline, sorry bestie, this binary isn't happening 😭

now, important vibe check for the admin who wants to automate user tree management: s6-usertree-maker is a building block meant to be used in scripts, not a complete turnkey solution. it's a supporting character, not the lead. for instance:

  • s6-usertree-maker does not create userscandir for a user β€” it just assumes that that s6-scan-directory(7) is already in place.
  • it does not create logdir either β€” logdir, or at least its parent directory, must already exist before the logger is run, else s6-log(8) will fail repeatedly. πŸ’€ so, like, please make sure all the data and metadata referenced by the service's and the logger's run scripts are actually present and valid before starting the service.
and here's a warning that matters: if s6-usertree-maker encounters failure (and exits 111), it does not clean up the directories it created. so like, always test s6-usertree-maker's return code and clean up after it if needed. she leaves a mess, you tidy it. that's the deal πŸ™ˆ

πŸŽ€ Operation of the service πŸŽ€

when the service is started, its run script will execute the following operations, in order:

  • Clear all its environment variables, except PATH. this is the anti-leak measure β€” it prevents any data leak from the parent supervision tree into the user subtree. clean slate energy ✨
  • Fill its environment with data related to user:
    • USER is set to user.
    • HOME is set to user's home directory.
    • UID is set to user's uid.
    • GID is set to user's primary gid.
    • GIDLIST is set to user's supplementary groups list.
  • If the service has been created with the -E option to s6-usertree-maker:
    • Add all the variables defined in envdir to its environment.
    • For every variable var given via a -e option, subject var to substitution with the USER, HOME, UID, GID and GIDLIST variables (see below).
  • Set the PATH environment variable to path, subjected to variable substitution.
  • Execute into s6-svscan(8), running in userscandir (which is first subjected to variable substitution).

and the service is logged β€” its stderr and stdout are piped to an s6-log(8) process running as loguser and writing to the logdir directory. this logger is the catch-all logger for the supervision tree owned by user.

lowkey a security note: it is recommended to make loguser distinct from user, and to have logdir in a place that is not under the control of user. separation is self-care 🧚

if user wants to keep control of their logs, they can declare a logger for each of their services. their logs, their rules πŸ’œ

🌈 Variable substitution 🌈

when the service starts, the USER, HOME, UID, GID and GIDLIST environment variables are deduced from user's identity. and the values of those variables may be used in a few configuration knobs:

  • The value of userscandir: it's likely that the s6-scan-directory(7) belonging to user resides under user's home directory. or under /run/user/${UID}, or some similar scheme.
  • The PATH environment variable, declared in path: it's often useful to prepend the default system PATH with a user-specific directory that hosts that user's binaries. for instance, you may want the PATH to be set as something like ${HOME}/bin:/usr/bin:/bin.
  • Any variable declared in envdir and given as an argument to an -e option to s6-usertree-maker. if envdir is a template valid for all users, it may contain variables that depend on user-specific data: for instance, the XDG_CONFIG_HOME variable may be set to ${HOME}/.config.

when the strings β€˜${USER}’, β€˜${HOME}’, β€˜${UID}’, β€˜${GID}’, or β€˜${GIDLIST}’ appear in the value for userscandir, path, or any of the var variables, they are substituted with the corresponding value of the USER, HOME, UID, GID, or GIDLIST environment variable instead. (yes, that quoting is exactly how the original rolls, don't come for me 🫢)

for instance β€” a little example, because examples slay: if no -d option is provided, the default value for userscandir is ${HOME}/service. so if the provided user is β€˜ska’ and ska's home directory is /home/ska, then s6-svscan(8) will be run on /home/ska/service. and that's the whole plot πŸ”₯


πŸ’… OPTIONS πŸ’…

  • -d userscandir β€” the supervision tree will be run on the userscandir directory. userscandir is subject to variable substitution (see above). default is ${HOME}/service.
  • -p path β€” the supervision tree will be run with a PATH environment variable set to path. path is subject to variable substitution. default is /usr/bin:/bin, or whatever has been given to the β€˜--with-default-path’ option to skalibs' configure script.
  • -E envdir β€” the supervision tree will be run with the environment variables defined in the directory envdir, which will be read via s6-envdir(8) without options. by default, no envdir is defined and the supervision tree will only be run with the basic environment variables listed below.
  • -e var β€” perform variable substitution on var. this option is repeatable, and only makes sense when the -E option is also given. for every var listed via an -e option, the contents of var will be subjected to variable substitution before the supervision tree is run. this is only useful if var is defined in envdir, as a template, that is then instanced for user when the service is run. by default, only the PATH environment variable, customizable via -p, is subjected to variable substitution.
  • -r service/logger/pipeline β€” create an s6-rc[1] source definition directory. when this option is given, dir is not created as an s6-service-directory(7), but as a directory containing two services: dir/service and dir/logger, and dir is suitable as a source argument to s6-rc-compile[3]. the β€˜/pipeline’ part can be omitted, but if it is present, pipeline is used as a name for a bundle containing both service and logger. when this option is not given, dir is a regular service directory for direct inclusion (or linking) in the parent scan directory (and the catch-all logger for the user subtree is declared in dir/log).
  • -l loguser β€” run the catch-all logger of the user subdirectory as user loguser. default is β€˜root’.
  • -t stamptype β€” how logs are timestamped by the catch-all logger. β€˜0’ means no timestamp, β€˜1’ means external TAI64N format[4], β€˜2’ means ISO 8601 format[5], and β€˜3’ means both. default is β€˜1’.
  • -n nfiles β€” maximum number of archive files in logdir. default is β€˜10’.
  • -s filesize β€” maximum size of the current file (and archive files) in logdir. default is β€˜1000000’.
  • -S maxsize β€” maximum total size of the archives in the logdir. default is β€˜0’ meaning no limits apart from those enforced by the -n and -s options.
  • -P prefix β€” when logging to logdir, prefix logged lines with the prefix string.

⭐ EXIT STATUS ⭐

  • 0 β€” Success. we love a happy ending πŸ’–
  • 100 β€” Wrong usage.
  • 111 β€” System call failed. 😭 and remember, no cleanup happens on this one!

πŸ“ EXAMPLES πŸ“

okay here's the first one, look at her go:

s6-usertree-maker -d '/run/user/${UID}/service' -p
'${HOME}/bin:/usr/bin:/bin' -E /etc/user-env -e XDG_CONFIG_HOME -l
catchlog ska /var/log/usertree/ska usertree-ska

this creates a service directory in β€˜usertree-ska’ declaring a service that starts a supervision tree on /run/user/1000/service if ska has uid 1000, with /home/ska/bin:/usr/bin/bin as its PATH if ska's home directory is /home/ska, and with all the environment variables declared in /etc/user-env, among which the XDG_CONFIG_HOME variable is processed for variable substitution. the supervision tree has a catch-all logger running as user catchlog, and storing its data in the /var/log/usertree/ska directory.

note that simple quotes are used here to prevent the shell from interpreting β€˜${UID}’ and β€˜${HOME}’. protect your variables, bestie 🫢

and the second one, the s6-rc variant:

s6-usertree-maker -d '/run/user/${UID}/service' -p
'${HOME}/bin:/usr/bin:/bin' -E /etc/user-env -e XDG_CONFIG_HOME -l
catchlog -r usertree-ska/usertree-ska-log/usertree-ska-pipeline
ska /var/log/usertree/ska usertree

same as above, except it does not create a service directory. instead, it creates a β€˜usertree’ directory containing two subdirectories: β€˜usertree-ska’, the s6-rc[1] source definition directory for the service, and β€˜usertree-ska-log’, the source definition directory for its logger. it also creates an implicit β€˜usertree-ska-pipeline’ bundle containing both the service and the logger. two birds, one gorgeous command ✨


🐚 SEE ALSO 🐚

this man page is ported from the authoritative documentation at: https://skarnet.org/software/s6/s6-usertree-maker.html


πŸ‘‘ AUTHORS πŸ‘‘

  • Laurent Bercot
  • Alexis <flexibeast@gmail.com> (man page port)

and that's a wrap! πŸ’œ sourced from Debian, dated January 15, 2023, filed under S6-USERTREE-MAKER(8) β€” go forth and supervise, bestie πŸŒΈβœ¨πŸŽ€

πŸ“¦ where this page comes from