nixos/systemd-repart: definition files in initrd

Store the definition files in the initrd instead of reading them from
the Nix store in /sysroot.

This way, the initrd has to be re-generated every time the definition
files change. When the path to the defintion files instead of the
definition files themselves are embedded in the initrd, however, the
initrd also has to be re-generated every time. In this regard, this
change does not improve the status quo.

However, now systemd-repart also works reliable when the Nix store is
mounted separately from the root partition.

This change also enables new use-cases like creating partitions
necessary to boot the system. However, by default, the root partition
cannot be created on first boot because the systemd-repart service
requires a /sysroot to be mounted. Otherwise, systemd-repart cannot
determine the device to operate on.
This commit is contained in:
nikstur 2023-05-09 00:11:21 +02:00
parent 5c2a7490cf
commit d85abd2764

View file

@ -72,11 +72,6 @@ in
};
config = lib.mkIf (cfg.enable || initrdCfg.enable) {
# Always link the definitions into /etc so that they are also included in
# the /nix/store of the sysroot during early userspace (i.e. while in the
# initrd).
environment.etc."repart.d".source = definitionsDirectory;
boot.initrd.systemd = lib.mkIf initrdCfg.enable {
additionalUpstreamUnits = [
"systemd-repart.service"
@ -86,6 +81,8 @@ in
"${config.boot.initrd.systemd.package}/bin/systemd-repart"
];
contents."/etc/repart.d".source = definitionsDirectory;
# Override defaults in upstream unit.
services.systemd-repart = {
# systemd-repart tries to create directories in /var/tmp by default to
@ -93,31 +90,31 @@ in
# the initrd, however, /var/tmp does not provide more persistence than
# /tmp, so we re-use it here.
environment."TMPDIR" = "/tmp";
# Unset the conditions as they cannot be met before activation because
# the definition files are not stored in the expected locations.
unitConfig.ConditionDirectoryNotEmpty = [
" " # required to unset the previous value.
];
serviceConfig = {
# systemd-repart runs before the activation script. Thus we cannot
# rely on them being linked in /etc already. Instead we have to
# explicitly pass their location in the sysroot to the binary.
ExecStart = [
" " # required to unset the previous value.
# When running in the initrd, systemd-repart by default searches
# for definition files in /sysroot or /sysusr. We tell it to look
# in the initrd itself.
''${config.boot.initrd.systemd.package}/bin/systemd-repart \
--definitions=/sysroot${definitionsDirectory} \
--definitions=/etc/repart.d \
--dry-run=no
''
];
};
# Because the initrd does not have the `initrd-usr-fs.target` the
# upestream unit runs too early in the boot process, before the sysroot
# is available. However, systemd-repart needs access to the sysroot to
# find the definition files.
# systemd-repart needs to run after /sysroot (or /sysuser, but we don't
# have it) has been mounted because otherwise it cannot determine the
# device (i.e disk) to operate on. If you want to run systemd-repart
# without /sysroot, you have to explicitly tell it which device to
# operate on.
after = [ "sysroot.mount" ];
};
};
environment.etc = lib.mkIf cfg.enable {
"repart.d".source = definitionsDirectory;
};
systemd = lib.mkIf cfg.enable {
additionalUpstreamSystemUnits = [
"systemd-repart.service"