From f606ea731cf2fe53c390f6a8fbf373542295d936 Mon Sep 17 00:00:00 2001 From: UGA Innovation Factory Date: Tue, 13 Jan 2026 18:20:24 -0500 Subject: [PATCH] feat: Refactor to use flake-parts and import inventory and users thru the flake parts --- flake.nix | 3 +- fleet/common.nix | 3 +- fleet/default.nix | 2 +- fleet/fleet-data.nix | 65 ------------- fleet/fleet-option.nix | 108 +++++++++++++++++++++ fleet/user-config.nix | 168 +++++---------------------------- inventory.nix | 1 + lib/mkFleet.nix | 2 +- parts/fleet-option.nix | 9 -- parts/nixos-configurations.nix | 13 ++- users.nix | 16 ++-- 11 files changed, 156 insertions(+), 234 deletions(-) delete mode 100644 fleet/fleet-data.nix delete mode 100644 parts/fleet-option.nix diff --git a/flake.nix b/flake.nix index cc600e4..a38576f 100644 --- a/flake.nix +++ b/flake.nix @@ -76,11 +76,12 @@ imports = [ ./parts/formatter.nix ./parts/lib.nix - ./parts/fleet-option.nix ./parts/nixos-configurations.nix ./parts/nixos-modules.nix ./parts/packages.nix ./parts/templates.nix + ./inventory.nix + ./users.nix ]; }; } diff --git a/fleet/common.nix b/fleet/common.nix index 5f4cbe7..17766de 100644 --- a/fleet/common.nix +++ b/fleet/common.nix @@ -12,12 +12,11 @@ }: { imports = [ - (import ./fleet-data.nix { inherit inputs lib; }) ./fs.nix ./boot.nix ./user-config.nix + ./fleet-option.nix ../sw - ../users.nix ]; options.athenix = { diff --git a/fleet/default.nix b/fleet/default.nix index 8fa9298..3aaff20 100644 --- a/fleet/default.nix +++ b/fleet/default.nix @@ -17,7 +17,7 @@ let # Evaluate inventory to get fleet data # Import fleet-option.nix (defines athenix.fleet) and inventory.nix (sets values) # We use a minimal module here to avoid circular dependencies from common.nix's imports - + hostTypes = config.athenix.hwTypes; # Helper to create a single NixOS system configuration diff --git a/fleet/fleet-data.nix b/fleet/fleet-data.nix deleted file mode 100644 index 12c6721..0000000 --- a/fleet/fleet-data.nix +++ /dev/null @@ -1,65 +0,0 @@ -# ============================================================================ -# Fleet Data for NixOS Configurations -# ============================================================================ -# This module exposes only the fleet inventory data (not hwTypes module functions) -# to individual NixOS configurations. Used by fleet/common.nix. -{ inputs, lib, ... }: -let - fleetDefinition = lib.mkOption { - description = "Hardware types definitions for the fleet."; - type = lib.types.attrsOf ( - lib.types.submodule ( - { name, ... }: - { - options = { - type = lib.mkOption { - type = lib.types.oneOf [ - lib.types.str - lib.types.listOf lib.types.str - ]; - default = name; - description = "Type(s) of system configuration for this device."; - }; - system = lib.mkOption { - type = lib.types.str; - default = "x86_64-linux"; - description = "NixOS system architecture for this hardware type."; - }; - devices = lib.mkOption { - type = lib.types.oneOf [ - lib.types.int - (lib.types.attrsOf ( - lib.types.submodule ( - { name, ... }: - { - freeformType = lib.types.attrs; - } - ) - )) - ]; - }; - count = lib.mkOption { - type = lib.types.int; - default = 0; - description = "Number of devices of this type to create."; - }; - defaultCount = lib.mkOption { - type = lib.types.int; - default = 0; - description = "Default number of devices to create with default configurations and numbered hostnames."; - }; - overrides = lib.mkOption { - type = lib.types.attrs; - default = { }; - description = "Overrides to apply to all devices of this type."; - }; - }; - } - ) - ); - }; -in -{ - imports = [ ../inventory.nix ]; - options.athenix.fleet = fleetDefinition; -} diff --git a/fleet/fleet-option.nix b/fleet/fleet-option.nix index 88e9f32..f6f91cd 100644 --- a/fleet/fleet-option.nix +++ b/fleet/fleet-option.nix @@ -59,6 +59,109 @@ 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 = [ ]; + }; + external = lib.mkOption { + type = lib.types.nullOr ( + lib.types.oneOf [ + lib.types.path + lib.types.package + lib.types.attrs + ] + ); + default = null; + description = '' + External user configuration module. Can be: + - A path to a local module directory + - A fetchGit/fetchTarball result pointing to a repository + + The external module can contain: + - user.nix (optional): Sets athenix.users. options AND home-manager config + - nixos.nix (optional): System-level NixOS 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.enum [ + "bash" + "zsh" + "fish" + "tcsh" + ] + ); + default = "bash"; + description = "The shell for this user."; + }; + editor = lib.mkOption { + type = lib.types.nullOr ( + lib.types.enum [ + "vim" + "neovim" + "emacs" + "nano" + "code" + ] + ); + default = "neovim"; + 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.athenix = { @@ -67,6 +170,11 @@ in description = "Hardware types definitions for the fleet."; type = lib.types.attrs; }; + 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.athenix.hwTypes = lib.mkDefault (import ../hw { inherit inputs; }); diff --git a/fleet/user-config.nix b/fleet/user-config.nix index 7f33c83..9d960ea 100644 --- a/fleet/user-config.nix +++ b/fleet/user-config.nix @@ -14,9 +14,6 @@ # and Home Manager configuration. let - # Load users.nix to get account definitions - accounts = config.athenix.users or { }; - # Helper: Resolve external module path from fetchGit/fetchTarball/path resolveExternalPath = external: @@ -33,149 +30,9 @@ let path != null && (builtins.isPath path || (builtins.isString path && lib.hasPrefix "/" path)) && builtins.pathExists path; - - # Extract athenix.users options from external user.nix modules - # First, build a cache of options per user from their external user.nix (if any). - externalUserModuleOptions = lib.genAttrs (lib.attrNames accounts) ( - name: - let - user = accounts.${name}; - externalPath = resolveExternalPath (user.external or null); - userNixPath = if externalPath != null then externalPath + "/user.nix" else null; - in - if isValidPath userNixPath then - let - # Import and evaluate the module with minimal args - outerModule = import userNixPath { inherit inputs; }; - evaluatedModule = outerModule { - config = { }; - inherit lib pkgs; - osConfig = null; - }; - # Extract just the athenix.users. options - athenixUsers = evaluatedModule.athenix.users or { }; - in - athenixUsers.${name} or { } - else - { } - ); - - # externalUserOptions only contains users that actually have options defined - externalUserOptions = lib.filterAttrs ( - _: moduleOptions: moduleOptions != { } - ) externalUserModuleOptions; - - # 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 = [ ]; - }; - external = lib.mkOption { - type = lib.types.nullOr ( - lib.types.oneOf [ - lib.types.path - lib.types.package - lib.types.attrs - ] - ); - default = null; - description = '' - External user configuration module. Can be: - - A path to a local module directory - - A fetchGit/fetchTarball result pointing to a repository - - The external module can contain: - - user.nix (optional): Sets athenix.users. options AND home-manager config - - nixos.nix (optional): System-level NixOS 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.athenix.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 = { - # Merge user definitions from users.nix with options from external user.nix modules - # External options take precedence over users.nix (which uses lib.mkDefault) - athenix.users = lib.mapAttrs ( - name: user: - user - // { - description = lib.mkDefault (user.description or null); - shell = lib.mkDefault (user.shell or null); - extraGroups = lib.mkDefault (user.extraGroups or [ ]); - } - // (externalUserOptions.${name} or { }) - ) accounts; - # Generate NixOS users users.users = let @@ -187,16 +44,31 @@ in isPlasma6 = config.services.desktopManager.plasma6.enable; defaultPackages = lib.optionals (isPlasma6 && name != "root") [ pkgs.kdePackages.kate ]; finalPackages = lib.subtractLists user.excludePackages (defaultPackages ++ user.extraPackages); + shells = { + bash = pkgs.bash; + zsh = pkgs.zsh; + fish = pkgs.fish; + tcsh = pkgs.tcsh; + }; in - { + rec { 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; + shell = if user.shell != null then shells.${user.shell} else pkgs.bash; + packages = finalPackages ++ [ shell ]; + group = if user.isNormalUser then name else lib.mkDefault "root"; } ) enabledAccounts; + # Generate user groups for normal users + users.groups = + let + enabledAccounts = lib.filterAttrs (_: user: user.enable) config.athenix.users; + normalUsers = lib.filterAttrs (_: user: user.isNormalUser) enabledAccounts; + in + lib.mapAttrs (_: _: { }) normalUsers; + # Home Manager configs per user home-manager = { useGlobalPkgs = true; @@ -263,6 +135,10 @@ in home.username = name; home.homeDirectory = if name == "root" then "/root" else "/home/${name}"; home.stateVersion = "25.11"; + programs.${user.editor} = { + enable = true; + defaultEditor = true; + }; } (lib.mkIf (!hasExternal) { # For local users only, add their packages diff --git a/inventory.nix b/inventory.nix index 25eff41..c029da2 100644 --- a/inventory.nix +++ b/inventory.nix @@ -131,6 +131,7 @@ rev = "dab32f5884895cead0fae28cb7d88d17951d0c12"; submodules = true; }; + "usda-dash".athenix.users.engr-ugaif.enable = true; }; overrides = { athenix.host.useHostPrefix = false; diff --git a/lib/mkFleet.nix b/lib/mkFleet.nix index e9cd399..5e3b783 100644 --- a/lib/mkFleet.nix +++ b/lib/mkFleet.nix @@ -3,7 +3,7 @@ { inputs, lib, - config + config, }: import ../fleet/default.nix { inherit inputs lib config; diff --git a/parts/fleet-option.nix b/parts/fleet-option.nix deleted file mode 100644 index 96c5a56..0000000 --- a/parts/fleet-option.nix +++ /dev/null @@ -1,9 +0,0 @@ -# Flake-parts wrapper for fleet-option.nix -{ inputs, self, lib, config, ... }: -let - fleetModule = import ../fleet/fleet-option.nix { inherit inputs lib; }; - inventoryModule = import ../inventory.nix { }; -in -{ - imports = [ fleetModule inventoryModule ]; -} diff --git a/parts/nixos-configurations.nix b/parts/nixos-configurations.nix index 5729ab5..ac51ef4 100644 --- a/parts/nixos-configurations.nix +++ b/parts/nixos-configurations.nix @@ -1,6 +1,17 @@ # NixOS configurations generated from fleet -{ inputs, self, lib, config, ... }: { + inputs, + self, + lib, + pkgs, + config, + ... +}: +{ + imports = [ + ../fleet/fleet-option.nix + ]; + flake.nixosConfigurations = let fleet = self.lib.mkFleet { inherit inputs lib config; }; diff --git a/users.nix b/users.nix index e813fa8..ebc9efb 100644 --- a/users.nix +++ b/users.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ ... }: { # ============================================================================ # User Definitions @@ -46,19 +46,19 @@ ]; enable = true; # Default user, enabled everywhere }; - hdh20267 = { - external = builtins.fetchGit { - url = "https://git.factory.uga.edu/hdh20267/hdh20267-nix"; - rev = "c538e0c0510045b58264627bb897fc499dc7c490"; - }; - }; + #hdh20267 = { + # external = builtins.fetchGit { + # url = "https://git.factory.uga.edu/hdh20267/hdh20267-nix"; + # rev = "c538e0c0510045b58264627bb897fc499dc7c490"; + # }; + #}; sv22900 = { description = "Alireza Vaezi"; extraGroups = [ "networkmanager" "wheel" ]; - shell = pkgs.zsh; + shell = "zsh"; # enable = false by default, set to true per-system }; };