Users.users move away from list

I have to rewrite some user definition for a server.
Right now the code looks like this:

let
  sshkeys = pkgs.fetchFromGitHub {
    owner = "abc";
    repo = "def";
    rev = "123";
    sha512 = "456";
  };
  getpubkeys = user: builtins.readFile "${sshkeys}/${user}.pub";
  mkuser = user: { name = user; isNormalUser = true; extraGroups = [ "wheel" ]; initialPassword = "hdsklf"; openssh.authorizedKeys.keys = [ (getpubkeys user) ]; };
  mkusers = users: map (mkuser) users;
in
{
  users.users = mkusers [ "alice" "bob" "charlie" ] ++ [
    { name = "dana"; isNormalUser = true; extraGroups = [ "wheel" ]; openssh.authorizedKeys.keys = [
      "ssh-rsa AAAA..."
    ]; }
  ];
}

This is working fine, except since 20.03 I get a message that it will be deprecated soon.
It allows me to have a simple list where users can be added to be granted access, they only have to login with their key and then can change their password.

How do I change these lines to create an attribute set instead?
I’m stuck with no idea where to begin - I’m using NixOS for quite some years now but pretty much never used functions to generate my config.

Perhaps there is a better way but my first inclination would be to use lib.genAttrs function like so:

nix-repl> let mkUser = user: { isNormalUser = true; }; in lib.genAttrs [ "alice" "bob" ] (user: mkUser user)
{ alice = { ... }; bob = { ... }; }
1 Like

Thank you, that was the help I needed. :slight_smile:
My full solution is now this:

let
  sshkeys = pkgs.fetchFromGitHub {
    owner = "abc";
    repo = "def";
    rev = "123";
    sha512 = "456";
  };
  getpubkeys = user: builtins.readFile "${sshkeys}/${user}.pub";
  mkuser = user: { name = user; isNormalUser = true; extraGroups = [ "wheel" ]; initialPassword = "hdsklf"; openssh.authorizedKeys.keys = [ (getpubkeys user) ]; };
in
{
  users.users = (lib.genAttrs [ "alice" "bob" "charlie" ] mkuser) // {
    dana = { name = "dana"; isNormalUser = true; extraGroups = [ "wheel" ]; openssh.authorizedKeys.keys = [
      "ssh-rsa AAAA..."
    ]; };
  };
}

Rebuilding the system does not even change the hash, so it results in exactly the same output as before.
Update: included @lheckemann’s suggestion

2 Likes

(user: mkuser "${user}") can be simplified to mkuser :slight_smile:

1 Like

although you’re not using it anymore, this can be simplified to mkusers = map mkuser through eta reduction.
https://wiki.haskell.org/Eta_conversion