summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2205.section.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-2205.section.md2
-rw-r--r--nixos/lib/systemd-types.nix34
-rw-r--r--nixos/lib/utils.nix2
-rw-r--r--nixos/modules/system/boot/systemd/initrd.nix32
-rw-r--r--nixos/modules/system/boot/systemd/shutdown.nix36
-rw-r--r--nixos/tests/systemd-shutdown.nix11
7 files changed, 76 insertions, 43 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index 05b3822cab7..3a130e950ca 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -1266,7 +1266,7 @@
           <literal>systemd-shutdown</literal> is now properly linked on
           shutdown to unmount all filesystems and device mapper devices
           cleanly. This can be disabled using
-          <literal>boot.systemd.shutdown.enable</literal>.
+          <literal>systemd.shutdownRamfs.enable</literal>.
         </para>
       </listitem>
       <listitem>
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index 16c59ce3ddd..861339e4693 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -500,7 +500,7 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - `systemd-nspawn@.service` settings have been reverted to the default systemd behaviour. User namespaces are now activated by default. If you want to keep running nspawn containers without user namespaces you need to set `systemd.nspawn.<name>.execConfig.PrivateUsers = false`
 
-- `systemd-shutdown` is now properly linked on shutdown to unmount all filesystems and device mapper devices cleanly. This can be disabled using `boot.systemd.shutdown.enable`.
+- `systemd-shutdown` is now properly linked on shutdown to unmount all filesystems and device mapper devices cleanly. This can be disabled using `systemd.shutdownRamfs.enable`.
 
 - The Tor SOCKS proxy is now actually disabled if `services.tor.client.enable` is set to `false` (the default). If you are using this functionality but didn't change the setting or set it to `false`, you now need to set it to `true`.
 
diff --git a/nixos/lib/systemd-types.nix b/nixos/lib/systemd-types.nix
index 71962fab2e1..961b6d7f985 100644
--- a/nixos/lib/systemd-types.nix
+++ b/nixos/lib/systemd-types.nix
@@ -1,4 +1,4 @@
-{ lib, systemdUtils }:
+{ lib, systemdUtils, pkgs }:
 
 with systemdUtils.lib;
 with systemdUtils.unitOptions;
@@ -34,4 +34,36 @@ rec {
 
   automounts = with types; listOf (submodule [ stage2AutomountOptions unitConfig automountConfig ]);
   initrdAutomounts = with types; attrsOf (submodule [ stage1AutomountOptions unitConfig automountConfig ]);
+
+  initrdContents = types.attrsOf (types.submodule ({ config, options, name, ... }: {
+    options = {
+      enable = mkEnableOption "copying of this file and symlinking it" // { default = true; };
+
+      target = mkOption {
+        type = types.path;
+        description = ''
+          Path of the symlink.
+        '';
+        default = name;
+      };
+
+      text = mkOption {
+        default = null;
+        type = types.nullOr types.lines;
+        description = "Text of the file.";
+      };
+
+      source = mkOption {
+        type = types.path;
+        description = "Path of the source file.";
+      };
+    };
+
+    config = {
+      source = mkIf (config.text != null) (
+        let name' = "initrd-" + baseNameOf name;
+        in mkDerivedConfig options.text (pkgs.writeText name')
+      );
+    };
+  }));
 }
diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix
index 497d98aa4d1..d7671a37499 100644
--- a/nixos/lib/utils.nix
+++ b/nixos/lib/utils.nix
@@ -213,6 +213,6 @@ rec {
   systemdUtils = {
     lib = import ./systemd-lib.nix { inherit lib config pkgs; };
     unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
-    types = import ./systemd-types.nix { inherit lib systemdUtils; };
+    types = import ./systemd-types.nix { inherit lib systemdUtils pkgs; };
   };
 }
diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix
index 6c1b42da1c4..0c508805e45 100644
--- a/nixos/modules/system/boot/systemd/initrd.nix
+++ b/nixos/modules/system/boot/systemd/initrd.nix
@@ -156,37 +156,7 @@ in {
       '';
       visible = false;
       default = {};
-      type = types.attrsOf (types.submodule ({ config, options, name, ... }: {
-        options = {
-          enable = mkEnableOption "copying of this file to initrd and symlinking it" // { default = true; };
-
-          target = mkOption {
-            type = types.path;
-            description = ''
-              Path of the symlink.
-            '';
-            default = name;
-          };
-
-          text = mkOption {
-            default = null;
-            type = types.nullOr types.lines;
-            description = "Text of the file.";
-          };
-
-          source = mkOption {
-            type = types.path;
-            description = "Path of the source file.";
-          };
-        };
-
-        config = {
-          source = mkIf (config.text != null) (
-            let name' = "initrd-" + baseNameOf name;
-            in mkDerivedConfig options.text (pkgs.writeText name')
-          );
-        };
-      }));
+      type = utils.systemdUtils.types.initrdContents;
     };
 
     storePaths = mkOption {
diff --git a/nixos/modules/system/boot/systemd/shutdown.nix b/nixos/modules/system/boot/systemd/shutdown.nix
index 93426931667..63e1751f9b4 100644
--- a/nixos/modules/system/boot/systemd/shutdown.nix
+++ b/nixos/modules/system/boot/systemd/shutdown.nix
@@ -1,31 +1,57 @@
-{ config, lib, ... }: let
+{ config, lib, utils, pkgs, ... }: let
 
-  cfg = config.boot.systemd.shutdown;
+  cfg = config.systemd.shutdownRamfs;
+
+  ramfsContents = let
+    storePaths = map (p: "${p}\n") cfg.storePaths;
+    contents = lib.mapAttrsToList (_: v: "${v.source}\n${v.target}") (lib.filterAttrs (_: v: v.enable) cfg.contents);
+  in pkgs.writeText "shutdown-ramfs-contents" (lib.concatStringsSep "\n" (storePaths ++ contents));
 
 in {
-  options.boot.systemd.shutdown = {
+  options.systemd.shutdownRamfs = {
     enable = lib.mkEnableOption "pivoting back to an initramfs for shutdown" // { default = true; };
+    contents = lib.mkOption {
+      description = "Set of files that have to be linked into the shutdown ramfs";
+      example = lib.literalExpression ''
+        {
+          "/lib/systemd/system-shutdown/zpool-sync-shutdown".source = writeShellScript "zpool" "exec ''${zfs}/bin/zpool sync"
+        }
+      '';
+      type = utils.systemdUtils.types.initrdContents;
+    };
+
+    storePaths = lib.mkOption {
+      description = ''
+        Store paths to copy into the shutdown ramfs as well.
+      '';
+      type = lib.types.listOf lib.types.singleLineStr;
+      default = [];
+    };
   };
 
   config = lib.mkIf cfg.enable {
+    systemd.shutdownRamfs.contents."/shutdown".source = "${config.systemd.package}/lib/systemd/systemd-shutdown";
+    systemd.shutdownRamfs.storePaths = [pkgs.runtimeShell "${pkgs.coreutils}/bin"];
+
     systemd.services.generate-shutdown-ramfs = {
       description = "Generate shutdown ramfs";
+      wantedBy = [ "shutdown.target" ];
       before = [ "shutdown.target" ];
       unitConfig = {
         DefaultDependencies = false;
         ConditionFileIsExecutable = [
           "!/run/initramfs/shutdown"
-          "/run/current-system/systemd/lib/systemd/systemd-shutdown"
         ];
       };
 
+      path = [pkgs.util-linux pkgs.makeInitrdNGTool pkgs.glibc pkgs.patchelf];
       serviceConfig.Type = "oneshot";
       script = ''
         mkdir -p /run/initramfs
         if ! mountpoint -q /run/initramfs; then
           mount -t tmpfs tmpfs /run/initramfs
         fi
-        cp /run/current-system/systemd/lib/systemd/systemd-shutdown /run/initramfs/shutdown
+        make-initrd-ng ${ramfsContents} /run/initramfs
       '';
     };
   };
diff --git a/nixos/tests/systemd-shutdown.nix b/nixos/tests/systemd-shutdown.nix
index 9283489c255..688cd6dd2c1 100644
--- a/nixos/tests/systemd-shutdown.nix
+++ b/nixos/tests/systemd-shutdown.nix
@@ -1,4 +1,6 @@
-import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : {
+import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : let
+  msg = "Shutting down NixOS";
+in {
   name = "systemd-shutdown";
   meta = with pkgs.lib.maintainers; {
     maintainers = [ das_j ];
@@ -6,7 +8,9 @@ import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : {
 
   nodes.machine = {
     imports = [ ../modules/profiles/minimal.nix ];
-    boot.initrd.systemd.enable = systemdStage1;
+    systemd.shutdownRamfs.contents."/etc/systemd/system-shutdown/shutdown-message".source = pkgs.writeShellScript "shutdown-message" ''
+      echo "${msg}"
+    '';
   };
 
   testScript = ''
@@ -14,7 +18,8 @@ import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : {
     # .shutdown() would wait for the machine to power off
     machine.succeed("systemctl poweroff")
     # Message printed by systemd-shutdown
-    machine.wait_for_console_text("All filesystems, swaps, loop devices, MD devices and DM devices detached.")
+    machine.wait_for_console_text("Unmounting '/oldroot'")
+    machine.wait_for_console_text("${msg}")
     # Don't try to sync filesystems
     machine.booted = False
   '';