156 lines
5.4 KiB
Nix
156 lines
5.4 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
{
|
|
|
|
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 || config.services.userborn.enable);
|
|
message = "`!system.etc.overlay.mutable` requires `systemd.sysusers.enable` or `services.userborn.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";
|
|
}
|
|
];
|
|
|
|
boot.initrd.availableKernelModules = [ "loop" "erofs" "overlay" ];
|
|
|
|
boot.initrd.systemd = {
|
|
mounts = [
|
|
{
|
|
where = "/run/etc-metadata";
|
|
what = "/etc-metadata-image";
|
|
type = "erofs";
|
|
options = "loop";
|
|
unitConfig = {
|
|
# Since this unit depends on the nix store being mounted, it cannot
|
|
# be a dependency of local-fs.target, because if it did, we'd have
|
|
# local-fs.target ordered after the nix store mount which would cause
|
|
# things like network.target to only become active after the nix store
|
|
# has been mounted.
|
|
# This breaks for instance setups where sshd needs to be up before
|
|
# any encrypted disks can be mounted.
|
|
DefaultDependencies = false;
|
|
RequiresMountsFor = [
|
|
"/sysroot/nix/store"
|
|
];
|
|
};
|
|
requires = [
|
|
config.boot.initrd.systemd.services.initrd-find-etc.name
|
|
];
|
|
after = [
|
|
config.boot.initrd.systemd.services.initrd-find-etc.name
|
|
];
|
|
requiredBy = [ "initrd-fs.target" ];
|
|
before = [ "initrd-fs.target" ];
|
|
}
|
|
{
|
|
where = "/sysroot/etc";
|
|
what = "overlay";
|
|
type = "overlay";
|
|
options = lib.concatStringsSep "," ([
|
|
"relatime"
|
|
"redirect_dir=on"
|
|
"metacopy=on"
|
|
"lowerdir=/run/etc-metadata::/etc-basedir"
|
|
] ++ 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 = [
|
|
config.boot.initrd.systemd.services.initrd-find-etc.name
|
|
] ++ lib.optionals config.system.etc.overlay.mutable [
|
|
config.boot.initrd.systemd.services."rw-etc".name
|
|
];
|
|
after = [
|
|
config.boot.initrd.systemd.services.initrd-find-etc.name
|
|
] ++ lib.optionals config.system.etc.overlay.mutable [
|
|
config.boot.initrd.systemd.services."rw-etc".name
|
|
];
|
|
unitConfig = {
|
|
RequiresMountsFor = [
|
|
"/sysroot/nix/store"
|
|
"/run/etc-metadata"
|
|
];
|
|
DefaultDependencies = false;
|
|
};
|
|
}
|
|
];
|
|
services = lib.mkMerge [
|
|
(lib.mkIf config.system.etc.overlay.mutable {
|
|
rw-etc = {
|
|
requiredBy = [ "initrd-fs.target" ];
|
|
before = [ "initrd-fs.target" ];
|
|
unitConfig = {
|
|
DefaultDependencies = false;
|
|
RequiresMountsFor = "/sysroot";
|
|
};
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStart = ''
|
|
/bin/mkdir -p -m 0755 /sysroot/.rw-etc/upper /sysroot/.rw-etc/work
|
|
'';
|
|
};
|
|
};
|
|
})
|
|
{
|
|
initrd-find-etc = {
|
|
description = "Find the path to the etc metadata image and based dir";
|
|
requires = [
|
|
config.boot.initrd.systemd.services.initrd-find-nixos-closure.name
|
|
];
|
|
after = [
|
|
config.boot.initrd.systemd.services.initrd-find-nixos-closure.name
|
|
];
|
|
before = [ "shutdown.target" ];
|
|
conflicts = [ "shutdown.target" ];
|
|
requiredBy = [ "initrd.target" ];
|
|
unitConfig = {
|
|
DefaultDependencies = false;
|
|
RequiresMountsFor = "/sysroot/nix/store";
|
|
};
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
};
|
|
|
|
script = /* bash */ ''
|
|
set -uo pipefail
|
|
|
|
closure="$(realpath /nixos-closure)"
|
|
|
|
metadata_image="$(${pkgs.chroot-realpath}/bin/chroot-realpath /sysroot "$closure/etc-metadata-image")"
|
|
ln -s "/sysroot$metadata_image" /etc-metadata-image
|
|
|
|
basedir="$(${pkgs.chroot-realpath}/bin/chroot-realpath /sysroot "$closure/etc-basedir")"
|
|
ln -s "/sysroot$basedir" /etc-basedir
|
|
'';
|
|
};
|
|
}
|
|
];
|
|
};
|
|
|
|
})
|
|
|
|
];
|
|
}
|