{ config, pkgs, lib, ... }: with lib; let cfg = config.services.naxos.users; in { options.services.naxos.users = { enable = mkEnableOption "NaxOS Declarative User Management"; adminUser = mkOption { type = types.str; default = "admin"; description = "Primary administrator account name."; }; adminSshKeys = mkOption { type = types.listOf types.str; default = []; description = "Public SSH keys for the administrator."; }; users = mkOption { type = types.attrsOf (types.submodule { options = { description = mkOption { type = types.str; default = ""; description = "User full name or comment."; }; isAdmin = mkOption { type = types.bool; default = false; description = "Whether the user has sudo/wheel privileges."; }; sshKeys = mkOption { type = types.listOf types.str; default = []; description = "Public SSH authorized keys."; }; extraGroups = mkOption { type = types.listOf types.str; default = []; description = "Additional Linux groups."; }; smbAccess = mkOption { type = types.bool; default = true; description = "Whether the user can access SMB shares."; }; }; }); default = {}; description = "Appliance user accounts."; }; }; config = mkIf cfg.enable { users.mutableUsers = true; # Admin user creation users.users.${cfg.adminUser} = { isNormalUser = true; description = "NaxOS Primary Administrator"; extraGroups = [ "wheel" "docker" "video" "render" "users" ]; openssh.authorizedKeys.keys = cfg.adminSshKeys; shell = pkgs.bashInteractive; }; # Additional users users.users = mapAttrs (name: ucfg: { isNormalUser = true; description = ucfg.description; extraGroups = (if ucfg.isAdmin then [ "wheel" ] else []) ++ ucfg.extraGroups ++ [ "users" ]; openssh.authorizedKeys.keys = ucfg.sshKeys; }) cfg.users; security.sudo.wheelNeedsPassword = false; }; }