refactor: create glue/ and variants/ directories
- Add glue/ for fleet generation logic and common configuration - Add variants/ for hardware type modules - Improves separation of concerns and module organization
This commit is contained in:
137
glue/boot.nix
Normal file
137
glue/boot.nix
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Boot & Storage Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# This module defines:
|
||||||
|
# - Disko partition layout (EFI, swap, root)
|
||||||
|
# - Bootloader configuration (systemd-boot with Plymouth)
|
||||||
|
# - Filesystem options (device, swap size)
|
||||||
|
# - Build method options (used by installer/artifacts.nix)
|
||||||
|
# - Convenience options (forUser, useHostPrefix)
|
||||||
|
|
||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
options.athenix = {
|
||||||
|
host = {
|
||||||
|
useHostPrefix = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to prepend the host prefix to the hostname (used in inventory and hosts/default.nix).";
|
||||||
|
};
|
||||||
|
filesystem = {
|
||||||
|
device = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "The main disk device to use for installation.";
|
||||||
|
};
|
||||||
|
useSwap = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to create and use a swap partition.";
|
||||||
|
};
|
||||||
|
swapSize = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "The size of the swap partition.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# ========== Disk Partitioning (Disko) ==========
|
||||||
|
disko.enableConfig = lib.mkDefault true;
|
||||||
|
|
||||||
|
disko.devices = {
|
||||||
|
disk.main = {
|
||||||
|
type = "disk";
|
||||||
|
device = config.athenix.host.filesystem.device;
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
# EFI System Partition
|
||||||
|
ESP = {
|
||||||
|
name = "ESP";
|
||||||
|
label = "BOOT";
|
||||||
|
size = "1G";
|
||||||
|
type = "EF00";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "vfat";
|
||||||
|
mountpoint = "/boot";
|
||||||
|
mountOptions = [ "umask=0077" ];
|
||||||
|
extraArgs = [
|
||||||
|
"-n"
|
||||||
|
"BOOT"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Swap Partition (size configurable per host)
|
||||||
|
swap = lib.mkIf config.athenix.host.filesystem.useSwap {
|
||||||
|
name = "swap";
|
||||||
|
label = "swap";
|
||||||
|
size = config.athenix.host.filesystem.swapSize;
|
||||||
|
content = {
|
||||||
|
type = "swap";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Root Partition (takes remaining space)
|
||||||
|
root = {
|
||||||
|
name = "root";
|
||||||
|
label = "root";
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "ext4";
|
||||||
|
mountpoint = "/";
|
||||||
|
extraArgs = [
|
||||||
|
"-L"
|
||||||
|
"ROOT"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Bootloader Configuration
|
||||||
|
boot = {
|
||||||
|
loader.systemd-boot.enable = true;
|
||||||
|
loader.efi.canTouchEfiVariables = true;
|
||||||
|
plymouth.enable = true;
|
||||||
|
|
||||||
|
# Enable "Silent boot"
|
||||||
|
consoleLogLevel = 3;
|
||||||
|
initrd.verbose = false;
|
||||||
|
|
||||||
|
# Hide the OS choice for bootloaders.
|
||||||
|
# It's still possible to open the bootloader list by pressing any key
|
||||||
|
# It will just not appear on screen unless a key is pressed
|
||||||
|
loader.timeout = lib.mkDefault 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Set your time zone.
|
||||||
|
time.timeZone = "America/New_York";
|
||||||
|
|
||||||
|
# Select internationalisation properties.
|
||||||
|
i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
|
||||||
|
i18n.extraLocaleSettings = {
|
||||||
|
LC_ADDRESS = "en_US.UTF-8";
|
||||||
|
LC_IDENTIFICATION = "en_US.UTF-8";
|
||||||
|
LC_MEASUREMENT = "en_US.UTF-8";
|
||||||
|
LC_MONETARY = "en_US.UTF-8";
|
||||||
|
LC_NAME = "en_US.UTF-8";
|
||||||
|
LC_NUMERIC = "en_US.UTF-8";
|
||||||
|
LC_PAPER = "en_US.UTF-8";
|
||||||
|
LC_TELEPHONE = "en_US.UTF-8";
|
||||||
|
LC_TIME = "en_US.UTF-8";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.sleep.extraConfig = ''
|
||||||
|
SuspendState=freeze
|
||||||
|
HibernateDelaySec=2h
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
99
glue/common.nix
Normal file
99
glue/common.nix
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Common Host Module
|
||||||
|
# ============================================================================
|
||||||
|
# This module contains all the common configuration shared by all host types.
|
||||||
|
# It is automatically imported by the fleet generator for every host.
|
||||||
|
|
||||||
|
{ inputs }:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./boot.nix
|
||||||
|
./user-config.nix
|
||||||
|
../sw
|
||||||
|
../users.nix
|
||||||
|
inputs.home-manager.nixosModules.home-manager
|
||||||
|
inputs.agenix.nixosModules.default
|
||||||
|
inputs.disko.nixosModules.disko
|
||||||
|
];
|
||||||
|
|
||||||
|
# Define garbage collection options here since they're consumed in this module
|
||||||
|
options.athenix = {
|
||||||
|
forUser = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Convenience option to configure a host for a specific user.
|
||||||
|
Automatically enables the user (sets athenix.users.username.enable = true).
|
||||||
|
Value should be a username from athenix.users.accounts.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
system.gc = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to enable automatic garbage collection.";
|
||||||
|
};
|
||||||
|
frequency = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "weekly";
|
||||||
|
description = "How often to run garbage collection (systemd timer format).";
|
||||||
|
};
|
||||||
|
retentionDays = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 30;
|
||||||
|
description = "Number of days to keep old generations before deletion.";
|
||||||
|
};
|
||||||
|
optimise = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to automatically optimize the Nix store.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
host.buildMethods = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ "installer-iso" ];
|
||||||
|
description = ''
|
||||||
|
List of allowed build methods for this host (used by installer/artifacts.nix).
|
||||||
|
Supported methods:
|
||||||
|
- "installer-iso": Generates an auto-install ISO that installs this configuration to disk.
|
||||||
|
- "iso": Generates a live ISO (using nixos-generators).
|
||||||
|
- "ipxe": Generates iPXE netboot artifacts (kernel, initrd, script).
|
||||||
|
- "lxc": Generates an LXC container tarball.
|
||||||
|
- "proxmox": Generates a Proxmox VMA archive.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkMerge [
|
||||||
|
# Enable forUser if specified
|
||||||
|
(lib.mkIf (config.athenix.forUser != null) {
|
||||||
|
athenix.users.${config.athenix.forUser}.enable = true;
|
||||||
|
})
|
||||||
|
|
||||||
|
{
|
||||||
|
system.stateVersion = "25.11";
|
||||||
|
|
||||||
|
nix.settings.experimental-features = [
|
||||||
|
"nix-command"
|
||||||
|
"flakes"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Automatic Garbage Collection
|
||||||
|
nix.gc = lib.mkIf config.athenix.system.gc.enable {
|
||||||
|
automatic = true;
|
||||||
|
dates = config.athenix.system.gc.frequency;
|
||||||
|
options = "--delete-older-than ${toString config.athenix.system.gc.retentionDays}d";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Optimize storage
|
||||||
|
nix.optimise.automatic = config.athenix.system.gc.optimise;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
278
glue/fleet.nix
Normal file
278
glue/fleet.nix
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
{
|
||||||
|
inputs,
|
||||||
|
fleet ? import ../inventory.nix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Fleet Generator
|
||||||
|
# ============================================================================
|
||||||
|
# This file contains the logic to generate NixOS configurations for all hosts
|
||||||
|
# defined in inventory.nix. It supports both hostname-based and count-based
|
||||||
|
# configurations with flexible type associations.
|
||||||
|
|
||||||
|
let
|
||||||
|
nixpkgs = inputs.nixpkgs;
|
||||||
|
lib = nixpkgs.lib;
|
||||||
|
|
||||||
|
# Load all available host types from hosts/
|
||||||
|
hostTypes = import ../variants { inherit inputs; };
|
||||||
|
|
||||||
|
# Helper to create a single NixOS system configuration
|
||||||
|
mkHost =
|
||||||
|
{
|
||||||
|
hostName,
|
||||||
|
system ? "x86_64-linux",
|
||||||
|
hostType,
|
||||||
|
configOverrides ? { },
|
||||||
|
externalModuleThunk ? null,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# Lazy evaluation: only fetch external module when building this host
|
||||||
|
externalModulePath =
|
||||||
|
if externalModuleThunk != null then
|
||||||
|
let
|
||||||
|
# Force evaluation of the thunk (fetchGit, fetchTarball, etc.)
|
||||||
|
fetchedPath = externalModuleThunk;
|
||||||
|
# Extract outPath from fetchGit/fetchTarball results
|
||||||
|
extractedPath =
|
||||||
|
if builtins.isAttrs fetchedPath && fetchedPath ? outPath then fetchedPath.outPath else fetchedPath;
|
||||||
|
in
|
||||||
|
if builtins.isPath extractedPath then
|
||||||
|
extractedPath + "/default.nix"
|
||||||
|
else if lib.isDerivation extractedPath then
|
||||||
|
extractedPath + "/default.nix"
|
||||||
|
else
|
||||||
|
extractedPath + "/default.nix"
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
|
||||||
|
# Load users.nix to find external user modules
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
usersData = import ../users.nix { inherit pkgs; };
|
||||||
|
accounts = usersData.athenix.users or { };
|
||||||
|
|
||||||
|
# Build a map of user names to their nixos module paths (if they exist)
|
||||||
|
# We'll use this to conditionally import modules based on user.enable
|
||||||
|
userNixosModulePaths = lib.filterAttrs (_: v: v != null) (
|
||||||
|
lib.mapAttrs (
|
||||||
|
name: user:
|
||||||
|
if (user ? external && user.external != null) then
|
||||||
|
let
|
||||||
|
externalPath =
|
||||||
|
if builtins.isAttrs user.external && user.external ? outPath then
|
||||||
|
user.external.outPath
|
||||||
|
else
|
||||||
|
user.external;
|
||||||
|
nixosModulePath = externalPath + "/nixos.nix";
|
||||||
|
in
|
||||||
|
if
|
||||||
|
(builtins.isPath externalPath || (builtins.isString externalPath && lib.hasPrefix "/" externalPath))
|
||||||
|
&& builtins.pathExists nixosModulePath
|
||||||
|
then
|
||||||
|
nixosModulePath
|
||||||
|
else
|
||||||
|
null
|
||||||
|
else
|
||||||
|
null
|
||||||
|
) accounts
|
||||||
|
);
|
||||||
|
|
||||||
|
# Create conditional wrapper modules for each user's nixos.nix
|
||||||
|
# Each wrapper checks if the user is enabled before applying the module content
|
||||||
|
userNixosModules = lib.mapAttrsToList (
|
||||||
|
name: modulePath:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}@args:
|
||||||
|
let
|
||||||
|
# Import the user's nixos module - it returns a function or attrset
|
||||||
|
importedModuleFunc = import modulePath { inherit inputs; };
|
||||||
|
# If it's a function, call it with the module args; otherwise use as-is
|
||||||
|
importedModule =
|
||||||
|
if lib.isFunction importedModuleFunc then importedModuleFunc args else importedModuleFunc;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = lib.mkIf (config.athenix.users.${name}.enable or false) importedModule;
|
||||||
|
}
|
||||||
|
) userNixosModulePaths;
|
||||||
|
|
||||||
|
# Get the host type module from the hostTypes attribute set
|
||||||
|
typeModule =
|
||||||
|
hostTypes.${hostType}
|
||||||
|
or (throw "Host type '${hostType}' not found. Available types: ${lib.concatStringsSep ", " (lib.attrNames hostTypes)}");
|
||||||
|
|
||||||
|
# External module from fetchGit/fetchurl
|
||||||
|
externalPathModule =
|
||||||
|
if externalModulePath != null then import externalModulePath { inherit inputs; } else { };
|
||||||
|
|
||||||
|
# Config override module - translate special keys to athenix options
|
||||||
|
overrideModule =
|
||||||
|
{ ... }:
|
||||||
|
let
|
||||||
|
cleanConfig = lib.removeAttrs configOverrides [
|
||||||
|
"type"
|
||||||
|
"count"
|
||||||
|
"devices"
|
||||||
|
"overrides"
|
||||||
|
"defaultCount"
|
||||||
|
"buildMethods"
|
||||||
|
];
|
||||||
|
specialConfig = lib.optionalAttrs (configOverrides ? buildMethods) {
|
||||||
|
athenix.host.buildMethods = configOverrides.buildMethods;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = lib.mkMerge [
|
||||||
|
cleanConfig
|
||||||
|
specialConfig
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
allModules =
|
||||||
|
userNixosModules
|
||||||
|
++ [
|
||||||
|
(import ./common.nix { inherit inputs; })
|
||||||
|
typeModule
|
||||||
|
overrideModule
|
||||||
|
{ networking.hostName = hostName; }
|
||||||
|
]
|
||||||
|
++ lib.optional (externalModulePath != null) externalPathModule;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
system = lib.nixosSystem {
|
||||||
|
inherit system;
|
||||||
|
specialArgs = { inherit inputs; };
|
||||||
|
modules = allModules;
|
||||||
|
};
|
||||||
|
modules = allModules;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Process inventory entries - top-level keys are always prefixes
|
||||||
|
processInventory = lib.mapAttrs (
|
||||||
|
prefix: config:
|
||||||
|
let
|
||||||
|
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
|
||||||
|
"${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
|
||||||
|
# Check if deviceConfig has an 'external' field for lazy evaluation
|
||||||
|
hasExternalField = builtins.isAttrs deviceConfig && deviceConfig ? external;
|
||||||
|
|
||||||
|
# Extract external module thunk if present (don't evaluate yet!)
|
||||||
|
externalModuleThunk = if hasExternalField then deviceConfig.external else null;
|
||||||
|
|
||||||
|
# Remove 'external' from config to avoid conflicts
|
||||||
|
cleanDeviceConfig =
|
||||||
|
if hasExternalField then lib.removeAttrs deviceConfig [ "external" ] else deviceConfig;
|
||||||
|
|
||||||
|
# Merge: base config -> overrides -> device-specific config
|
||||||
|
mergedConfig = lib.recursiveUpdate (lib.recursiveUpdate baseConfig overrides) cleanDeviceConfig;
|
||||||
|
|
||||||
|
# Check useHostPrefix from the merged config
|
||||||
|
usePrefix = mergedConfig.athenix.host.useHostPrefix or true;
|
||||||
|
hostName = mkHostName prefix deviceKey usePrefix;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = hostName;
|
||||||
|
value = mkHost {
|
||||||
|
inherit
|
||||||
|
hostName
|
||||||
|
system
|
||||||
|
hostType
|
||||||
|
externalModuleThunk
|
||||||
|
;
|
||||||
|
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
|
||||||
|
lib.recursiveUpdate deviceHosts countHosts
|
||||||
|
) fleet;
|
||||||
|
|
||||||
|
# Flatten the nested structure
|
||||||
|
allHosts = lib.foldl' lib.recursiveUpdate { } (lib.attrValues processInventory);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
nixosConfigurations = lib.mapAttrs (n: v: v.system) allHosts;
|
||||||
|
modules = lib.mapAttrs (n: v: v.modules) allHosts;
|
||||||
|
}
|
||||||
276
glue/user-config.nix
Normal file
276
glue/user-config.nix
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
{
|
||||||
|
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
|
||||||
|
# Load users.nix to get account definitions
|
||||||
|
usersData = import ../users.nix { inherit pkgs; };
|
||||||
|
accounts = usersData.athenix.users or { };
|
||||||
|
|
||||||
|
# Helper: Resolve external module path from fetchGit/fetchTarball/path
|
||||||
|
resolveExternalPath =
|
||||||
|
external:
|
||||||
|
if external == null then
|
||||||
|
null
|
||||||
|
else if builtins.isAttrs external && external ? outPath then
|
||||||
|
external.outPath
|
||||||
|
else
|
||||||
|
external;
|
||||||
|
|
||||||
|
# Helper: Check if path exists and is valid
|
||||||
|
isValidPath =
|
||||||
|
path:
|
||||||
|
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.<name> 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.<name> 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
|
||||||
|
enabledAccounts = lib.filterAttrs (_: user: user.enable) config.athenix.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.athenix.users;
|
||||||
|
in
|
||||||
|
lib.mapAttrs (
|
||||||
|
name: user:
|
||||||
|
let
|
||||||
|
# Resolve external module paths
|
||||||
|
hasExternal = user.external != null;
|
||||||
|
externalPath = resolveExternalPath user.external;
|
||||||
|
userNixPath = if externalPath != null then externalPath + "/user.nix" else null;
|
||||||
|
hasExternalUser = isValidPath userNixPath;
|
||||||
|
|
||||||
|
# Import external user.nix for home-manager (filter out athenix.* options)
|
||||||
|
externalUserModule =
|
||||||
|
if hasExternalUser then
|
||||||
|
let
|
||||||
|
fullModule = import userNixPath { inherit inputs; };
|
||||||
|
in
|
||||||
|
# Only pass through non-athenix options to home-manager
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
osConfig,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
evaluated = fullModule {
|
||||||
|
inherit
|
||||||
|
config
|
||||||
|
lib
|
||||||
|
pkgs
|
||||||
|
osConfig
|
||||||
|
;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.filterAttrs (attrName: _: attrName != "athenix") evaluated
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
|
||||||
|
# Common imports based on user flags
|
||||||
|
commonImports = lib.optional user.useZshTheme ../sw/theme.nix ++ [
|
||||||
|
(import ../sw/nvim.nix { inherit user; })
|
||||||
|
];
|
||||||
|
|
||||||
|
# Build imports list
|
||||||
|
allImports = user.extraImports ++ commonImports ++ lib.optional hasExternalUser externalUserModule;
|
||||||
|
in
|
||||||
|
lib.mkMerge [
|
||||||
|
{
|
||||||
|
imports = allImports;
|
||||||
|
|
||||||
|
# Always set these required options
|
||||||
|
home.username = name;
|
||||||
|
home.homeDirectory = if name == "root" then "/root" else "/home/${name}";
|
||||||
|
home.stateVersion = "25.11";
|
||||||
|
}
|
||||||
|
(lib.mkIf (!hasExternal) {
|
||||||
|
# For local users only, add their packages
|
||||||
|
home.packages = user.homePackages;
|
||||||
|
})
|
||||||
|
]
|
||||||
|
) enabledAccounts;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
29
variants/default.nix
Normal file
29
variants/default.nix
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Host Types Module
|
||||||
|
# ============================================================================
|
||||||
|
# This module exports all available host types as an attribute set.
|
||||||
|
# Each type is a NixOS module function that takes { inputs } and returns
|
||||||
|
# a module configuration.
|
||||||
|
|
||||||
|
{ inputs }:
|
||||||
|
let
|
||||||
|
inherit (builtins) readDir attrNames;
|
||||||
|
lib = inputs.nixpkgs.lib;
|
||||||
|
inherit (lib) filterAttrs removeSuffix genAttrs;
|
||||||
|
|
||||||
|
files = readDir ./.;
|
||||||
|
|
||||||
|
# Keep only regular *.nix files except default.nix
|
||||||
|
nixFiles =
|
||||||
|
filterAttrs
|
||||||
|
(name: type:
|
||||||
|
type == "regular"
|
||||||
|
&& lib.hasSuffix ".nix" name
|
||||||
|
&& name != "default.nix")
|
||||||
|
files;
|
||||||
|
|
||||||
|
moduleNames = map (name: removeSuffix ".nix" name) (attrNames nixFiles);
|
||||||
|
in
|
||||||
|
genAttrs moduleNames
|
||||||
|
(name:
|
||||||
|
import ./${name}.nix { inherit inputs; })
|
||||||
51
variants/nix-desktop.nix
Normal file
51
variants/nix-desktop.nix
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Desktop Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Hardware and boot configuration for standard desktop workstations.
|
||||||
|
# Includes Intel CPU support and NVMe storage.
|
||||||
|
|
||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Boot Configuration ==========
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"xhci_pci" # USB 3.0 support
|
||||||
|
"nvme" # NVMe SSD support
|
||||||
|
"usb_storage" # USB storage devices
|
||||||
|
"sd_mod" # SD card support
|
||||||
|
"sdhci_pci" # SD card host controller
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" ]; # Intel virtualization support
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
boot.kernelParams = [
|
||||||
|
"quiet" # Minimal boot messages
|
||||||
|
"splash" # Show Plymouth boot splash
|
||||||
|
"boot.shell_on_fail" # Emergency shell on boot failure
|
||||||
|
"udev.log_priority=3" # Reduce udev logging
|
||||||
|
"rd.systemd.show_status=auto" # Show systemd status during boot
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Filesystem Configuration ==========
|
||||||
|
athenix.host.filesystem.swapSize = lib.mkDefault "16G";
|
||||||
|
athenix.host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
|
||||||
|
athenix.host.buildMethods = lib.mkDefault [ "installer-iso" ];
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
|
||||||
|
# ========== Hardware Configuration ==========
|
||||||
|
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
|
||||||
|
# ========== Software Profile ==========
|
||||||
|
athenix.sw.enable = lib.mkDefault true;
|
||||||
|
athenix.sw.type = lib.mkDefault "desktop";
|
||||||
|
}
|
||||||
67
variants/nix-ephemeral.nix
Normal file
67
variants/nix-ephemeral.nix
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Ephemeral/Diskless System Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Configuration for systems that run entirely from RAM without persistent storage.
|
||||||
|
# Suitable for kiosks, netboot clients, and stateless workstations.
|
||||||
|
# All data is lost on reboot.
|
||||||
|
|
||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Boot Configuration ==========
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"xhci_pci" # USB 3.0 support
|
||||||
|
"nvme" # NVMe support
|
||||||
|
"usb_storage" # USB storage devices
|
||||||
|
"sd_mod" # SD card support
|
||||||
|
"sdhci_pci" # SD card host controller
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" ]; # Intel virtualization support
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
boot.kernelParams = [
|
||||||
|
"quiet" # Minimal boot messages
|
||||||
|
"splash" # Show Plymouth boot splash
|
||||||
|
"boot.shell_on_fail" # Emergency shell on boot failure
|
||||||
|
"udev.log_priority=3" # Reduce udev logging
|
||||||
|
"rd.systemd.show_status=auto" # Show systemd status during boot
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Ephemeral Configuration ==========
|
||||||
|
# No persistent storage - everything runs from RAM
|
||||||
|
athenix.host.filesystem.swapSize = lib.mkForce "0G";
|
||||||
|
athenix.host.filesystem.device = lib.mkForce "/dev/null"; # Dummy device
|
||||||
|
athenix.host.buildMethods = lib.mkDefault [
|
||||||
|
"iso" # Live ISO image
|
||||||
|
"ipxe" # Network boot
|
||||||
|
];
|
||||||
|
|
||||||
|
# Disable disk management for RAM-only systems
|
||||||
|
disko.enableConfig = lib.mkForce false;
|
||||||
|
|
||||||
|
# Define tmpfs root filesystem
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "none";
|
||||||
|
fsType = "tmpfs";
|
||||||
|
options = [
|
||||||
|
"defaults"
|
||||||
|
"size=50%"
|
||||||
|
"mode=755"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
|
||||||
|
athenix.sw.enable = lib.mkDefault true;
|
||||||
|
athenix.sw.type = lib.mkDefault "stateless-kiosk";
|
||||||
|
}
|
||||||
64
variants/nix-laptop.nix
Normal file
64
variants/nix-laptop.nix
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Laptop Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Hardware and boot configuration for laptop systems with mobile features.
|
||||||
|
# Includes power management, lid switch handling, and Intel graphics fixes.
|
||||||
|
|
||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Boot Configuration ==========
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"xhci_pci" # USB 3.0 support
|
||||||
|
"thunderbolt" # Thunderbolt support
|
||||||
|
"nvme" # NVMe SSD support
|
||||||
|
"usb_storage" # USB storage devices
|
||||||
|
"sd_mod" # SD card support
|
||||||
|
"sdhci_pci" # SD card host controller
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" ]; # Intel virtualization support
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
boot.kernelParams = [
|
||||||
|
"quiet" # Minimal boot messages
|
||||||
|
"splash" # Show Plymouth boot splash
|
||||||
|
"boot.shell_on_fail" # Emergency shell on boot failure
|
||||||
|
"udev.log_priority=3" # Reduce udev logging
|
||||||
|
"rd.systemd.show_status=auto" # Show systemd status during boot
|
||||||
|
"i915.enable_psr=0" # Disable Panel Self Refresh (stability)
|
||||||
|
"i915.enable_dc=0" # Disable display power saving
|
||||||
|
"i915.enable_fbc=0" # Disable framebuffer compression
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Hardware Configuration ==========
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
|
||||||
|
# ========== Filesystem Configuration ==========
|
||||||
|
athenix.host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
|
||||||
|
athenix.host.filesystem.swapSize = lib.mkDefault "34G"; # Larger swap for hibernation
|
||||||
|
athenix.host.buildMethods = lib.mkDefault [ "installer-iso" ];
|
||||||
|
|
||||||
|
# ========== Power Management ==========
|
||||||
|
services.upower.enable = lib.mkDefault true;
|
||||||
|
services.logind.settings = {
|
||||||
|
Login = {
|
||||||
|
HandleLidSwitch = "suspend";
|
||||||
|
HandleLidSwitchExternalPower = "suspend";
|
||||||
|
HandleLidSwitchDocked = "ignore";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
athenix.sw.enable = lib.mkDefault true;
|
||||||
|
athenix.sw.type = lib.mkDefault "desktop";
|
||||||
|
}
|
||||||
61
variants/nix-lxc.nix
Normal file
61
variants/nix-lxc.nix
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Proxmox LXC Container Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Configuration for lightweight Linux containers running in Proxmox.
|
||||||
|
# Disables boot/disk management and enables remote development support.
|
||||||
|
|
||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
inputs.vscode-server.nixosModules.default
|
||||||
|
"${modulesPath}/virtualisation/proxmox-lxc.nix"
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Nix Configuration ==========
|
||||||
|
nix.settings.trusted-users = [
|
||||||
|
"root"
|
||||||
|
"engr-ugaif"
|
||||||
|
];
|
||||||
|
nix.settings.experimental-features = [
|
||||||
|
"nix-command"
|
||||||
|
"flakes"
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Container-Specific Configuration ==========
|
||||||
|
boot.isContainer = true;
|
||||||
|
boot.loader.systemd-boot.enable = lib.mkForce false; # No bootloader in container
|
||||||
|
disko.enableConfig = lib.mkForce false; # No disk management in container
|
||||||
|
console.enable = true;
|
||||||
|
|
||||||
|
# Allow getty to work in containers
|
||||||
|
systemd.services."getty@".unitConfig.ConditionPathExists = [
|
||||||
|
""
|
||||||
|
"/dev/%I"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Suppress unnecessary systemd units for containers
|
||||||
|
systemd.suppressedSystemUnits = [
|
||||||
|
"dev-mqueue.mount"
|
||||||
|
"sys-kernel-debug.mount"
|
||||||
|
"sys-fs-fuse-connections.mount"
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Remote Development ==========
|
||||||
|
services.vscode-server.enable = true;
|
||||||
|
|
||||||
|
# ========== System Configuration ==========
|
||||||
|
system.stateVersion = "25.11";
|
||||||
|
athenix.host.buildMethods = lib.mkDefault [
|
||||||
|
"lxc" # LXC container tarball
|
||||||
|
"proxmox" # Proxmox VMA archive
|
||||||
|
];
|
||||||
|
|
||||||
|
athenix.sw.enable = lib.mkDefault true;
|
||||||
|
athenix.sw.type = lib.mkDefault "headless";
|
||||||
|
}
|
||||||
69
variants/nix-surface.nix
Normal file
69
variants/nix-surface.nix
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Microsoft Surface Tablet Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Hardware configuration for Surface Go tablets in kiosk mode.
|
||||||
|
# Uses nixos-hardware module and older kernel for Surface-specific drivers.
|
||||||
|
|
||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# Use older kernel version for better Surface Go compatibility
|
||||||
|
refSystem = inputs.nixpkgs-old-kernel.lib.nixosSystem {
|
||||||
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
|
modules = [ inputs.nixos-hardware.nixosModules.microsoft-surface-go ];
|
||||||
|
};
|
||||||
|
refKernelPackages = refSystem.config.boot.kernelPackages;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
inputs.nixos-hardware.nixosModules.microsoft-surface-go
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Boot Configuration ==========
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"xhci_pci" # USB 3.0 support
|
||||||
|
"nvme" # NVMe support (though Surface uses eMMC)
|
||||||
|
"usb_storage" # USB storage devices
|
||||||
|
"sd_mod" # SD card support
|
||||||
|
"sdhci_pci" # SD card host controller
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" ]; # Intel virtualization support
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
boot.kernelParams = [
|
||||||
|
"quiet" # Minimal boot messages
|
||||||
|
"splash" # Show Plymouth boot splash
|
||||||
|
"boot.shell_on_fail" # Emergency shell on boot failure
|
||||||
|
"udev.log_priority=3" # Reduce udev logging
|
||||||
|
"rd.systemd.show_status=auto" # Show systemd status during boot
|
||||||
|
"intel_ipu3_imgu" # Intel camera image processing
|
||||||
|
"intel_ipu3_isys" # Intel camera sensor interface
|
||||||
|
"fbcon=map:1" # Framebuffer console mapping
|
||||||
|
"i915.enable_psr=0" # Disable Panel Self Refresh (breaks resume)
|
||||||
|
"i915.enable_dc=0" # Disable display power saving
|
||||||
|
];
|
||||||
|
|
||||||
|
# Use older kernel for better Surface hardware support
|
||||||
|
boot.kernelPackages = lib.mkForce refKernelPackages;
|
||||||
|
|
||||||
|
# ========== Filesystem Configuration ==========
|
||||||
|
athenix.host.filesystem.swapSize = lib.mkDefault "8G";
|
||||||
|
athenix.host.filesystem.device = lib.mkDefault "/dev/mmcblk0"; # eMMC storage # eMMC storage
|
||||||
|
athenix.host.buildMethods = lib.mkDefault [ "installer-iso" ];
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
|
||||||
|
# ========== Hardware Configuration ==========
|
||||||
|
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
|
||||||
|
# ========== Software Profile ==========
|
||||||
|
athenix.sw.enable = lib.mkDefault true;
|
||||||
|
athenix.sw.type = lib.mkDefault "tablet-kiosk"; # Touch-optimized kiosk mode
|
||||||
|
}
|
||||||
53
variants/nix-wsl.nix
Normal file
53
variants/nix-wsl.nix
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Windows Subsystem for Linux (WSL) Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Configuration for NixOS running in WSL2 on Windows.
|
||||||
|
# Integrates with nixos-wsl for WSL-specific functionality.
|
||||||
|
|
||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
inputs.nixos-wsl.nixosModules.default
|
||||||
|
inputs.vscode-server.nixosModules.default
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Options ==========
|
||||||
|
options.athenix.host.wsl.user = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "engr-ugaif";
|
||||||
|
description = "The default user to log in as in WSL.";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# ========== WSL Configuration ==========
|
||||||
|
wsl.enable = true;
|
||||||
|
# Use forUser if set, otherwise fall back to wsl.user option
|
||||||
|
wsl.defaultUser =
|
||||||
|
if config.athenix.forUser != null then config.athenix.forUser else config.athenix.host.wsl.user;
|
||||||
|
|
||||||
|
# ========== Software Profile ==========
|
||||||
|
athenix.sw.enable = lib.mkDefault true;
|
||||||
|
athenix.sw.type = lib.mkDefault "headless";
|
||||||
|
|
||||||
|
# ========== Remote Development ==========
|
||||||
|
services.vscode-server.enable = true;
|
||||||
|
|
||||||
|
# ========== Disable Irrelevant Systems ==========
|
||||||
|
# WSL doesn't use traditional boot or disk management
|
||||||
|
disko.enableConfig = lib.mkForce false;
|
||||||
|
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||||
|
boot.loader.grub.enable = lib.mkForce false;
|
||||||
|
|
||||||
|
# WSL manages its own networking
|
||||||
|
systemd.network.enable = lib.mkForce false;
|
||||||
|
|
||||||
|
# Provide dummy values for required options from boot.nix
|
||||||
|
athenix.host.filesystem.device = "/dev/null";
|
||||||
|
athenix.host.filesystem.swapSize = "0G";
|
||||||
|
};
|
||||||
|
}
|
||||||
50
variants/nix-zima.nix
Normal file
50
variants/nix-zima.nix
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Desktop Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Hardware and boot configuration for standard desktop workstations.
|
||||||
|
# Includes Intel CPU support and NVMe storage.
|
||||||
|
|
||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Boot Configuration ==========
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"xhci_pci" # USB 3.0 support
|
||||||
|
"usb_storage" # USB storage devices
|
||||||
|
"sd_mod" # SD card support
|
||||||
|
"sdhci_pci" # SD card host controller
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" ]; # Intel virtualization support
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
boot.kernelParams = [
|
||||||
|
"quiet" # Minimal boot messages
|
||||||
|
"splash" # Show Plymouth boot splash
|
||||||
|
"boot.shell_on_fail" # Emergency shell on boot failure
|
||||||
|
"udev.log_priority=3" # Reduce udev logging
|
||||||
|
"rd.systemd.show_status=auto" # Show systemd status during boot
|
||||||
|
];
|
||||||
|
|
||||||
|
# ========== Filesystem Configuration ==========
|
||||||
|
athenix.host.filesystem.useSwap = lib.mkDefault false;
|
||||||
|
athenix.host.filesystem.device = lib.mkDefault "/dev/mmcblk0";
|
||||||
|
athenix.host.buildMethods = lib.mkDefault [ "installer-iso" ];
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
|
||||||
|
# ========== Hardware Configuration ==========
|
||||||
|
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
|
||||||
|
# ========== Software Profile ==========
|
||||||
|
athenix.sw.enable = lib.mkDefault true;
|
||||||
|
athenix.sw.type = lib.mkDefault "desktop";
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user