nixpkgs/nixos/modules/system/etc/etc-activation.nix
nikstur d820fe987e nixos/etc: wantedBy -> requiredBy for mounting overlay etc
I've observed that sometimes the overlay mount unit does not get started
when using wantedBy. requiredBy makes this relationship stricter and if
necessary will restart the initrd-fs.target and thus ensure that when
this target is reached /etc has alredy been mounted. This is in line
with the description of initrd-fs.target in systemd.special:

> Thus, once this target is reached the /sysroot/ hierarchy is fully set up
2024-08-22 12:12:18 +02:00

97 lines
3.1 KiB
Nix

{ config, lib, ... }:
{
imports = [ ./etc.nix ];
config = lib.mkMerge [
{
system.activationScripts.etc =
lib.stringAfter [ "users" "groups" ] config.system.build.etcActivationCommands;
}
(lib.mkIf config.system.etc.overlay.enable {
assertions = [
{
assertion = config.boot.initrd.systemd.enable;
message = "`system.etc.overlay.enable` requires `boot.initrd.systemd.enable`";
}
{
assertion = (!config.system.etc.overlay.mutable) -> config.systemd.sysusers.enable;
message = "`system.etc.overlay.mutable = false` requires `systemd.sysusers.enable`";
}
{
assertion = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.6";
message = "`system.etc.overlay.enable requires a newer kernel, at least version 6.6";
}
{
assertion = config.systemd.sysusers.enable -> (config.users.mutableUsers == config.system.etc.overlay.mutable);
message = ''
When using systemd-sysusers and mounting `/etc` via an overlay, users
can only be mutable when `/etc` is mutable and vice versa.
'';
}
];
boot.initrd.availableKernelModules = [ "loop" "erofs" "overlay" ];
boot.initrd.systemd = {
mounts = [
{
where = "/run/etc-metadata";
what = "/sysroot${config.system.build.etcMetadataImage}";
type = "erofs";
options = "loop";
unitConfig.RequiresMountsFor = [
"/sysroot/nix/store"
];
}
{
where = "/sysroot/etc";
what = "overlay";
type = "overlay";
options = lib.concatStringsSep "," ([
"relatime"
"redirect_dir=on"
"metacopy=on"
"lowerdir=/run/etc-metadata::/sysroot${config.system.build.etcBasedir}"
] ++ lib.optionals config.system.etc.overlay.mutable [
"rw"
"upperdir=/sysroot/.rw-etc/upper"
"workdir=/sysroot/.rw-etc/work"
] ++ lib.optionals (!config.system.etc.overlay.mutable) [
"ro"
]);
requiredBy = [ "initrd-fs.target" ];
before = [ "initrd-fs.target" ];
requires = lib.mkIf config.system.etc.overlay.mutable [ "rw-etc.service" ];
after = lib.mkIf config.system.etc.overlay.mutable [ "rw-etc.service" ];
unitConfig.RequiresMountsFor = [
"/sysroot/nix/store"
"/run/etc-metadata"
];
}
];
services = lib.mkIf config.system.etc.overlay.mutable {
rw-etc = {
unitConfig = {
DefaultDependencies = false;
RequiresMountsFor = "/sysroot";
};
serviceConfig = {
Type = "oneshot";
ExecStart = ''
/bin/mkdir -p -m 0755 /sysroot/.rw-etc/upper /sysroot/.rw-etc/work
'';
};
};
};
};
})
];
}