systemd-initrd: Add users and groups with static IDs.

Changed files
+94 -1
nixos
modules
config
system
boot
systemd
tests
+92
nixos/modules/config/users-groups.nix
···
uidsAreUnique = idsAreUnique (filterAttrs (n: u: u.uid != null) cfg.users) "uid";
gidsAreUnique = idsAreUnique (filterAttrs (n: g: g.gid != null) cfg.groups) "gid";
+
sdInitrdUidsAreUnique = idsAreUnique (filterAttrs (n: u: u.uid != null) config.boot.initrd.systemd.users) "uid";
+
sdInitrdGidsAreUnique = idsAreUnique (filterAttrs (n: g: g.gid != null) config.boot.initrd.systemd.groups) "gid";
spec = pkgs.writeText "users-groups.json" (builtins.toJSON {
inherit (cfg) mutableUsers;
···
WARNING: enabling this can lock you out of your system. Enable this only if you know what are you doing.
'';
};
+
+
# systemd initrd
+
boot.initrd.systemd.users = mkOption {
+
visible = false;
+
description = ''
+
Users to include in initrd.
+
'';
+
default = {};
+
type = types.attrsOf (types.submodule ({ name, ... }: {
+
options.uid = mkOption {
+
visible = false;
+
type = types.int;
+
description = ''
+
ID of the user in initrd.
+
'';
+
defaultText = literalExpression "config.users.users.\${name}.uid";
+
default = cfg.users.${name}.uid;
+
};
+
options.group = mkOption {
+
visible = false;
+
type = types.singleLineStr;
+
description = ''
+
Group the user belongs to in initrd.
+
'';
+
defaultText = literalExpression "config.users.users.\${name}.group";
+
default = cfg.users.${name}.group;
+
};
+
}));
+
};
+
+
boot.initrd.systemd.groups = mkOption {
+
visible = false;
+
description = ''
+
Groups to include in initrd.
+
'';
+
default = {};
+
type = types.attrsOf (types.submodule ({ name, ... }: {
+
options.gid = mkOption {
+
visible = false;
+
type = types.int;
+
description = ''
+
ID of the group in initrd.
+
'';
+
defaultText = literalExpression "config.users.groups.\${name}.gid";
+
default = cfg.groups.${name}.gid;
+
};
+
}));
+
};
};
···
"/etc/profiles/per-user/$USER"
];
+
# systemd initrd
+
boot.initrd.systemd = lib.mkIf config.boot.initrd.systemd.enable {
+
contents = {
+
"/etc/passwd".text = ''
+
${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: { uid, group }: let
+
g = config.boot.initrd.systemd.groups.${group};
+
in "${n}:x:${toString uid}:${toString g.gid}::/var/empty:") config.boot.initrd.systemd.users)}
+
'';
+
"/etc/group".text = ''
+
${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: { gid }: "${n}:x:${toString gid}:") config.boot.initrd.systemd.groups)}
+
'';
+
};
+
+
users = {
+
root = {};
+
nobody = {};
+
};
+
+
groups = {
+
root = {};
+
nogroup = {};
+
systemd-journal = {};
+
tty = {};
+
dialout = {};
+
kmem = {};
+
input = {};
+
video = {};
+
render = {};
+
sgx = {};
+
audio = {};
+
video = {};
+
lp = {};
+
disk = {};
+
cdrom = {};
+
tape = {};
+
kvm = {};
+
};
+
};
+
assertions = [
{ assertion = !cfg.enforceIdUniqueness || (uidsAreUnique && gidsAreUnique);
message = "UIDs and GIDs must be unique!";
+
}
+
{ assertion = !cfg.enforceIdUniqueness || (sdInitrdUidsAreUnique && sdInitrdGidsAreUnique);
+
message = "systemd initrd UIDs and GIDs must be unique!";
}
{ # If mutableUsers is false, to prevent users creating a
# configuration that locks them out of the system, ensure that
-1
nixos/modules/system/boot/systemd/initrd.nix
···
"/etc/modules-load.d/nixos.conf".text = concatStringsSep "\n" config.boot.initrd.kernelModules;
-
"/etc/passwd".source = "${pkgs.fakeNss}/etc/passwd";
# We can use either ! or * to lock the root account in the
# console, but some software like OpenSSH won't even allow you
# to log in with an SSH key if you use ! so we use * instead
+2
nixos/tests/systemd-initrd-simple.nix
···
machine.succeed("[ -e /dev/pts/ptmx ]") # /dev/pts
machine.succeed("[ -e /run/keys ]") # /run/keys
+
with subtest("groups work"):
+
machine.fail("journalctl -b 0 | grep 'systemd-udevd.*Unknown group.*ignoring'")
with subtest("growfs works"):
oldAvail = machine.succeed("df --output=avail / | sed 1d")