diff options
Diffstat (limited to 'nixos/modules/system/boot/s6.nix')
-rw-r--r-- | nixos/modules/system/boot/s6.nix | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/nixos/modules/system/boot/s6.nix b/nixos/modules/system/boot/s6.nix new file mode 100644 index 000000000000..23ccd0f0c8b6 --- /dev/null +++ b/nixos/modules/system/boot/s6.nix @@ -0,0 +1,256 @@ +{ pkgs, lib, config, ... }: + +let + inherit (builtins) typeOf; + inherit (pkgs) linkFarm writeScript runCommand; + inherit (lib) concatStringsSep mapAttrsToList mkOption mkDefault types filterAttrsRecursive foldr; + + s6EntryTypes = { + int = v: s6Entry (toString v); + bool = v: s6Entry ""; + string = writeScript "s6-file"; + set = v: linkFarm "s6-dir" + (mapAttrsToList (name: value: { inherit name; path = s6Entry value; }) v); + list = v: s6Entry (concatStringsSep "\n" v); + }; + + s6Entry = v: s6EntryTypes.${typeOf v} v; + + s6RcCompile = { uids ? null, gids ? null, fdhuser ? null }: source: + runCommand "s6-rc-compile" {} '' + ${config.s6.rc.package}/bin/s6-rc-compile \ + ${if (uids != null) then "-u ${concatStringsSep "," uids}" else ""} \ + ${if (gids != null) then "-g ${concatStringsSep "," gids}" else ""} \ + ${if (fdhuser != null) then "-h ${fdhuser}" else ""} \ + $out \ + ${lib.traceVal (toString (s6Entry (filterAttrsRecursive (n: v: v != null) source)))} + ''; + +in { + options = { + s6.rc.package = mkOption { + default = pkgs.s6-rc; + description = '' + The package to look for the s6-rc, s6-rc-compile, and s6-rc-init + commands in. + ''; + }; + + s6.rc.initTimeout = mkOption { + default = null; + description = '' + Milliseconds to wait for all s6-supervise processes to start up before + giving up. + ''; + }; + + s6.rc.timeout = mkOption { + default = null; + description = '' + Milliseconds to wait for s6-rc to transition to the up state. + ''; + }; + + s6.rc.services = mkOption { + description = '' + Attribute set of available services. Names correspond to service + directory names on disk. Values are attribute sets of service + properties, which are then transformed into the directory structure + expected by s6-rc-compile. + ''; + example = { + foo = { + type = "oneshot"; + up = "echo hello world"; + dependencies = [ "bar" "baz" ]; + env = { a = "b"; }; + }; + }; + + type = with types; attrsOf + (submodule { + options = { + type = mkOption { + description = "type"; + type = enum [ "bundle" "oneshot" "longrun" ]; + }; + contents = mkOption { + description = "contents"; + type = nullOr (listOf str); + default = null; + }; + timeout-up = mkOption { + description = "timeout-up"; + type = nullOr ints.unsigned; + default = null; + }; + timeout-down = mkOption { + description = "timeout-down"; + type = nullOr ints.unsigned; + default = null; + }; + dependencies = mkOption { + description = "dependencies"; + type = nullOr (listOf str); + default = null; + }; + up = mkOption { + description = "up"; + type = nullOr str; + default = null; + }; + down = mkOption { + description = "down"; + type = nullOr str; + default = null; + }; + run = mkOption { + description = "run"; + type = nullOr str; + default = null; + }; + finish = mkOption { + description = "finish"; + type = nullOr str; + default = null; + }; + notification-fd = mkOption { + description = "notification-fd"; + type = nullOr ints.unsigned; + default = null; + }; + timeout-kill = mkOption { + description = "timeout-kill"; + type = nullOr ints.unsigned; + default = null; + }; + timeout-finish = mkOption { + description = "timeout-finish"; + type = nullOr ints.unsigned; + default = null; + }; + nosetsid = mkOption { + description = "nosetsid"; + type = nullOr bool; + default = null; + }; + data = mkOption { + description = "data"; + type = nullOr (attrsOf str); + default = null; + }; + env = mkOption { + description = "env"; + type = nullOr (attrsOf str); + default = null; + }; + producer-for = mkOption { + description = "producer-for"; + type = nullOr str; + default = null; + }; + consumer-for = mkOption { + description = "consumer-for"; + type = nullOr (listOf str); + default = null; + }; + pipeline-name = mkOption { + description = "pipeline-name"; + type = nullOr str; + default = null; + }; + }; + }); + }; + + s6.rc.live = mkOption { + default = "/run/s6-rc"; + description = '' + Where to store the s6-rc live state. + ''; + }; + + s6.rc.prefix = mkOption { + default = ""; + description = '' + Unique prefix to apply to all service names when they are added to the + supervisor, for disambiguation. + ''; + }; + + s6.rc.uids = mkOption { + default = null; + description = '' + IDs of users who should be allowed to start and stop services controlled + by this instance of s6-rc. Default: only root. + ''; + }; + + s6.rc.gids = mkOption { + default = null; + description = '' + IDs of groups who should be allowed to start and stop services controlled + by this instance of s6-rc. Default: only root. + ''; + }; + + s6.rc.fdhuser = mkOption { + default = null; + description = '' + User for the s6-fileholder-daemon process to run as. Defaults to root, + the owner of the supervision tree. + ''; + }; + + s6.rc.initBundle = mkOption { + default = "ok-all"; + description = '' + Name of the top bundle to be brought up at system startup. + ''; + }; + + s6.rc.initCommand = mkOption { + description = '' + The s6-rc-init command line to be executed by rc.init, prior to running + s6-rc. + ''; + }; + + s6.rc.command = mkOption { + description = '' + The s6-rc command line to be executed by rc.init, after running + s6-rc-init. + ''; + }; + }; + + config = { + s6.rc.services.${config.s6.rc.initBundle} = { + type = "bundle"; + contents = []; + }; + + s6.rc.initCommand = mkDefault '' + ${config.s6.rc.package}/bin/s6-rc-init \ + -c ${s6RcCompile + { inherit (config.s6.rc) uids gids fdhuser; } + config.s6.rc.services} \ + -l ${config.s6.rc.live} \ + -p "${config.s6.rc.prefix}" \ + ${if (config.s6.rc.initTimeout != null) + then "-t ${toString config.s6.rc.initTimeout}" + else ""} \ + /run/service + ''; + + s6.rc.command = mkDefault '' + ${config.s6.rc.package}/bin/s6-rc \ + -l ${config.s6.rc.live} \ + change \ + ${if (config.s6.rc.timeout != null) + then "-t ${toString config.s6.rc.timeout}" + else ""} \ + ${config.s6.rc.initBundle} + ''; + }; +} |