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 "pivoting back to an initramfs for shutdown" // { default = true; };
13 contents = lib.mkOption {
14 description = "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 = ''
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 = {
34 "/shutdown".source = "${config.systemd.package}/lib/systemd/systemd-shutdown";
35 "/etc/initrd-release".source = config.environment.etc.os-release.source;
36 "/etc/os-release".source = config.environment.etc.os-release.source;
37 };
38 systemd.shutdownRamfs.storePaths = [pkgs.runtimeShell "${pkgs.coreutils}/bin"];
39
40 systemd.mounts = [{
41 what = "tmpfs";
42 where = "/run/initramfs";
43 type = "tmpfs";
44 }];
45
46 systemd.services.generate-shutdown-ramfs = {
47 description = "Generate shutdown ramfs";
48 wantedBy = [ "shutdown.target" ];
49 before = [ "shutdown.target" ];
50 unitConfig = {
51 DefaultDependencies = false;
52 RequiresMountsFor = "/run/initramfs";
53 ConditionFileIsExecutable = [
54 "!/run/initramfs/shutdown"
55 ];
56 };
57
58 serviceConfig = {
59 Type = "oneshot";
60 ProtectSystem = "strict";
61 ReadWritePaths = "/run/initramfs";
62 ExecStart = "${pkgs.makeInitrdNGTool}/bin/make-initrd-ng ${ramfsContents} /run/initramfs";
63 };
64 };
65 };
66}