Update lean 4.15 (#373564)
[NixPkgs.git] / nixos / modules / system / boot / systemd / repart.nix
blob0e1c1b4e2785c178a36a12b3f088bc7a7426e867
2   config,
3   lib,
4   pkgs,
5   utils,
6   ...
7 }:
9 let
10   cfg = config.systemd.repart;
11   initrdCfg = config.boot.initrd.systemd.repart;
13   format = pkgs.formats.ini { };
15   definitionsDirectory = utils.systemdUtils.lib.definitions "repart.d" format (
16     lib.mapAttrs (_n: v: { Partition = v; }) cfg.partitions
17   );
19   partitionAssertions = lib.mapAttrsToList (
20     fileName: definition:
21     let
22       inherit (utils.systemdUtils.lib) GPTMaxLabelLength;
23       labelLength = builtins.stringLength definition.Label;
24     in
25     {
26       assertion = definition ? Label -> GPTMaxLabelLength >= labelLength;
27       message = ''
28         The partition label '${definition.Label}' defined for '${fileName}' is ${toString labelLength}
29         characters long, but the maximum label length supported by systemd is ${toString GPTMaxLabelLength}.
30       '';
31     }
32   ) cfg.partitions;
35   options = {
36     boot.initrd.systemd.repart = {
37       enable = lib.mkEnableOption "systemd-repart" // {
38         description = ''
39           Grow and add partitions to a partition table at boot time in the initrd.
40           systemd-repart only works with GPT partition tables.
42           To run systemd-repart after the initrd, see
43           `options.systemd.repart.enable`.
44         '';
45       };
47       device = lib.mkOption {
48         type = with lib.types; nullOr str;
49         description = ''
50           The device to operate on.
52           If `device == null`, systemd-repart will operate on the device
53           backing the root partition. So in order to dynamically *create* the
54           root partition in the initrd you need to set a device.
55         '';
56         default = null;
57         example = "/dev/vda";
58       };
59     };
61     systemd.repart = {
62       enable = lib.mkEnableOption "systemd-repart" // {
63         description = ''
64           Grow and add partitions to a partition table.
65           systemd-repart only works with GPT partition tables.
67           To run systemd-repart while in the initrd, see
68           `options.boot.initrd.systemd.repart.enable`.
69         '';
70       };
72       partitions = lib.mkOption {
73         type =
74           with lib.types;
75           attrsOf (
76             attrsOf (oneOf [
77               str
78               int
79               bool
80             ])
81           );
82         default = { };
83         example = {
84           "10-root" = {
85             Type = "root";
86           };
87           "20-home" = {
88             Type = "home";
89             SizeMinBytes = "512M";
90             SizeMaxBytes = "2G";
91           };
92         };
93         description = ''
94           Specify partitions as a set of the names of the definition files as the
95           key and the partition configuration as its value. The partition
96           configuration can use all upstream options. See <link
97           xlink:href="https://www.freedesktop.org/software/systemd/man/repart.d.html"/>
98           for all available options.
99         '';
100       };
101     };
102   };
104   config = lib.mkIf (cfg.enable || initrdCfg.enable) {
105     assertions = [
106       {
107         assertion = initrdCfg.enable -> config.boot.initrd.systemd.enable;
108         message = ''
109           'boot.initrd.systemd.repart.enable' requires 'boot.initrd.systemd.enable' to be enabled.
110         '';
111       }
112     ] ++ partitionAssertions;
114     # systemd-repart uses loopback devices for partition creation
115     boot.initrd.availableKernelModules = lib.optional initrdCfg.enable "loop";
117     boot.initrd.systemd = lib.mkIf initrdCfg.enable {
118       additionalUpstreamUnits = [
119         "systemd-repart.service"
120       ];
122       storePaths = [
123         "${config.boot.initrd.systemd.package}/bin/systemd-repart"
124       ];
126       contents."/etc/repart.d".source = definitionsDirectory;
128       # Override defaults in upstream unit.
129       services.systemd-repart =
130         let
131           deviceUnit = "${utils.escapeSystemdPath initrdCfg.device}.device";
132         in
133         {
134           # systemd-repart tries to create directories in /var/tmp by default to
135           # store large temporary files that benefit from persistence on disk. In
136           # the initrd, however, /var/tmp does not provide more persistence than
137           # /tmp, so we re-use it here.
138           environment."TMPDIR" = "/tmp";
139           serviceConfig = {
140             ExecStart = [
141               " " # required to unset the previous value.
142               # When running in the initrd, systemd-repart by default searches
143               # for definition files in /sysroot or /sysusr. We tell it to look
144               # in the initrd itself.
145               ''
146                 ${config.boot.initrd.systemd.package}/bin/systemd-repart \
147                                   --definitions=/etc/repart.d \
148                                   --dry-run=no ${lib.optionalString (initrdCfg.device != null) initrdCfg.device}
149               ''
150             ];
151           };
152           # systemd-repart needs to run after /sysroot (or /sysuser, but we
153           # don't have it) has been mounted because otherwise it cannot
154           # determine the device (i.e disk) to operate on. If you want to run
155           # systemd-repart without /sysroot (i.e. to create the root
156           # partition), you have to explicitly tell it which device to operate
157           # on. The service then needs to be ordered to run after this device
158           # is available.
159           requires = lib.mkIf (initrdCfg.device != null) [ deviceUnit ];
160           after = if initrdCfg.device == null then [ "sysroot.mount" ] else [ deviceUnit ];
161         };
162     };
164     environment.etc = lib.mkIf cfg.enable {
165       "repart.d".source = definitionsDirectory;
166     };
168     systemd = lib.mkIf cfg.enable {
169       additionalUpstreamSystemUnits = [
170         "systemd-repart.service"
171       ];
172     };
173   };
175   meta.maintainers = with lib.maintainers; [ nikstur ];