1{ config, lib, utils, pkgs, ... }: let
2
3 cfg = config.systemd.shutdownRamfs;
4
5 ramfsContents = let
6 storePaths = map (p: "${p}\n") cfg.storePaths;
7 contents = lib.mapAttrsToList (_: v: "${v.source}\n${v.target}") (lib.filterAttrs (_: v: v.enable) cfg.contents);
8 in pkgs.writeText "shutdown-ramfs-contents" (lib.concatStringsSep "\n" (storePaths ++ contents));
9
10in {
11 options.systemd.shutdownRamfs = {
12 enable = lib.mkEnableOption (lib.mdDoc "pivoting back to an initramfs for shutdown") // { default = true; };
13 contents = lib.mkOption {
14 description = lib.mdDoc "Set of files that have to be linked into the shutdown ramfs";
15 example = lib.literalExpression ''
16 {
17 "/lib/systemd/system-shutdown/zpool-sync-shutdown".source = writeShellScript "zpool" "exec ''${zfs}/bin/zpool sync"
18 }
19 '';
20 type = utils.systemdUtils.types.initrdContents;
21 };
22
23 storePaths = lib.mkOption {
24 description = lib.mdDoc ''
25 Store paths to copy into the shutdown ramfs as well.
26 '';
27 type = lib.types.listOf lib.types.singleLineStr;
28 default = [];
29 };
30 };
31
32 config = lib.mkIf cfg.enable {
33 systemd.shutdownRamfs.contents."/shutdown".source = "${config.systemd.package}/lib/systemd/systemd-shutdown";
34 systemd.shutdownRamfs.storePaths = [pkgs.runtimeShell "${pkgs.coreutils}/bin"];
35
36 systemd.mounts = [{
37 what = "tmpfs";
38 where = "/run/initramfs";
39 type = "tmpfs";
40 }];
41
42 systemd.services.generate-shutdown-ramfs = {
43 description = "Generate shutdown ramfs";
44 wantedBy = [ "shutdown.target" ];
45 before = [ "shutdown.target" ];
46 unitConfig = {
47 DefaultDependencies = false;
48 RequiresMountsFor = "/run/initramfs";
49 ConditionFileIsExecutable = [
50 "!/run/initramfs/shutdown"
51 ];
52 };
53
54 serviceConfig = {
55 Type = "oneshot";
56 ProtectSystem = "strict";
57 ReadWritePaths = "/run/initramfs";
58 ExecStart = "${pkgs.makeInitrdNGTool}/bin/make-initrd-ng ${ramfsContents} /run/initramfs";
59 };
60 };
61 };
62}