196 lines
6.2 KiB
Nix
196 lines
6.2 KiB
Nix
{
|
|
pkgs,
|
|
config,
|
|
lib,
|
|
inputs,
|
|
...
|
|
}:
|
|
|
|
# ============================================================================
|
|
# User Configuration Module
|
|
# ============================================================================
|
|
# This module defines the schema for user accounts and handles their creation.
|
|
# It bridges the gap between the data in 'users.nix' and the actual NixOS
|
|
# and Home Manager configuration.
|
|
|
|
let
|
|
# Submodule defining the structure of a user account
|
|
userSubmodule = lib.types.submodule {
|
|
options = {
|
|
isNormalUser = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
description = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
};
|
|
extraGroups = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
};
|
|
hashedPassword = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "!";
|
|
};
|
|
extraPackages = lib.mkOption {
|
|
type = lib.types.listOf lib.types.package;
|
|
default = [ ];
|
|
};
|
|
excludePackages = lib.mkOption {
|
|
type = lib.types.listOf lib.types.package;
|
|
default = [ ];
|
|
};
|
|
homePackages = lib.mkOption {
|
|
type = lib.types.listOf lib.types.package;
|
|
default = [ ];
|
|
};
|
|
extraImports = lib.mkOption {
|
|
type = lib.types.listOf lib.types.path;
|
|
default = [ ];
|
|
};
|
|
home = lib.mkOption {
|
|
type = lib.types.nullOr (
|
|
lib.types.oneOf [
|
|
lib.types.path
|
|
lib.types.package
|
|
lib.types.attrs
|
|
]
|
|
);
|
|
default = null;
|
|
description = ''
|
|
External home-manager configuration. Can be:
|
|
- A path to a local module
|
|
- A fetchGit/fetchTarball result pointing to a repository
|
|
- An attribute set with home-manager configuration
|
|
Example: builtins.fetchGit { url = "https://github.com/user/dotfiles"; rev = "..."; }
|
|
'';
|
|
};
|
|
opensshKeys = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "List of SSH public keys for the user.";
|
|
};
|
|
shell = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.package;
|
|
default = null;
|
|
description = "The shell for this user.";
|
|
};
|
|
editor = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.package;
|
|
default = null;
|
|
description = "The default editor for this user.";
|
|
};
|
|
useZshTheme = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Whether to apply the system Zsh theme.";
|
|
};
|
|
useNvimPlugins = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Whether to apply the system Neovim configuration.";
|
|
};
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Whether this user account is enabled on this system.";
|
|
};
|
|
};
|
|
};
|
|
in
|
|
{
|
|
options.ugaif.users = lib.mkOption {
|
|
type = lib.types.attrsOf userSubmodule;
|
|
default = { };
|
|
description = "User accounts configuration. Set enable=true for users that should exist on this system.";
|
|
};
|
|
|
|
config = {
|
|
# Generate NixOS users
|
|
users.users =
|
|
let
|
|
enabledAccounts = lib.filterAttrs (_: user: user.enable) config.ugaif.users;
|
|
in
|
|
lib.mapAttrs (
|
|
name: user:
|
|
let
|
|
isPlasma6 = config.services.desktopManager.plasma6.enable;
|
|
defaultPackages = lib.optionals (isPlasma6 && name != "root") [ pkgs.kdePackages.kate ];
|
|
finalPackages = lib.subtractLists user.excludePackages (defaultPackages ++ user.extraPackages);
|
|
in
|
|
{
|
|
inherit (user) isNormalUser extraGroups hashedPassword;
|
|
description = if user.description != null then user.description else lib.mkDefault "";
|
|
openssh.authorizedKeys.keys = user.opensshKeys;
|
|
packages = finalPackages;
|
|
shell = if user.shell != null then user.shell else pkgs.bash;
|
|
}
|
|
) enabledAccounts;
|
|
|
|
# Home Manager configs per user
|
|
home-manager = {
|
|
useGlobalPkgs = true;
|
|
useUserPackages = true;
|
|
extraSpecialArgs = {
|
|
osConfig = config;
|
|
inherit inputs;
|
|
};
|
|
|
|
users =
|
|
let
|
|
enabledAccounts = lib.filterAttrs (_: user: user.enable) config.ugaif.users;
|
|
in
|
|
lib.mapAttrs (
|
|
name: user:
|
|
{ ... }:
|
|
let
|
|
# Check if user has external home configuration
|
|
hasExternalHome = user.home != null;
|
|
|
|
# Extract path from fetchGit/fetchTarball if needed
|
|
externalHomePath =
|
|
if hasExternalHome then
|
|
if builtins.isAttrs user.home && user.home ? outPath then user.home.outPath else user.home
|
|
else
|
|
null;
|
|
|
|
# Import external module if it's a path
|
|
externalHomeModule =
|
|
if
|
|
externalHomePath != null
|
|
&& (
|
|
builtins.isPath externalHomePath
|
|
|| (builtins.isString externalHomePath && lib.hasPrefix "/" externalHomePath)
|
|
)
|
|
then
|
|
import (externalHomePath + "/home.nix") { inherit inputs; }
|
|
else if builtins.isAttrs user.home && !(user.home ? outPath) then
|
|
user.home # Direct attrset configuration
|
|
else
|
|
{ };
|
|
|
|
# Common imports based on flags
|
|
commonImports = lib.optional user.useZshTheme ../sw/theme.nix ++ [
|
|
(import ../sw/nvim.nix { inherit user; })
|
|
];
|
|
in
|
|
if hasExternalHome then
|
|
{
|
|
# External users: Merge external config with common imports
|
|
imports = commonImports ++ [ externalHomeModule ];
|
|
}
|
|
else
|
|
{
|
|
# Local users: Apply full configuration.
|
|
imports = user.extraImports ++ commonImports;
|
|
home.username = name;
|
|
home.homeDirectory = if name == "root" then "/root" else "/home/${name}";
|
|
home.stateVersion = "25.11";
|
|
home.packages = user.homePackages;
|
|
}
|
|
) enabledAccounts;
|
|
};
|
|
};
|
|
}
|