From 6f23a456963c2fd11a8ad1a64457be86c2ffa1d5 Mon Sep 17 00:00:00 2001
From: Daniel Barlow <dan@telent.net>
Date: Wed, 28 Sep 2022 21:31:15 +0100
Subject: [PATCH] configuration for users and groups

---
 default.nix       |  1 +
 modules/base.nix  | 19 +++++++++++++++++--
 modules/users.nix | 26 ++++++++++++++++++++++++++
 3 files changed, 44 insertions(+), 2 deletions(-)
 create mode 100644 modules/users.nix

diff --git a/default.nix b/default.nix
index 7a105478e..7ff623e6e 100644
--- a/default.nix
+++ b/default.nix
@@ -10,6 +10,7 @@ let
     ({ lib, ... } : { config = { inherit (device) kernel; }; })
     <liminix-config>
     ./modules/s6
+    ./modules/users.nix
   ] nixpkgs.pkgs;
   squashfs = liminix.builders.squashfs config.filesystem.contents;
   kernel = callPackage ./kernel {
diff --git a/modules/base.nix b/modules/base.nix
index e3d7f2e17..e13703944 100644
--- a/modules/base.nix
+++ b/modules/base.nix
@@ -33,10 +33,27 @@ in {
         type = types.attrsOf types.nonEmptyStr;
       };
     };
+    groups =  mkOption {
+      type = types.attrsOf types.anything;
+    };
+    users =  mkOption {
+      type = types.attrsOf types.anything;
+    };
   };
   config = {
     defaultProfile.packages = with pkgs;
       [ s6-init-bin busybox execline s6-linux-init s6-rc ];
+
+    users.root = {
+      uid = 0; gid= 0; gecos = "Root of all evaluation";
+      dir = "/";
+      passwd = "";
+      shell = "/bin/sh";
+    };
+    groups.root = {
+      gid = 0; usernames = ["root"];
+    };
+
     filesystem = dir {
       bin = dir {
         sh = symlink "${busybox}/bin/sh";
@@ -57,8 +74,6 @@ in {
             PATH=${lib.makeBinPath config.defaultProfile.packages}
             export PATH
           '');
-        passwd = { file = "root::0:0:root:/:/bin/sh\n"; };
-        group = { file = "root::0:\n"; };
       };
       proc = dir {};
       run = dir {};
diff --git a/modules/users.nix b/modules/users.nix
new file mode 100644
index 000000000..63edb2a0c
--- /dev/null
+++ b/modules/users.nix
@@ -0,0 +1,26 @@
+{ lib, pkgs, config, ...}:
+let
+  inherit (lib) concatStrings concatStringsSep mapAttrsToList; # mkEnableOption mkOption types isDerivation isType hasAttr ;
+  inherit (builtins) toString;
+  inherit (pkgs.pseudofile) dir symlink;
+#  inherit (pkgs) busybox;
+  passwd-file  =
+    let lines =  mapAttrsToList (name: u: "${name}:${if u ? passwd  then u.passwd else "!!"}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n" )
+      config.users;
+    in concatStrings lines;
+  group-file =
+    let lines = mapAttrsToList
+      (name: {gid, usernames ? []}:
+        "${name}:x:${toString gid}:${concatStringsSep "," usernames}\n" )
+      config.groups;
+    in concatStrings lines;
+in {
+  config = {
+    filesystem = dir {
+      etc = dir {
+        passwd = { file = passwd-file; };
+        group = { file = group-file; };
+      };
+    };
+  };
+}