diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 20ec1bda2810..f70e8c292c41 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -252,6 +252,17 @@ let mv -f $1.tmp $1 ''; + idsAreUnique = set: idAttr: !(fold (name: args@{ dup, acc }: + let + id = builtins.toString (builtins.getAttr idAttr (builtins.getAttr name set)); + exists = builtins.hasAttr id acc; + newAcc = acc // (builtins.listToAttrs [ { name = id; value = true; } ]); + in if dup then args else if exists + then builtins.trace "Duplicate ${idAttr} ${id}" { dup = true; acc = null; } + else { dup = false; acc = newAcc; } + ) { dup = false; acc = {}; } (builtins.attrNames set)).dup; + uidsAreUnique = idsAreUnique cfg.extraUsers "uid"; + gidsAreUnique = idsAreUnique cfg.extraGroups "gid"; in { @@ -282,6 +293,14 @@ in ''; }; + users.enforceIdUniqueness = mkOption { + type = types.bool; + default = true; + description = '' + Whether to require that no two users/groups share the same uid/gid. + ''; + }; + users.extraUsers = mkOption { default = {}; type = types.loaOf types.optionSet; @@ -432,6 +451,8 @@ in # for backwards compatibility system.activationScripts.groups = stringAfter [ "users" ] ""; + assertions = [ { assertion = !cfg.enforceIdUniqueness || (uidsAreUnique && gidsAreUnique); message = "uids and gids must be unique!"; } ]; + }; }