diff options
Diffstat (limited to 'nixos/modules/config/users-groups.nix')
-rw-r--r-- | nixos/modules/config/users-groups.nix | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index afedc8e382e5..d172ddb6bca7 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -109,6 +109,36 @@ let description = "The path to the user's shell."; }; + subUidRanges = mkOption { + type = types.listOf types.optionSet; + default = []; + example = [ + { startUid = 1000; count = 1; } + { startUid = 100001; count = 65534; } + ]; + options = [ subordinateUidRange ]; + description = '' + Subordinate user ids that user is allowed to use. + They are set into <filename>/etc/subuid</filename> and are used + by <literal>newuidmap</literal> for user namespaces. + ''; + }; + + subGidRanges = mkOption { + type = types.listOf types.optionSet; + default = []; + example = [ + { startGid = 100; count = 1; } + { startGid = 1001; count = 999; } + ]; + options = [ subordinateGidRange ]; + description = '' + Subordinate group ids that user is allowed to use. + They are set into <filename>/etc/subgid</filename> and are used + by <literal>newgidmap</literal> for user namespaces. + ''; + }; + createHome = mkOption { type = types.bool; default = false; @@ -216,6 +246,54 @@ let }; + subordinateUidRange = { + startUid = mkOption { + type = types.int; + description = '' + Start of the range of subordinate user ids that user is + allowed to use. + ''; + }; + count = mkOption { + type = types.int; + default = 1; + description = ''Count of subordinate user ids''; + }; + }; + + subordinateGidRange = { + startGid = mkOption { + type = types.int; + description = '' + Start of the range of subordinate group ids that user is + allowed to use. + ''; + }; + count = mkOption { + type = types.int; + default = 1; + description = ''Count of subordinate group ids''; + }; + }; + + filterNull = a: filter (x: hasAttr a x && getAttr a x != null); + + sortOn "gid" (filterNull "gid" (attrValues cfg.extraGroups)) + sortOn "uid" (filterNull "uid" (attrValues cfg.extraUsers)) + mkSubuidEntry = user: concatStrings ( + map (range: "${user.name}:${toString range.startUid}:${toString range.count}\n") + user.subUidRanges); + + subuidFile = concatStrings (map mkSubuidEntry ( + sortOn "uid" (filterNull "uid" (attrValues cfg.extraUsers)))); + + mkSubgidEntry = user: concatStrings ( + map (range: "${user.name}:${toString range.startGid}:${toString range.count}\n") + user.subGidRanges); + + subgidFile = concatStrings (map mkSubgidEntry ( + sortOn "uid" (filterNull "uid" (attrValues cfg.extraUsers)))); + idsAreUnique = set: idAttr: !(fold (name: args@{ dup, acc }: let id = builtins.toString (builtins.getAttr idAttr (builtins.getAttr name set)); @@ -391,6 +469,15 @@ in { # for backwards compatibility system.activationScripts.groups = stringAfter [ "users" ] ""; + environment.etc."subuid" = { + text = subuidFile; + mode = "0644"; + }; + environment.etc."subgid" = { + text = subgidFile; + mode = "0644"; + }; + assertions = [ { assertion = !cfg.enforceIdUniqueness || (uidsAreUnique && gidsAreUnique); message = "UIDs and GIDs must be unique!"; |