This commit is contained in:
mjallen18
2025-08-24 18:56:51 -05:00
parent cfaf900db6
commit 2ea82a643d
22 changed files with 338 additions and 531 deletions

View File

@@ -7,6 +7,7 @@
}:
with lib;
let
inherit (lib.mjallen) mkOpt mkBoolOpt;
cfg = config.${namespace}.user;
isRoot = (cfg.name == "root");
@@ -22,79 +23,38 @@ let
# Yubikey
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCuzZfywCSde/3J1zRWH0s7OMEhHIwZeNWdKHUxMAYE/5hzFRtl5LYuNU68zxj7Aj67VF8VGwBbMEU6X/ebiNAxahmjf4mtioby5b4TIy+0Xvdbayoch938bP7UhskzobaJF6epg3vyATnJGr6i0EOXiDSkJU8vL1oeue0HN7WmwzIqxw0BTaSh6HJvjhhFhs20dBHc2x9behIfSmKFe9gBlPcIriUtpXNgasm14QCMk537dlSgGUFxPGIzZRAUSn5wqFjbiNK0rP/1MJzhGtXhHFJ8irI4TiVEk3cOm5nMoJxTP4KScfmHU+niU1Al+d0KOBsHb71AWutazRudKvsqrPsbG6vT4gGMVjOCTN9e89jcapz5GEQsVQR6s1HUjh4G+2PFbHOFmR8Mks+TIumqHIWsXgQnFBadblDRGPwrSH3zulvRzghyfTyU/bX28iGvpli2ckso5nJmG8D1LO7Y/E8U8ZGW4hC75+iP90cu9G1Ff1hETkrv6xpbNTGL61U= cardno:33_720_987"
];
defaultPasswordFile = config.sops.secrets."matt_password".path;
in
{
options.${namespace}.user = with types; {
email = lib.mkOption {
type = str;
default = "jalle008@proton.me";
description = "The email of the user.";
};
extraGroups = lib.mkOption {
type = (listOf str);
default = [ ];
description = "Groups for the user to be assigned.";
};
extraOptions = lib.mkOption {
type = attrs;
default = { };
description = "Extra options passed to <option>users.users.<name></option>.";
};
fullName = lib.mkOption {
type = str;
default = "Matt Jallen";
description = "The full name of the user.";
};
name = lib.mkOption {
type = str;
default = "matt";
description = "The name to use for the user account.";
};
passwordFile = lib.mkOption {
type = nullOr path;
default = null;
description = "Path to the password file for this user account";
};
sshKeys = lib.mkOption {
type = listOf str;
default = [ ];
description = "List of SSH public keys for the user.";
};
enableCommonSshKeys = lib.mkOption {
type = bool;
default = true;
description = "Whether to include common SSH keys used across systems.";
};
uid = lib.mkOption {
type = int;
default = if isRoot then ids.uids.root else 1000;
description = "The user ID for the user account.";
};
packages = lib.mkOption {
type = listOf package;
default = [ ];
description = "List of packages to install for this user.";
};
linger = lib.mkOption {
type = bool;
default = false;
description = "Whether to enable systemd user service persistence.";
};
password = lib.mkOption {
type = nullOr str;
default = null;
description = "Plain text password for the user (development only).";
};
hashedPassword = lib.mkOption {
type = nullOr str;
default = null;
description = "Hashed password for the user.";
};
mutableUsers = lib.mkOption {
type = bool;
default = false;
description = "Whether users are mutable (can be modified after creation).";
};
email = mkOpt str "jalle008@proton.me" "The email of the user.";
extraGroups = mkOpt (listOf str) [ ] "Groups for the user to be assigned.";
extraOptions = mkOpt attrs { } "Extra options passed to <option>users.users.<name></option>.";
fullName = mkOpt str "Matt Jallen" "The full name of the user.";
name = mkOpt str "matt" "The name to use for the user account.";
sshKeys = mkOpt (listOf str) [ ] "List of SSH public keys for the user.";
enableCommonSshKeys = mkBoolOpt true "Whether to include common SSH keys used across systems.";
uid = mkOpt int (if isRoot then ids.uids.root else 1000) "The user ID for the user account.";
packages = mkOpt (listOf package) [ ] "List of packages to install for this user.";
linger = mkBoolOpt false "Whether to enable systemd user service persistence.";
password = mkOpt (nullOr str) null "Plain text password for the user (development only).";
hashedPassword = mkOpt (nullOr str) null "Hashed password for the user.";
hashedPasswordFile = mkOpt (nullOr path) defaultPasswordFile "Path to the password file for this user account";
mutableUsers = mkBoolOpt false "Whether users are mutable (can be modified after creation).";
};
config = {
@@ -106,6 +66,9 @@ in
uid
linger
packages
password
hashedPassword
hashedPasswordFile
;
extraGroups = [
@@ -136,16 +99,26 @@ in
# SSH keys - combine user-specific and common keys
openssh.authorizedKeys.keys = cfg.sshKeys ++ (lib.optionals cfg.enableCommonSshKeys commonSshKeys);
# Authentication - priority: passwordFile > hashedPassword > password
hashedPasswordFile = lib.mkIf (cfg.passwordFile != null) cfg.passwordFile;
hashedPassword = lib.mkIf (
cfg.passwordFile == null && cfg.hashedPassword != null
) cfg.hashedPassword;
password = lib.mkIf (
cfg.passwordFile == null && cfg.hashedPassword == null && cfg.password != null
) cfg.password;
}
// cfg.extraOptions;
assertions = [
{
assertion = (cfg.password != null) || (cfg.hashedPassword != null) || (cfg.hashedPasswordFile != null);
message = "User '${cfg.name}' requires at least one password method (password, hashedPassword, or hashedPasswordFile).";
}
{
assertion =
let
passwordMethods = lib.count (x: x != null) [ cfg.password cfg.hashedPassword cfg.hashedPasswordFile ];
in
passwordMethods <= 1;
message = "User '${cfg.name}' can only use one password method at a time. Found multiple: ${lib.concatStringsSep ", " (lib.filter (x: x != null) [
(if cfg.password != null then "password" else null)
(if cfg.hashedPassword != null then "hashedPassword" else null)
(if cfg.hashedPasswordFile != null then "hashedPasswordFile" else null)
])}";
}
];
};
}