PLUGIN-RUNNER(8mandos)

πŸ“¦
version 1.8.19 Β· 3 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’… PLUGIN-RUNNER (8mandos) β€” Mandos Manual

okay bestie, gather round, because this one is a whole situation and you're gonna want snacks πŸ“


✨ NAME ✨

plugin-runner β€” runs all the Mandos plugins, hands you the data from whichever one succeeds first. literally the plug that plugs in the plugs 🫢


✨ SYNOPSIS ✨

plugin-runner [--global-env=ENV=value | -G ENV=value ...]
              [--env-for=PLUGIN:ENV=value | -E PLUGIN:ENV=value ...]
              [--global-options=OPTIONS | -g OPTIONS ...]
              [--options-for=PLUGIN:OPTIONS | -o PLUGIN:OPTIONS ...]
              [--disable=PLUGIN | -d PLUGIN ...]
              [--enable=PLUGIN | -e PLUGIN ...]
              [--groupid=ID]
              [--userid=ID]
              [--plugin-dir=DIRECTORY]
              [--plugin-helper-dir=DIRECTORY]
              [--config-file=FILE]
              [--debug]

plugin-runner {--help | -?}

plugin-runner --usage

plugin-runner {--version | -V}

✨ DESCRIPTION ✨

so plugin-runner is a program that's meant to be listed as the β€œkeyscript” for the root disk over in crypttab(5). its whole job? spit out a password so that cryptsetup(8) can unlock your root disk. that's it, that's the gig πŸ’…

it is not meant to be run by hand β€” but you can run it by hand if you wanna test it. just know that any password it gets its hands on is simply gonna get dumped onto standard output. no filter, no shame, no cap 🌸


✨ PURPOSE ✨

the reason this exists at all: making it possible to remotely reboot β€” and reboot unattended β€” a client machine that has an encrypted root file system. yes queen, headless boxes can come back from the dead on their own. the full tea is in the section called β€œOVERVIEW” πŸ‘‘


✨ OPTIONS ✨

  • --global-env ENV=value, -G ENV=value β€” drops an environment variable setting onto every plugin. this overrides any environment variable that was inherited. no exceptions, periodt.
  • --env-for PLUGIN:ENV=value, -E PLUGIN:ENV=value β€” drops an environment variable setting onto just the PLUGIN plugin. this overrides inherited environment variables and anything you set with --global-env. it's giving very specific πŸ’…
  • --global-options OPTIONS, -g OPTIONS β€” passes some options to all plugins. OPTIONS is a comma separated list of options. honestly? not a super useful option, except for handing the β€œ--debug” option to every single plugin at once.
  • --options-for PLUGIN:OPTION, -o PLUGIN:OPTION β€” passes some options to one specific plugin. PLUGIN is the name (the file basename) of a plugin, and OPTIONS is a comma separated list of options.
heads up bestie: options are not split on whitespace. so to hand the plugin β€œfoo” the option --bar with the option argument β€œbaz”, you go either --options-for=foo:--bar=baz or --options-for=foo:--bar,baz. doing --options-for="foo:--bar baz" will not work. i don't make the rules 😭
  • --disable PLUGIN, -d PLUGIN β€” disables the plugin named PLUGIN. it will not be started. blocked, uninvited, not on the list πŸ™ˆ
  • --enable PLUGIN, -e PLUGIN β€” re-enables the plugin named PLUGIN. this is only useful for undoing an earlier --disable option, maybe one that came from the configuration file.
  • --groupid ID β€” changes to group ID ID on startup. the default is 65534. all plugins get started using this group ID.
note: this must be a number, not a name. numbers only, bestie πŸ”’
  • --userid ID β€” changes to user ID ID on startup. the default is 65534. all plugins get started using this user ID.
same deal: this must be a number, not a name.
  • --plugin-dir DIRECTORY β€” points at a different plugin directory. the default is /lib/mandos/plugins.d, which is where it'll live in the initial RAM disk environment.
  • --plugin-helper-dir DIRECTORY β€” points at a different plugin helper directory. the default is /lib/mandos/plugin-helpers, which is where it'll live in the initial RAM disk environment. (this one just gets passed along to every plugin via the MANDOSPLUGINHELPERDIR environment variable. see the section called β€œWRITING PLUGINS”)
  • --config-file FILE β€” points at a different file to read extra options from. see the section called β€œFILES”. any other command line options will override whatever the file said. file gets first dibs, CLI gets the final word ✨
  • --debug β€” turns on debug mode. this dumps a lot of output to standard error about what the program is up to. it still does all its normal functions though, nothing gets skipped. default is to not run in debug mode.
the plugins are not affected by this option. if you want complete debugging eruption, use --global-options=--debug πŸ’€
  • --help, -? β€” gives you a help message about options and what they mean.
  • --usage β€” gives you a short usage message.
  • --version, -V β€” prints the program version.

✨ OVERVIEW ✨

so this whole thing is part of the Mandos system, which lets computers have encrypted root file systems and still be capable of remote and/or unattended reboots. iconic behaviour honestly πŸ‘‘

here's the vibe: the computers run a little client program inside the initial RAM disk environment, and that client talks to a server over a network. all that network chatter is encrypted with TLS. the server identifies each client using a TLS key, and every client has one that's unique to it. then the server sends the client an encrypted password. the client decrypts that password using a separate OpenPGP key, and then that password gets used to unlock the root file system β€” after which the computer just carries on booting like nothing happened. slay πŸ’…

this program runs on the client side, inside the initial RAM disk environment, and it's the one responsible for getting a password. how? by running plugins. one of those plugins will normally be the actual client program that talks to the server πŸ¦‹


✨ PLUGINS ✨

this program gets a password by running a bunch of plugins, which are just executable programs sitting in a directory inside the initial RAM disk environment. the default directory is /lib/mandos/plugins.d, but you can change that with the --plugin-dir option.

the plugins get started in parallel, and the first plugin to output a password and exit with a successful exit code wins the whole thing β€” at which point plugin-runner outputs that plugin's password, stops every other plugin, and dips out. main character energy, first come first served πŸ†

🌸 WRITING PLUGINS 🌸

a plugin is an executable program that prints a password to its standard output, then exits with a successful (zero) exit status. if the exit status is not zero, then anything the plugin wrote to standard output gets ignored by the plugin runner. anything the plugin writes to its standard error channel just gets passed straight through to the plugin runner's standard error β€” which is usually the system console.

if the password is a single-line, manually entered passphrase, then you should not print a final trailing newline character. don't do it bestie πŸ™ˆ

the plugin runs in the initial RAM disk environment, so be careful β€” it must not depend on any files or running services that aren't available in there. if the plugin needs helper executables (and they're not in the PATH), you can drop them into the plugin helper directory. the name of that directory gets handed to the plugin through the MANDOSPLUGINHELPERDIR environment variable πŸŽ€

the plugin must exit cleanly and free all allocated resources when it receives the TERM signal, because that's exactly what the plugin runner uses to stop all the other plugins once one plugin has output a password and exited cleanly. no lingering, no loose ends 🫢

the plugin also must not use resources β€” like, say, reading from standard input β€” without knowing that no other plugin is using that same resource. sharing is only caring when you actually know who you're sharing with 😭

it's useful, but not required, for the plugin to take the --debug option.


✨ FALLBACK ✨

if no plugins succeed, this program has a fallback: it asks for a password on the console using getpass(3), and then outputs it. this is not meant to be the normal mode of operation, because there's a separate plugin whose whole job is getting a password from the console. so like, this is the emergency backup outfit, not the everyday fit πŸ’…


✨ EXIT STATUS ✨

the exit status of this program is zero if no errors were encountered, and otherwise not zero. and the fallback (see the section called β€œFALLBACK”) may or may not have succeeded either way. ambiguous? yes. accurate? also yes ✨


✨ ENVIRONMENT ✨

this program doesn't use any environment variables itself β€” it just passes its environment on to all the plugins. you can modify the environment that reaches the plugins with the --global-env and --env-for options. also, the --plugin-helper-dir option affects the MANDOSPLUGINHELPERDIR environment variable for the plugins 🌈


✨ FILES ✨

  • /conf/conf.d/mandos/plugin-runner.conf β€” since this program runs as a keyscript, there's basically little to no opportunity to pass command line arguments to it. so it also reads this file and uses its contents as whitespace-separated command line options. also, everything from a β€œ#” character to the end of a line is ignored.

this program is meant to run in the initial RAM disk environment, so that's where this file is assumed to exist. the file does not need to exist in the normal file system.

this file gets processed before the normal command line options, so the latter can override the former if need be.

this file name is the default; you can change which file gets read for arguments using the --config-file option.

  • /lib/mandos/plugins.d β€” the default plugin directory; changeable with the --plugin-dir option.
  • /lib/mandos/plugin-helpers β€” the default plugin helper directory; changeable with the --plugin-helper-dir option.

✨ BUGS ✨

the --config-file option is ignored when it's specified from within a configuration file. yeah. that one. i know. πŸ’€

please report bugs to the Mandos development mailing list: <mandos-dev@recompile.se> (subscription required). note that this list is public. the developers can be reached privately at <mandos@recompile.se> (OpenPGP key fingerprint 153A 37F1 0BBA 0435 987F 2C4A 7223 2973 CA34 C2C4 for encrypted mail) πŸ”


✨ EXAMPLE ✨

normal invocation needs no options:

plugin-runner

run the program, but not the plugins, in debug mode:

plugin-runner --debug

run all plugins, but run the β€œfoo” plugin in debug mode:

plugin-runner --options-for=foo:--debug

run all plugins, but not the program, in debug mode:

plugin-runner --global-options=--debug

read a different configuration file, run plugins from a different directory, specify an alternate plugin helper directory and add four options to the mandos-client(8mandos) plugin:

cd /etc/keys/mandos; plugin-runner
--config-file=/etc/mandos/plugin-runner.conf --plugin-dir
/usr/lib/x86_64-linux-gnu/mandos/plugins.d --plugin-helper-dir
/usr/lib/x86_64-linux-gnu/mandos/plugin-helpers
--options-for=mandos-client:--pubkey=pubkey.txt,--seckey=seckey.txt,
--tls-pubkey=tls-pubkey.pem,--tls-privkey=tls-privkey.pem

okay that's part one bestie, don't go anywhere β€” there's more coming πŸ’œ

πŸ” SECURITY πŸ”

okay bestie, so when this program starts up, it's gonna try to switch to another user. If you started it as root, it WILL succeed, and by default it switches to user and group 65534, which are assumed to be non-privileged. That user and group is then what all plugins get started as. So like, the only way to run a plugin as a privileged user is to have the set-user-ID or set-group-ID bit set on the plugin executable file (see execve(2)). no cap πŸ’…

And if this program is used as a keyscript in crypttab(5), there's a slight risk that if this program fails to work, there might be no way to boot the system except for booting from another media and editing the initial RAM disk image to not run this program. But like, this is unlikely, because the password-prompt(8mandos) plugin will read a password from the console in case of failure of the other plugins, and this plugin runner will also, in case of catastrophic failure, itself fall back to asking and outputting a password on the console (see the section called β€œFALLBACK”). 🫢✨

πŸ‘€ SEE ALSO πŸ‘€

Copyright Β© 2008-2024 Teddy Hogeborn, BjΓΆrn PΓ₯hlsson πŸ’–

This manual page is part of Mandos.

Mandos is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Mandos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Mandos. If not, see http://www.gnu.org/licenses/.


Mandos 1.8.19, dated 2025-06-27, from PLUGIN-RUNNER(8mandos) β€” slay, bye bestie πŸ’…πŸ’–

πŸ“¦ where this page comes from