diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ddf2e70..539528f 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -26,8 +26,8 @@ This is a **NixOS system configuration repository** that uses: - **`flake.nix`**: Entry point - inputs and outputs only - **`inventory.nix`**: Fleet definitions - host configurations - **`users.nix`**: User account definitions -- **`variants/`**: Hardware type modules (desktop, laptop, surface, lxc, wsl, etc.) -- **`glue/`**: Fleet generation logic and common system configuration +- **`hw/`**: Hardware type modules (desktop, laptop, surface, lxc, wsl, etc.) +- **`fleet/`**: Fleet generation logic and common system configuration - **`sw/`**: Software configurations by system type - **`installer/`**: Build artifact generation (ISO, LXC, etc.) - **`templates/`**: Templates for external configurations @@ -45,9 +45,12 @@ All Innovation Factory-specific options MUST use the `athenix` namespace: ### Host Options (`athenix.host.*`) ```nix athenix.host = { - filesystem.device = "/dev/sda"; # Boot disk - filesystem.swapSize = "32G"; # Swap size - buildMethods = [ "iso" ]; # Artifact types + filesystem.device = "/dev/nvme0n1"; # Boot disk (default: null) + filesystem.swapSize = "32G"; # Swap size (default: null) + buildMethods = [ "installer-iso" ]; # Artifact types (defined in sw/gc.nix) + useHostPrefix = true; # Hostname prefix behavior + wsl.user = "username"; # WSL default user +}; useHostPrefix = true; # Hostname prefix behavior wsl.user = "username"; # WSL default user }; @@ -114,6 +117,17 @@ athenix.forUser = "username"; # Convenience: enable user + set WSL us 3. System modules: Provide `default.nix` that accepts `{ inputs, ... }` 4. Reference in `inventory.nix` or `users.nix` using `builtins.fetchGit` +#### Using Athenix as a Library +External flakes can use Athenix's fleet generator: +```nix +outputs = { athenix, ... }: { + nixosConfigurations = athenix.lib.mkFleet { + fleet = import ./custom-inventory.nix; + hwTypes = import ./custom-hardware.nix; + }; +}; +``` + ## Important Constraints ### What NOT to Do diff --git a/README.md b/README.md index 8e2d0e7..822848a 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ users.nix # User account definitions flake.lock # Locked dependency versions -variants/ # Hardware type modules (exportable as nixosModules) +hw/ # Hardware type modules (exportable as nixosModules) ├── default.nix # Auto-exports all variant types ├── nix-desktop.nix # Desktop workstations ├── nix-laptop.nix # Laptop systems @@ -64,8 +64,8 @@ variants/ # Hardware type modules (exportable as nixosModules) ├── nix-zima.nix # ZimaBoard systems └── nix-ephemeral.nix # Diskless/netboot systems -glue/ # Fleet generation and common configuration -├── fleet.nix # Processes inventory.nix to generate all hosts +fleet/ # Fleet generation and common configuration +├── default.nix # Processes inventory.nix to generate all hosts ├── common.nix # Common NixOS configuration (all hosts) ├── boot.nix # Boot and filesystem configuration └── user-config.nix # User account and home-manager integration @@ -233,6 +233,35 @@ nix flake show **See [docs/BUILDING.md](docs/BUILDING.md) for complete guide.** +### Using Athenix as a Library + +Import Athenix in your own flake to use its fleet generation logic with custom inventory: + +```nix +{ + inputs.athenix.url = "git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git"; + + outputs = { self, athenix, ... }: { + # Generate configurations with custom fleet and hardware types + nixosConfigurations = athenix.lib.mkFleet { + fleet = import ./my-inventory.nix; + hwTypes = import ./my-hardware-types.nix; + }; + + # Or use individual modules + nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { + modules = [ + athenix.nixosModules.hw.nix-desktop # Use Athenix hardware configs + athenix.nixosModules.sw # Use Athenix software configs + ./configuration.nix + ]; + }; + }; +} +``` + +**Exported modules:** `nix-desktop`, `nix-laptop`, `nix-surface`, `nix-lxc`, `nix-wsl`, `nix-ephemeral`, `nix-zima`, `sw`, `common` + ## System Types Set via `athenix.sw.type`: diff --git a/docs/EXTERNAL_MODULES.md b/docs/EXTERNAL_MODULES.md index a94dfef..4ba7299 100644 --- a/docs/EXTERNAL_MODULES.md +++ b/docs/EXTERNAL_MODULES.md @@ -115,8 +115,8 @@ server-config/ When a host is built, modules load in this order: -1. Hardware type module (from `variants/nix-*.nix`) -2. Common system configuration (from `glue/common.nix`) +1. Hardware type module (from `hw/nix-*.nix`) +2. Common system configuration (from `fleet/common.nix`) 3. Software type module (from `sw/{type}/`) 4. User NixOS modules (from `users.nix` - `nixos.nix` files) 5. Device-specific overrides (from `inventory.nix`) diff --git a/docs/NAMESPACE.md b/docs/NAMESPACE.md index 118688b..6c55c7d 100644 --- a/docs/NAMESPACE.md +++ b/docs/NAMESPACE.md @@ -17,9 +17,9 @@ Hardware and boot-related settings. Boot disk device path. -**Type:** String +**Type:** String or null -**Default:** `"/dev/sda"` +**Default:** `null` (must be set by hardware type or per-host) **Example:** ```nix @@ -30,9 +30,9 @@ athenix.host.filesystem.device = "/dev/nvme0n1"; Swap partition size. -**Type:** String (size with unit, e.g., `"32G"`, `"2G"`) +**Type:** String (size with unit, e.g., `"32G"`, `"2G"`) or null -**Default:** `"32G"` +**Default:** `null` (must be set by hardware type or per-host) **Example:** ```nix diff --git a/flake.nix b/flake.nix index 74acc6a..e1cd249 100644 --- a/flake.nix +++ b/flake.nix @@ -69,7 +69,7 @@ ... }: let - fleet = import ./glue/fleet.nix { inherit inputs; }; + fleet = self.lib.mkFleet { inherit inputs; }; linuxSystem = "x86_64-linux"; artifacts = import ./installer/artifacts.nix { inherit inputs fleet self; @@ -90,11 +90,14 @@ nixosConfigurations = fleet.nixosConfigurations; # Expose artifacts to all systems, but they are always built for x86_64-linux - packages = forAllSystems (_: artifacts); + packages.${linuxSystem} = artifacts; # Expose host type modules and installer modules for external use nixosModules = import ./installer/modules.nix { inherit inputs; }; + # Library functions + lib = import ./lib { inherit inputs; }; + # Templates for external configurations templates = import ./templates; }; diff --git a/fleet/boot.nix b/fleet/boot.nix new file mode 100644 index 0000000..b2ef67c --- /dev/null +++ b/fleet/boot.nix @@ -0,0 +1,48 @@ +# ============================================================================ +# Boot configuration module +# ============================================================================ +# This module defines: +# - Bootloader configuration (systemd-boot with Plymouth) +# - Timezone and locale settings +# - Systemd sleep configuration + +{ config, lib, ... }: +{ + boot = { + loader.systemd-boot.enable = lib.mkDefault true; + loader.efi.canTouchEfiVariables = lib.mkDefault true; + plymouth.enable = lib.mkDefault 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 + ''; +} diff --git a/fleet/common.nix b/fleet/common.nix new file mode 100644 index 0000000..5bc95bf --- /dev/null +++ b/fleet/common.nix @@ -0,0 +1,51 @@ +# ============================================================================ +# 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 = [ + ./fs.nix + ./boot.nix + ./user-config.nix + ../sw + ../users.nix + ]; + + 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. + ''; + }; + 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)."; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf (config.athenix.forUser != null) { + athenix.users.${config.athenix.forUser}.enable = true; + }) + { + system.stateVersion = "25.11"; + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; + } + ]; +} diff --git a/glue/fleet.nix b/fleet/default.nix similarity index 92% rename from glue/fleet.nix rename to fleet/default.nix index e0714b2..e870fbd 100644 --- a/glue/fleet.nix +++ b/fleet/default.nix @@ -1,6 +1,7 @@ { inputs, - fleet ? import ../inventory.nix, + fleet ? null, + hwTypes ? null, ... }: @@ -15,8 +16,23 @@ let nixpkgs = inputs.nixpkgs; lib = nixpkgs.lib; - # Load all available host types from hosts/ - hostTypes = import ../variants { inherit inputs; }; + # 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 + inventoryModule = lib.evalModules { + modules = [ + (import ./fleet-option.nix { inherit inputs; }) + { + _module.args = { + pkgs = nixpkgs.legacyPackages.x86_64-linux; + }; + } + (lib.mkIf (fleet != null) { athenix.fleet = lib.mkForce fleet; }) + (lib.mkIf (hwTypes != null) { athenix.hwTypes = lib.mkForce hwTypes; }) + ]; + }; + + hostTypes = inventoryModule.config.athenix.hwTypes; # Helper to create a single NixOS system configuration mkHost = @@ -135,7 +151,7 @@ let allModules = userNixosModules ++ [ - (import ./common.nix { inherit inputs; }) + ./common.nix typeModule overrideModule { networking.hostName = hostName; } @@ -267,10 +283,12 @@ let { }; in lib.recursiveUpdate deviceHosts countHosts - ) fleet; + ); + + fleetData = inventoryModule.config.athenix.fleet; # Flatten the nested structure - allHosts = lib.foldl' lib.recursiveUpdate { } (lib.attrValues processInventory); + allHosts = lib.foldl' lib.recursiveUpdate { } (lib.attrValues (processInventory fleetData)); in { nixosConfigurations = lib.mapAttrs (n: v: v.system) allHosts; diff --git a/fleet/fleet-option.nix b/fleet/fleet-option.nix new file mode 100644 index 0000000..e781ba6 --- /dev/null +++ b/fleet/fleet-option.nix @@ -0,0 +1,75 @@ +# ============================================================================ +# Fleet Option Definition +# ============================================================================ +# This module only defines the athenix.fleet option without any dependencies. +# Used by fleet.nix to evaluate inventory data without circular dependencies. +{ 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 +{ + options.athenix = { + fleet = fleetDefinition; + hwTypes = lib.mkOption { + description = "Hardware types definitions for the fleet."; + type = lib.types.attrs; + }; + }; + + config.athenix.fleet = lib.mkDefault (import ../inventory.nix); + config.athenix.hwTypes = lib.mkDefault (import ../hw { inherit inputs; }); +} diff --git a/fleet/fs.nix b/fleet/fs.nix new file mode 100644 index 0000000..97fd6d0 --- /dev/null +++ b/fleet/fs.nix @@ -0,0 +1,90 @@ +# ============================================================================ +# FS & Storage Configuration +# ============================================================================ +# This module defines: +# - Disko partition layout (EFI, swap, root) +# - Filesystem options (device, swap size) + +{ config, lib, ... }: + +{ + options.athenix = { + host.filesystem = { + device = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + 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.nullOr lib.types.str; + default = null; + description = "The size of the swap partition."; + }; + }; + }; + + config = { + # ========== Disk Partitioning (Disko) ========== + disko.enableConfig = lib.mkDefault (config.athenix.host.filesystem.device != null); + + 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" + ]; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/glue/user-config.nix b/fleet/user-config.nix similarity index 100% rename from glue/user-config.nix rename to fleet/user-config.nix diff --git a/glue/boot.nix b/glue/boot.nix deleted file mode 100644 index 8e81434..0000000 --- a/glue/boot.nix +++ /dev/null @@ -1,137 +0,0 @@ -# ============================================================================ -# 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 - ''; - }; -} diff --git a/glue/common.nix b/glue/common.nix deleted file mode 100644 index c7ad4ae..0000000 --- a/glue/common.nix +++ /dev/null @@ -1,99 +0,0 @@ -# ============================================================================ -# 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; - } - ]; -} diff --git a/variants/default.nix b/hw/default.nix similarity index 76% rename from variants/default.nix rename to hw/default.nix index d91f415..5172bee 100644 --- a/variants/default.nix +++ b/hw/default.nix @@ -2,13 +2,12 @@ # 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. +# Each type is a NixOS module (a function suitable for lib.types.submodule). { inputs }: let - inherit (builtins) readDir attrNames; lib = inputs.nixpkgs.lib; + inherit (builtins) readDir attrNames; inherit (lib) filterAttrs removeSuffix genAttrs; files = readDir ./.; @@ -20,4 +19,5 @@ let moduleNames = map (name: removeSuffix ".nix" name) (attrNames nixFiles); in -genAttrs moduleNames (name: import ./${name}.nix { inherit inputs; }) +# Export: { name = ; } +genAttrs moduleNames (name: import (./. + ("/" + name + ".nix"))) diff --git a/variants/nix-desktop.nix b/hw/nix-desktop.nix similarity index 99% rename from variants/nix-desktop.nix rename to hw/nix-desktop.nix index 2455eba..d7116f9 100644 --- a/variants/nix-desktop.nix +++ b/hw/nix-desktop.nix @@ -4,7 +4,6 @@ # Hardware and boot configuration for standard desktop workstations. # Includes Intel CPU support and NVMe storage. -{ inputs, ... }: { config, lib, diff --git a/variants/nix-ephemeral.nix b/hw/nix-ephemeral.nix similarity index 99% rename from variants/nix-ephemeral.nix rename to hw/nix-ephemeral.nix index 51e46c0..3d71a81 100644 --- a/variants/nix-ephemeral.nix +++ b/hw/nix-ephemeral.nix @@ -5,7 +5,6 @@ # Suitable for kiosks, netboot clients, and stateless workstations. # All data is lost on reboot. -{ inputs, ... }: { config, lib, diff --git a/variants/nix-laptop.nix b/hw/nix-laptop.nix similarity index 99% rename from variants/nix-laptop.nix rename to hw/nix-laptop.nix index 6d9ed5c..ec0e60e 100644 --- a/variants/nix-laptop.nix +++ b/hw/nix-laptop.nix @@ -4,7 +4,6 @@ # Hardware and boot configuration for laptop systems with mobile features. # Includes power management, lid switch handling, and Intel graphics fixes. -{ inputs, ... }: { config, lib, diff --git a/variants/nix-lxc.nix b/hw/nix-lxc.nix similarity index 98% rename from variants/nix-lxc.nix rename to hw/nix-lxc.nix index cecb409..a5b161d 100644 --- a/variants/nix-lxc.nix +++ b/hw/nix-lxc.nix @@ -4,11 +4,11 @@ # Configuration for lightweight Linux containers running in Proxmox. # Disables boot/disk management and enables remote development support. -{ inputs, ... }: { config, lib, modulesPath, + inputs, ... }: { diff --git a/variants/nix-surface.nix b/hw/nix-surface.nix similarity index 82% rename from variants/nix-surface.nix rename to hw/nix-surface.nix index 53f74c4..4452f88 100644 --- a/variants/nix-surface.nix +++ b/hw/nix-surface.nix @@ -4,22 +4,13 @@ # 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, + inputs, ... }: -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") @@ -51,9 +42,6 @@ in "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 diff --git a/variants/nix-wsl.nix b/hw/nix-wsl.nix similarity index 98% rename from variants/nix-wsl.nix rename to hw/nix-wsl.nix index f13787a..6e9e6e4 100644 --- a/variants/nix-wsl.nix +++ b/hw/nix-wsl.nix @@ -4,10 +4,10 @@ # Configuration for NixOS running in WSL2 on Windows. # Integrates with nixos-wsl for WSL-specific functionality. -{ inputs, ... }: { lib, config, + inputs, ... }: { diff --git a/variants/nix-zima.nix b/hw/nix-zima.nix similarity index 98% rename from variants/nix-zima.nix rename to hw/nix-zima.nix index 1174ff0..a87ef60 100644 --- a/variants/nix-zima.nix +++ b/hw/nix-zima.nix @@ -4,7 +4,6 @@ # Hardware and boot configuration for standard desktop workstations. # Includes Intel CPU support and NVMe storage. -{ inputs, ... }: { config, lib, diff --git a/installer/PROXMOX_LXC.md b/installer/PROXMOX_LXC.md index 057e3c9..64d25ef 100644 --- a/installer/PROXMOX_LXC.md +++ b/installer/PROXMOX_LXC.md @@ -46,7 +46,7 @@ Add the host to `inventory.nix` with the `nix-lxc` type or ensure it has the app } ``` -Your host type configuration (`variants/nix-lxc.nix`) should include: +Your host type configuration (`hw/nix-lxc.nix`) should include: ```nix { diff --git a/installer/modules.nix b/installer/modules.nix index d69a837..9f59981 100644 --- a/installer/modules.nix +++ b/installer/modules.nix @@ -13,12 +13,15 @@ # inputs.athenix.nixosModules.sw { inputs }: -# Automatically import all variant modules from variants/ directory -# This returns an attribute set like: { nix-desktop = ...; nix-laptop = ...; nix-lxc = ...; sw = ...; } -(import ../variants { inherit inputs; }) -// { +# Expose hardware type modules from hw/ directory +# This returns an attribute set like: { nix-desktop = ...; nix-laptop = ...; nix-lxc = ...; } +let + hostTypes = import ../hw { inherit inputs; }; +in +{ # Software configuration module - main module with all athenix.sw options # Use athenix.sw.type to select profile: "desktop", "tablet-kiosk", "headless", "stateless-kiosk" + hw = hostTypes; sw = { inputs, diff --git a/inventory.nix b/inventory.nix index a6ce1b0..0338d8f 100644 --- a/inventory.nix +++ b/inventory.nix @@ -70,7 +70,6 @@ # rev = "e1ccd7cc3e709afe4f50b0627e1c4bde49165014"; # }; # }; - { # ========== Lab Laptops ========== # Creates: nix-laptop1, nix-laptop2 diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..372377f --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,4 @@ +{ inputs }: +{ + mkFleet = import ./mkFleet.nix; +} diff --git a/lib/mkFleet.nix b/lib/mkFleet.nix new file mode 100644 index 0000000..94a034c --- /dev/null +++ b/lib/mkFleet.nix @@ -0,0 +1,11 @@ +# Generate fleet configurations with custom fleet and hardware types +# Usage: nixosConfigurations = athenix.lib.mkFleet { fleet = { ... }; hwTypes = { ... }; } +{ + inputs, + fleet ? null, + hwTypes ? null, +}: +import ../fleet/default.nix { + inherit inputs; + inherit fleet hwTypes; +} diff --git a/sw/default.nix b/sw/default.nix index 81c372f..8ae4d39 100644 --- a/sw/default.nix +++ b/sw/default.nix @@ -28,8 +28,12 @@ in imports = [ ./python.nix ./ghostty.nix + ./gc.nix ./updater.nix ./update-ref.nix + inputs.home-manager.nixosModules.home-manager + inputs.agenix.nixosModules.default + inputs.disko.nixosModules.disko ]; options.athenix.sw = { diff --git a/sw/gc.nix b/sw/gc.nix new file mode 100644 index 0000000..e679c02 --- /dev/null +++ b/sw/gc.nix @@ -0,0 +1,58 @@ +{ + config, + lib, + pkgs, + ... +}: +{ + options.athenix = { + 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 = { + # 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; + }; +} diff --git a/sw/stateless-kiosk/net.nix b/sw/stateless-kiosk/net.nix index f8aad34..3983ab8 100644 --- a/sw/stateless-kiosk/net.nix +++ b/sw/stateless-kiosk/net.nix @@ -26,5 +26,5 @@ }; # Disable systemd-networkd and systemd-hostnamed - systemd.network.enable = false; + systemd.network.enable = lib.mkForce false; }