summary refs log tree commit diff
path: root/nixos/modules/config
diff options
context:
space:
mode:
authoradisbladis <adisbladis@gmail.com>2020-04-28 22:30:34 +0100
committeradisbladis <adisbladis@gmail.com>2020-07-13 13:15:02 +0200
commit5733967290f19f5e1ee43ef057b9b31c647ba80d (patch)
treea75df6865c5def3e870e73f3439493cab3efb715 /nixos/modules/config
parent0963cebfc5648d267d37863047f9484edf687ce6 (diff)
downloadnixpkgs-5733967290f19f5e1ee43ef057b9b31c647ba80d.tar
nixpkgs-5733967290f19f5e1ee43ef057b9b31c647ba80d.tar.gz
nixpkgs-5733967290f19f5e1ee43ef057b9b31c647ba80d.tar.bz2
nixpkgs-5733967290f19f5e1ee43ef057b9b31c647ba80d.tar.lz
nixpkgs-5733967290f19f5e1ee43ef057b9b31c647ba80d.tar.xz
nixpkgs-5733967290f19f5e1ee43ef057b9b31c647ba80d.tar.zst
nixpkgs-5733967290f19f5e1ee43ef057b9b31c647ba80d.zip
nixos.users-groups: Set up subuid/subgid mappings for all normal users
This is required by (among others) Podman to run containers in rootless mode.

Other distributions such as Fedora and Ubuntu already set up these mappings.

The scheme with a start UID/GID offset starting at 100000 and increasing in 65536 increments is copied from Fedora.
Diffstat (limited to 'nixos/modules/config')
-rw-r--r--nixos/modules/config/update-users-groups.pl55
-rw-r--r--nixos/modules/config/users-groups.nix24
2 files changed, 57 insertions, 22 deletions
diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl
index 15e448b787a..e1c7a46e430 100644
--- a/nixos/modules/config/update-users-groups.pl
+++ b/nixos/modules/config/update-users-groups.pl
@@ -281,3 +281,58 @@ foreach my $u (values %usersOut) {
 }
 
 updateFile("/etc/shadow", \@shadowNew, 0600);
+
+# Rewrite /etc/subuid & /etc/subgid to include default container mappings
+
+my $subUidMapFile = "/var/lib/nixos/auto-subuid-map";
+my $subUidMap = -e $subUidMapFile ? decode_json(read_file($subUidMapFile)) : {};
+
+my (%subUidsUsed, %subUidsPrevUsed);
+
+$subUidsPrevUsed{$_} = 1 foreach values %{$subUidMap};
+
+sub allocSubUid {
+    my ($name, @rest) = @_;
+
+    # TODO: No upper bounds?
+    my ($min, $max, $up) = (100000, 100000 * 100, 1);
+    my $prevId = $subUidMap->{$name};
+    if (defined $prevId && !defined $subUidsUsed{$prevId}) {
+        $subUidsUsed{$prevId} = 1;
+        return $prevId;
+    }
+
+    my $id = allocId(\%subUidsUsed, \%subUidsPrevUsed, $min, $max, $up, sub { my ($uid) = @_; getpwuid($uid) });
+    my $offset = $id - 100000;
+    my $count = $offset * 65536;
+    my $subordinate = 100000 + $count;
+    return $subordinate;
+}
+
+my @subGids;
+my @subUids;
+foreach my $u (values %usersOut) {
+    my $name = $u->{name};
+
+    foreach my $range (@{$u->{subUidRanges}}) {
+        my $value = join(":", ($name, $range->{startUid}, $range->{count}));
+        push @subUids, $value;
+    }
+
+    foreach my $range (@{$u->{subGidRanges}}) {
+        my $value = join(":", ($name, $range->{startGid}, $range->{count}));
+        push @subGids, $value;
+    }
+
+    if($u->{isNormalUser}) {
+        my $subordinate = allocSubUid($name);
+        $subUidMap->{$name} = $subordinate;
+        my $value = join(":", ($name, $subordinate, 65536));
+        push @subUids, $value;
+        push @subGids, $value;
+    }
+}
+
+updateFile("/etc/subuid", join("\n", @subUids) . "\n");
+updateFile("/etc/subgid", join("\n", @subGids) . "\n");
+updateFile($subUidMapFile, encode_json($subUidMap) . "\n");
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 7e5f3582ae8..ee64f785f5b 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -375,18 +375,6 @@ let
     };
   };
 
-  mkSubuidEntry = user: concatStrings (
-    map (range: "${user.name}:${toString range.startUid}:${toString range.count}\n")
-      user.subUidRanges);
-
-  subuidFile = concatStrings (map mkSubuidEntry (attrValues cfg.users));
-
-  mkSubgidEntry = user: concatStrings (
-    map (range: "${user.name}:${toString range.startGid}:${toString range.count}\n")
-        user.subGidRanges);
-
-  subgidFile = concatStrings (map mkSubgidEntry (attrValues cfg.users));
-
   idsAreUnique = set: idAttr: !(fold (name: args@{ dup, acc }:
     let
       id = builtins.toString (builtins.getAttr idAttr (builtins.getAttr name set));
@@ -406,6 +394,7 @@ let
       { inherit (u)
           name uid group description home createHome isSystemUser
           password passwordFile hashedPassword
+          isNormalUser subUidRanges subGidRanges
           initialPassword initialHashedPassword;
         shell = utils.toShellPath u.shell;
       }) cfg.users;
@@ -567,16 +556,7 @@ in {
     # Install all the user shells
     environment.systemPackages = systemShells;
 
-    environment.etc = {
-      subuid = {
-        text = subuidFile;
-        mode = "0644";
-      };
-      subgid = {
-        text = subgidFile;
-        mode = "0644";
-      };
-    } // (mapAttrs' (name: { packages, ... }: {
+    environment.etc = (mapAttrs' (name: { packages, ... }: {
       name = "profiles/per-user/${name}";
       value.source = pkgs.buildEnv {
         name = "user-environment";