From 43c723b3c60350eb72b11e658b2e6a122fda6bfc Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 22 Feb 2019 18:47:53 +0000 Subject: s6 experiments --- nixos/modules/module-list.nix | 2 + nixos/modules/security/pam.nix | 2 +- nixos/modules/services/hardware/mdevd.nix | 71 ++++++ nixos/modules/system/activation/top-level.nix | 38 +++ .../system/boot/loader/grub/install-grub.pl | 17 ++ nixos/modules/system/boot/s6.nix | 256 +++++++++++++++++++++ 6 files changed, 385 insertions(+), 1 deletion(-) create mode 100644 nixos/modules/services/hardware/mdevd.nix create mode 100644 nixos/modules/system/boot/s6.nix (limited to 'nixos') diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 37e90232da2a..04cc8ff0c1fd 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -277,6 +277,7 @@ ./services/hardware/irqbalance.nix ./services/hardware/lcd.nix ./services/hardware/lirc.nix + ./services/hardware/mdevd.nix ./services/hardware/nvidia-optimus.nix ./services/hardware/pcscd.nix ./services/hardware/pommed.nix @@ -790,6 +791,7 @@ ./system/boot/networkd.nix ./system/boot/plymouth.nix ./system/boot/resolved.nix + ./system/boot/s6.nix ./system/boot/shutdown.nix ./system/boot/stage-1.nix ./system/boot/stage-2.nix diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 926c6d77d3bb..8bf132e93b33 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -376,7 +376,7 @@ let ${optionalString cfg.otpwAuth "session optional ${pkgs.otpw}/lib/security/pam_otpw.so"} ${optionalString cfg.startSession - "session optional ${pkgs.systemd}/lib/security/pam_systemd.so"} + "session optional ${pkgs.elogind}/lib/security/pam_elogind.so"} ${optionalString cfg.forwardXAuth "session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"} ${optionalString (cfg.limits != []) diff --git a/nixos/modules/services/hardware/mdevd.nix b/nixos/modules/services/hardware/mdevd.nix new file mode 100644 index 000000000000..b141bfc875eb --- /dev/null +++ b/nixos/modules/services/hardware/mdevd.nix @@ -0,0 +1,71 @@ +{ pkgs, lib, config, ... }: + +let + inherit (lib) mkDefault mkIf mkOption; + +in { + options = { + services.mdevd.enable = mkOption { + default = false; + description = "Whether to use the mdevd kernel hotplug management daemon"; + }; + + services.mdevd.package = mkOption { + default = pkgs.mdevd; + description = "Package providing the mdevd command"; + }; + + services.mdevd.verbosity = mkOption { + default = 1; + description = "Log level between 0 and 3. 3 is the most verbose."; + }; + + services.mdevd.notif = mkOption { + default = 3; + description = "File descriptor to use to notify s6 of readiness."; + internal = true; + }; + + services.mdevd.kbufsz = mkOption { + default = 500000; + description = "Bytes of buffer to reserve for the netlink queue"; + }; + + services.mdevd.slashsys = mkOption { + default = "/sys"; + description = "Location of the sysfs"; + }; + + services.mdevd.slashdev = mkOption { + default = "/dev"; + description = "Location of the device nodes"; + }; + + services.mdevd.fwbase = mkOption { + description = "Location of the firmware files, if any"; + }; + }; + + config = mkIf config.services.mdevd.enable { + services.mdevd.fwbase = mkDefault "${config.hardware.firmware}/lib/firmware"; + + # s6.rc.services.mdevd = { + # type = "longrun"; + # notification-fd = config.services.mdevd.notif; + # run = '' + # #!${pkgs.execline}/bin/execlineb -P + # ${config.services.mdevd.package}/bin/mdevd + # -v ${toString config.services.mdevd.verbosity} + # -D ${toString config.services.mdevd.notif} + # -b ${toString config.services.mdevd.kbufsz} + # -f ${pkgs.writeText "mdev.conf" '' + # SUBSYSTEM=net;.* root:root 600 @${pkgs.nettools}/bin/nameif + # tun[0-9]* root:root 600 =net/ + # tap[0-9]* root:root 600 =net/ + # ''} + # -s ${config.services.mdevd.slashdev} + # -F ${config.services.mdevd.fwbase} + # ''; + # }; + }; +} diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index a560af5ce96d..4bee55d80fbb 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -52,6 +52,20 @@ let echo -n "$kernelParams" > $out/kernel-params + ln -s ${ + + pkgs.makeInitrd { + contents = [ + { symlink = "init"; + object = pkgs.writeScript "init" '' + echo hello world + ''; + } + ]; + } + + }/${config.system.boot.loader.initrdFile} $out/s6-initrd + ln -s ${initrdPath} $out/initrd ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out @@ -65,6 +79,30 @@ let unset activationScript cp ${config.system.build.bootStage2} $out/init + + ${pkgs.s6-linux-init}/bin/s6-linux-init-maker \ + -G "${pkgs.utillinux}/bin/agetty --noclear 38400 tty1" \ + -c $out/s6 \ + -b ${pkgs.execline.bin}/bin \ + -p ${lib.makeBinPath (with pkgs; [ execline s6 s6-portable-utils s6-linux-utils s6-linux-init ])} \ + -s /run/kernel-env \ + -2 $out/s6/rc.init \ + -Z ${pkgs.writeScript "shutdown" '' + #!${pkgs.execline}/bin/execlineb -P + echo alyssa shutting down + ''} \ + $out/s6 + sed -i '9aif { ${pkgs.coreutils}/bin/mkfifo -m 600 /run/service/s6-svscan-log/fifo }' "$out/s6/init" + rm $out/s6/run-image/service/s6-svscan-log/fifo + + cat <$out/s6/rc.init + #!${pkgs.execline}/bin/execlineb -P + if { $out/activate } + if { ${config.s6.rc.initCommand} } + ${config.s6.rc.command} + RC + chmod +x $out/s6/rc.init + substituteInPlace $out/init --subst-var-by systemConfig $out ln -s ${config.system.build.etc}/etc $out/etc diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index bda6a3136407..9ad86763f06e 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -372,6 +372,10 @@ sub addEntry { "systemConfig=" . Cwd::abs_path($path) . " " . "init=" . Cwd::abs_path("$path/init") . " " . readFile("$path/kernel-params"); + my $kernelParams6 = + "systemConfig=" . Cwd::abs_path($path) . " " . + "init=" . Cwd::abs_path($path) . "/s6/init " . + readFile("$path/kernel-params"); my $xenParams = $xen && -e "$path/xen-params" ? readFile("$path/xen-params") : ""; if ($grubVersion == 1) { @@ -393,6 +397,19 @@ sub addEntry { $conf .= " multiboot $xen $xenParams\n" if $xen; $conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n"; $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n"; + $conf .= "}\n"; + $conf .= "menuentry \"$name - s6\" {\n"; + $conf .= $grubBoot->search . "\n"; + if ($copyKernels == 0) { + $conf .= $grubStore->search . "\n"; + } + if ($extraInitrd) { + $conf .= $extraInitrdPath->search . "\n"; + } + $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; + $conf .= " multiboot $xen $xenParams\n" if $xen; + $conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams6\n"; + $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n"; $conf .= "}\n\n"; } } 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} + ''; + }; +} -- cgit 1.4.1