summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/security/pam.nix2
-rw-r--r--nixos/modules/services/hardware/mdevd.nix71
-rw-r--r--nixos/modules/system/activation/top-level.nix38
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl17
-rw-r--r--nixos/modules/system/boot/s6.nix256
6 files changed, 385 insertions, 1 deletions
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 <<RC >$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}
+    '';
+  };
+}