fix: Respect nvim user config option
This commit is contained in:
committed by
Hunter Halloran
parent
1c71bf099e
commit
3b0c147b3f
@@ -13,7 +13,22 @@
|
||||
|
||||
{
|
||||
options.ugaif = {
|
||||
forUser = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Convenience option to configure a host for a specific user.
|
||||
Automatically adds the user to extraUsers and sets wslUser for WSL hosts.
|
||||
Value should be a username from ugaif.users.accounts.
|
||||
'';
|
||||
};
|
||||
|
||||
host = {
|
||||
useHostPrefix = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Whether to prepend the host prefix to the hostname (used in inventory).";
|
||||
};
|
||||
filesystem = {
|
||||
device = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
||||
@@ -8,10 +8,25 @@
|
||||
# Host Generator
|
||||
# ============================================================================
|
||||
# This file contains the logic to generate NixOS configurations for all hosts
|
||||
# defined in inventory.nix. It handles:
|
||||
# 1. Common module imports (boot, users, software).
|
||||
# 2. Host-specific overrides (filesystem, enabled users).
|
||||
# 3. External flake integration for system overrides.
|
||||
# defined in inventory.nix. It supports both hostname-based and count-based
|
||||
# configurations with flexible type associations.
|
||||
#
|
||||
# Inventory format:
|
||||
# {
|
||||
# "my-hostname" = {
|
||||
# type = "nix-desktop"; # Host type module to use
|
||||
# system = "x86_64-linux"; # Optional
|
||||
# # ... any ugaif.* options or device-specific config
|
||||
# };
|
||||
#
|
||||
# "lab-prefix" = {
|
||||
# type = "nix-laptop";
|
||||
# count = 5; # Generates lab-prefix1, lab-prefix2, ... lab-prefix5
|
||||
# devices = {
|
||||
# "machine-1" = { ... }; # Override for lab-prefix1
|
||||
# };
|
||||
# };
|
||||
# }
|
||||
|
||||
let
|
||||
nixpkgs = inputs.nixpkgs;
|
||||
@@ -21,11 +36,11 @@ let
|
||||
{
|
||||
hostName,
|
||||
system ? "x86_64-linux",
|
||||
extraModules ? [ ],
|
||||
hostType,
|
||||
configOverrides ? { },
|
||||
}:
|
||||
let
|
||||
# Load users.nix to find external user flakes
|
||||
# We use legacyPackages to evaluate the simple data structure of users.nix
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
usersData = import ../users.nix { inherit pkgs; };
|
||||
accounts = usersData.ugaif.users.accounts or { };
|
||||
@@ -39,111 +54,177 @@ let
|
||||
{ }
|
||||
) accounts;
|
||||
|
||||
# Load the host type module
|
||||
typeFile = ./types + "/${hostType}.nix";
|
||||
typeModule =
|
||||
if builtins.pathExists typeFile then
|
||||
import typeFile { inherit inputs; }
|
||||
else
|
||||
throw "Host type '${hostType}' not found in hosts/types/";
|
||||
|
||||
# External flake override if specified
|
||||
externalFlakeModule =
|
||||
if configOverrides ? flakeUrl then
|
||||
(builtins.getFlake configOverrides.flakeUrl).nixosModules.default
|
||||
else
|
||||
{ };
|
||||
|
||||
# Config override module - translate special keys to ugaif options
|
||||
overrideModule =
|
||||
{ ... }:
|
||||
let
|
||||
cleanConfig = lib.removeAttrs configOverrides [
|
||||
"type"
|
||||
"count"
|
||||
"devices"
|
||||
"overrides"
|
||||
"defaultCount"
|
||||
"extraUsers"
|
||||
"flakeUrl"
|
||||
"hostname"
|
||||
"buildMethods"
|
||||
"wslUser"
|
||||
];
|
||||
specialConfig = lib.mkMerge [
|
||||
(lib.optionalAttrs (configOverrides ? extraUsers) {
|
||||
ugaif.users.enabledUsers = configOverrides.extraUsers;
|
||||
})
|
||||
(lib.optionalAttrs (configOverrides ? buildMethods) {
|
||||
ugaif.host.buildMethods = configOverrides.buildMethods;
|
||||
})
|
||||
(lib.optionalAttrs (configOverrides ? wslUser) {
|
||||
ugaif.host.wsl.user = configOverrides.wslUser;
|
||||
})
|
||||
];
|
||||
in
|
||||
{
|
||||
config = lib.mkMerge [
|
||||
cleanConfig
|
||||
specialConfig
|
||||
];
|
||||
};
|
||||
|
||||
allModules =
|
||||
userFlakeModules
|
||||
++ extraModules
|
||||
++ [
|
||||
typeModule
|
||||
overrideModule
|
||||
{ networking.hostName = hostName; }
|
||||
];
|
||||
]
|
||||
++ lib.optional (configOverrides ? flakeUrl) externalFlakeModule;
|
||||
in
|
||||
{
|
||||
system = lib.nixosSystem {
|
||||
inherit system;
|
||||
|
||||
specialArgs = { inherit inputs; };
|
||||
|
||||
modules = allModules;
|
||||
};
|
||||
modules = allModules;
|
||||
};
|
||||
|
||||
# Function to generate a set of hosts based on inventory count and overrides
|
||||
mkHostGroup =
|
||||
{
|
||||
prefix,
|
||||
count,
|
||||
system ? "x86_64-linux",
|
||||
extraModules ? [ ],
|
||||
deviceOverrides ? { },
|
||||
}:
|
||||
lib.listToAttrs (
|
||||
lib.concatMap (
|
||||
i:
|
||||
let
|
||||
defaultName = "${prefix}${toString i}";
|
||||
devConf = deviceOverrides.${toString i} or { };
|
||||
hasOverride = builtins.hasAttr (toString i) deviceOverrides;
|
||||
hostName =
|
||||
if hasOverride && (builtins.hasAttr "hostname" devConf) then devConf.hostname else defaultName;
|
||||
|
||||
# Extract flakeUrl if it exists
|
||||
externalFlake =
|
||||
if hasOverride && (builtins.hasAttr "flakeUrl" devConf) then
|
||||
builtins.getFlake devConf.flakeUrl
|
||||
else
|
||||
null;
|
||||
|
||||
# Module from external flake
|
||||
externalModule = if externalFlake != null then externalFlake.nixosModules.default else { };
|
||||
|
||||
# Config override module (filesystem, users)
|
||||
overrideModule =
|
||||
{ ... }:
|
||||
let
|
||||
# Extract device-specific config, removing special keys that need custom handling
|
||||
baseConfig = lib.removeAttrs devConf [
|
||||
"extraUsers"
|
||||
"flakeUrl"
|
||||
"hostname"
|
||||
"buildMethods"
|
||||
"wslUser"
|
||||
];
|
||||
# Handle special keys that map to specific ugaif options
|
||||
specialConfig = lib.mkMerge [
|
||||
(lib.optionalAttrs (devConf ? extraUsers) { ugaif.users.enabledUsers = devConf.extraUsers; })
|
||||
(lib.optionalAttrs (devConf ? buildMethods) { ugaif.host.buildMethods = devConf.buildMethods; })
|
||||
(lib.optionalAttrs (devConf ? wslUser) { ugaif.host.wsl.user = devConf.wslUser; })
|
||||
];
|
||||
in
|
||||
lib.mkIf hasOverride (lib.recursiveUpdate baseConfig specialConfig);
|
||||
|
||||
config = mkHost {
|
||||
hostName = hostName;
|
||||
inherit system;
|
||||
extraModules =
|
||||
extraModules ++ [ overrideModule ] ++ (lib.optional (externalFlake != null) externalModule);
|
||||
};
|
||||
|
||||
aliasNames = lib.optional (hostName != defaultName) hostName;
|
||||
names = lib.unique ([ defaultName ] ++ aliasNames);
|
||||
in
|
||||
lib.map (name: {
|
||||
inherit name;
|
||||
value = config;
|
||||
}) names
|
||||
) (lib.range 1 count)
|
||||
);
|
||||
|
||||
# Generate host groups based on the input hosts configuration
|
||||
hostGroups = lib.mapAttrsToList (
|
||||
type: config:
|
||||
# Process inventory entries - top-level keys are always prefixes
|
||||
processInventory = lib.mapAttrs (
|
||||
prefix: config:
|
||||
let
|
||||
typeFile = ./types + "/${type}.nix";
|
||||
modules =
|
||||
if builtins.pathExists typeFile then
|
||||
[ (import typeFile { inherit inputs; }) ]
|
||||
hostType = config.type or prefix;
|
||||
system = config.system or "x86_64-linux";
|
||||
devices = config.devices or { };
|
||||
hasCount = config ? count;
|
||||
|
||||
# Helper to generate hostname from prefix and suffix
|
||||
# Numbers get no dash: "nix-surface1", "nix-surface2"
|
||||
# Letters get dash: "nix-surface-alpha", "nix-surface-beta"
|
||||
mkHostName =
|
||||
prefix: suffix: usePrefix:
|
||||
if !usePrefix then
|
||||
suffix
|
||||
else if lib.match "[0-9]+" suffix != null then
|
||||
"${prefix}${suffix}" # numeric: no dash
|
||||
else
|
||||
throw "Host type '${type}' not found in hosts/types/";
|
||||
"${prefix}-${suffix}"; # non-numeric: add dash
|
||||
|
||||
# Extract common overrides and default count
|
||||
overrides = config.overrides or { };
|
||||
defaultCount = config.defaultCount or 0;
|
||||
|
||||
# If devices is a number, treat it as count
|
||||
devicesValue = config.devices or { };
|
||||
actualDevices = if lib.isInt devicesValue then { } else devicesValue;
|
||||
actualCount = if lib.isInt devicesValue then devicesValue else (config.count or 0);
|
||||
|
||||
# Clean base config - remove inventory management keys
|
||||
baseConfig = lib.removeAttrs config [
|
||||
"type"
|
||||
"system"
|
||||
"count"
|
||||
"devices"
|
||||
"overrides"
|
||||
"defaultCount"
|
||||
];
|
||||
|
||||
# Generate hosts from explicit device definitions
|
||||
deviceHosts = lib.listToAttrs (
|
||||
lib.mapAttrsToList (
|
||||
deviceKey: deviceConfig:
|
||||
let
|
||||
usePrefix = deviceConfig.ugaif.host.useHostPrefix or true;
|
||||
hostName = mkHostName prefix deviceKey usePrefix;
|
||||
# Merge: base config -> overrides -> device-specific config
|
||||
mergedConfig = lib.recursiveUpdate (lib.recursiveUpdate baseConfig overrides) deviceConfig;
|
||||
in
|
||||
{
|
||||
name = hostName;
|
||||
value = mkHost {
|
||||
inherit hostName system hostType;
|
||||
configOverrides = mergedConfig;
|
||||
};
|
||||
}
|
||||
) actualDevices
|
||||
);
|
||||
|
||||
# Generate numbered hosts from count or defaultCount
|
||||
# If devices are specified, defaultCount fills in the gaps
|
||||
countToUse = if actualCount > 0 then actualCount else defaultCount;
|
||||
|
||||
# Get which numbered keys are already defined in devices
|
||||
existingNumbers = lib.filter (k: lib.match "[0-9]+" k != null) (lib.attrNames actualDevices);
|
||||
|
||||
countHosts =
|
||||
if countToUse > 0 then
|
||||
lib.listToAttrs (
|
||||
lib.filter (x: x != null) (
|
||||
map (
|
||||
i:
|
||||
let
|
||||
deviceKey = toString i;
|
||||
# Skip if this number is already in explicit devices
|
||||
alreadyDefined = lib.elem deviceKey existingNumbers;
|
||||
in
|
||||
if alreadyDefined then
|
||||
null
|
||||
else
|
||||
let
|
||||
hostName = mkHostName prefix deviceKey true;
|
||||
mergedConfig = lib.recursiveUpdate baseConfig overrides;
|
||||
in
|
||||
{
|
||||
name = hostName;
|
||||
value = mkHost {
|
||||
inherit hostName system hostType;
|
||||
configOverrides = mergedConfig;
|
||||
};
|
||||
}
|
||||
) (lib.range 1 countToUse)
|
||||
)
|
||||
)
|
||||
else
|
||||
{ };
|
||||
in
|
||||
mkHostGroup {
|
||||
prefix = type;
|
||||
inherit (config) count;
|
||||
extraModules = modules;
|
||||
deviceOverrides = config.devices or { };
|
||||
}
|
||||
lib.recursiveUpdate deviceHosts countHosts
|
||||
) hosts;
|
||||
|
||||
allHosts = lib.foldl' lib.recursiveUpdate { } hostGroups;
|
||||
# Flatten the nested structure
|
||||
allHosts = lib.foldl' lib.recursiveUpdate { } (lib.attrValues processInventory);
|
||||
in
|
||||
{
|
||||
nixosConfigurations = lib.mapAttrs (n: v: v.system) allHosts;
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
config = {
|
||||
wsl.enable = true;
|
||||
wsl.defaultUser = config.ugaif.host.wsl.user;
|
||||
wsl.defaultUser =
|
||||
if config.ugaif.forUser != null then config.ugaif.forUser else config.ugaif.host.wsl.user;
|
||||
|
||||
# Enable the headless software profile
|
||||
ugaif.sw.enable = lib.mkDefault true;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
@@ -100,7 +101,8 @@ in
|
||||
ugaif.users.enabledUsers = [
|
||||
"root"
|
||||
"engr-ugaif"
|
||||
];
|
||||
]
|
||||
++ lib.optional (config.ugaif.forUser != null) config.ugaif.forUser;
|
||||
|
||||
# Generate NixOS users
|
||||
users.users =
|
||||
@@ -131,6 +133,7 @@ in
|
||||
useUserPackages = true;
|
||||
extraSpecialArgs = {
|
||||
osConfig = config;
|
||||
inherit inputs;
|
||||
};
|
||||
|
||||
users =
|
||||
@@ -146,8 +149,9 @@ in
|
||||
isExternal = user.flakeUrl != "";
|
||||
|
||||
# Common imports based on flags
|
||||
commonImports =
|
||||
lib.optional user.useZshTheme ../sw/theme.nix ++ lib.optional user.useNvimPlugins ../sw/nvim.nix;
|
||||
commonImports = lib.optional user.useZshTheme ../sw/theme.nix ++ [
|
||||
(import ../sw/nvim.nix { inherit user; })
|
||||
];
|
||||
in
|
||||
if isExternal then
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user