users

*An instance of this module will create a user account on the added machines, along with a generated password that is constant across machines and user settings. Optionally exports identity metadata (email, groups) via the auth export type for consumption by IdP clan services (Authelia, Kanidm, etc.). *

System

Usage

{
  inventory.instances = {
    # Deploy user alice on all machines. Don't prompt for password (will be
    # auto-generated).
    user-alice = {
      module = {
        name = "users";
        input = "clan-core";
      };
      roles.default.tags = [ "all" ];
      roles.default.settings = {
        user = "alice";
        prompt = false;
      };
    };

    # Deploy user Carol on all machines. Prompt only once and use the
    # same password on all machines. (`share = true`)
    user-carol = {
      module = {
        name = "users";
        input = "clan-core";
      };
      roles.default.tags = [ "all" ];
      roles.default.settings = {
        user = "carol";
        share = true;
        openssh.authorizedKeys.keys = [
          "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ..."
        ];
      };
    };

    # Deploy user bob only on his laptop. Prompt for a password.
    user-bob = {
      module = {
        name = "users";
        input = "clan-core";
      };
      roles.default.machines.bobs-laptop = { };
      roles.default.settings.user = "bob";
    };
  };
}

Integrating home-manager

home-manager manages user-specific dotfiles and packages. You can integrate it with the users service via extraModules.

First, add home-manager to your flake inputs:

{
  inputs = {
    # ... existing inputs
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };
}

Then use extraModules to attach home-manager configuration to a user:

{
  inventory.instances = {
    alice-user = {
      module.name = "users";
      roles.default.tags = [ "all" ];
      roles.default.settings = {
        user = "alice";
        groups = [
          "wheel"
          "networkmanager"
        ];
      };
      roles.default.extraModules = [ ./users/alice/home.nix ];
    };
  };
}
# users/alice/home.nix
{ self, ... }:
{
  imports = [ self.inputs.home-manager.nixosModules.default ];

  home-manager.users.alice = {
    home.stateVersion = "24.05";

    programs.git = {
      enable = true;
      userName = "Alice";
      userEmail = "alice@example.com";
    };

    # Add more home-manager configuration here
  };
}

The extraModules option accepts paths to NixOS modules. These modules are added to every machine that has this user.

Migration from root-password module

The deprecated clan.root-password module has been replaced by the users module. Here's how to migrate:

1. Update your flake configuration

Replace the root-password module import with a users service instance:

# OLD - Remove this from your nixosModules:
imports = [
  self.inputs.clan-core.clanModules.root-password
];

# NEW - Add to inventory.instances or machines/flake-module.nix:
instances = {
  users-root = {
    module.name = "users";
    module.input = "clan-core";
    roles.default.tags = [ "nixos" ];
    roles.default.settings = {
      user = "root";
      prompt = false;  # Set to true if you want to be prompted
      groups = [ ];
    };
  };
};

2. Migrate vars

The vars structure has changed from root-password to user-password-root:

# For each machine, rename the vars directories:
cd vars/per-machine/<machine-name>/
mv root-password user-password-root
mv user-password-root/password-hash user-password-root/user-password-hash
mv user-password-root/password user-password-root/user-password

Roles

The users service has the following roles:

  • default

Options for the default role

groups

Additional groups the user should be added to. You can add any group that exists on your system. Make sure these group exists on all machines where the user is enabled.

Commonly used groups:

  • "wheel" - Allows the user to run commands as root using sudo.
  • "networkmanager" - Allows the user to manage network connections.
  • "video" - Allows the user to access video devices.
  • "input" - Allows the user to access input devices.

Type: list of string

Default:

[ ]
Example
[
  "wheel"
  "networkmanager"
  "video"
  "input"
]

Declared in: clanServices/users/default.nix

identity

IdP identities keyed by IdP instance name. Each entry creates a user account in the corresponding IdP clan service. Example: identity.main = { groups = [ "users" ]; } creates an account in the IdP instance named "main" in inventory.

Type: attribute set of (submodule)

Default:

{ }
Example
{
  main = {
    email = "alice@example.com";
    groups = [ "admins" "users" ];
  };
}

Declared in: clanServices/users/default.nix

identity.<name>.displayname

Display name. Defaults to the username.

Type: null or string

Default:

null

Declared in: clanServices/users/default.nix

identity.<name>.email

Email for this IdP account. Defaults to @mail.<meta.domain>.

Type: string

Default:

""
Example
"alice@example.com"

Declared in: clanServices/users/default.nix

identity.<name>.groups

IdP-level groups. Control OIDC client access policies (e.g. "miniflux-users" gates miniflux access).

Type: list of string

Default:

[ ]
Example
[
  "admins"
  "users"
]

Declared in: clanServices/users/default.nix

openssh.authorizedKeys.keyFiles

A list of files each containing one OpenSSH public key that should be added to the user's authorized keys. The contents of the files are read at build time and added to a file that the SSH daemon reads in addition to the the user's authorized_keys file. You can combine the keyFiles and keys options.

Type: list of absolute path

Default:

[ ]

Declared in: clanServices/users/default.nix

openssh.authorizedKeys.keys

A list of verbatim OpenSSH public keys that should be added to the user's authorized keys. The keys are added to a file that the SSH daemon reads in addition to the the user's authorized_keys file.

Type: list of (optionally newline-terminated) single-line string

Default:

[ ]
Example
[
  "ssh-rsa AAAAB3NzaC1yc2etc/etc/etcjwrsh8e596z6J0l7 example@host"
  "ssh-ed25519 AAAAC3NzaCetcetera/etceteraJZMfk3QPfQ foo@bar"
]

Declared in: clanServices/users/default.nix

prompt

Whether the user should be prompted for a password.

Effects:

  • enabled (true) - Prompt for a password during the machine installation or update workflow.
  • disabled (false) - Generate a password during the machine installation or update workflow.

The password can be shown in two steps:

  • clan vars list <machine-name>
  • clan vars get <machine-name> <name-of-password-variable>

Type: boolean

Default:

true
Example
false

Declared in: clanServices/users/default.nix

share

Weather the user should have the same password on all machines.

By default, you will be prompted for a new password for every host. Unless generate is set to true.

Type: boolean

Default:

false
Example
true

Declared in: clanServices/users/default.nix

systemUser

Whether to create a Unix system account for this user.

Set to false for identity-only users who should exist in the IdP (Authelia, Kanidm, etc.) but have no shell access on any machine. The auth.user identity export still flows when identity.email is set, regardless of this flag.

Type: boolean

Default:

true

Declared in: clanServices/users/default.nix

user

The username for this account.

Type: string

Default:

"$'{instanceName}"
Example
"alice"

Declared in: clanServices/users/default.nix