formatter and lxc configuration

This commit is contained in:
UGA Innovation Factory
2025-12-10 14:52:34 +00:00
parent d4835360f5
commit 14202a8233
23 changed files with 742 additions and 308 deletions

View File

@@ -47,7 +47,10 @@
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
extraArgs = [ "-n" "BOOT" ];
extraArgs = [
"-n"
"BOOT"
];
};
};
@@ -56,7 +59,9 @@
name = "swap";
label = "swap";
size = config.host.filesystem.swapSize;
content = { type = "swap"; };
content = {
type = "swap";
};
};
# Root Partition (takes remaining space)
@@ -68,7 +73,10 @@
type = "filesystem";
format = "ext4";
mountpoint = "/";
extraArgs = [ "-L" "ROOT" ];
extraArgs = [
"-L"
"ROOT"
];
};
};
};

View File

@@ -1,4 +1,8 @@
{ inputs, hosts ? import ../inventory.nix, ... }:
{
inputs,
hosts ? import ../inventory.nix,
...
}:
# ============================================================================
# Host Generator
@@ -10,10 +14,10 @@
# 3. External flake integration for system overrides.
let
nixpkgs = inputs.nixpkgs;
lib = nixpkgs.lib;
nixpkgs = inputs.nixpkgs;
lib = nixpkgs.lib;
home-manager = inputs.home-manager;
disko = inputs.disko;
disko = inputs.disko;
# Modules shared by all hosts
commonModules = [
@@ -25,35 +29,44 @@ let
disko.nixosModules.disko
{
system.stateVersion = "25.11";
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
# Automatic Garbage Collection
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
# Optimize storage
nix.optimise.automatic = true;
}
];
# Helper to create a single NixOS system configuration
mkHost = { hostName, system ? "x86_64-linux", extraModules ? [ ] }:
mkHost =
{
hostName,
system ? "x86_64-linux",
extraModules ? [ ],
}:
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.modules.users.accounts or {};
accounts = usersData.modules.users.accounts or { };
# Extract flakeUrls and convert to modules
userFlakeModules = lib.mapAttrsToList (name: user:
userFlakeModules = lib.mapAttrsToList (
name: user:
if (user ? flakeUrl && user.flakeUrl != "") then
(builtins.getFlake user.flakeUrl).nixosModules.default
else
{}
{ }
) accounts;
in
lib.nixosSystem {
@@ -71,56 +84,85 @@ let
};
# Function to generate a set of hosts based on inventory count and overrides
mkHostGroup = { prefix, count, system ? "x86_64-linux", extraModules ? [], deviceOverrides ? {} }:
lib.listToAttrs (map (i: {
name = "${prefix}${toString i}";
value =
mkHostGroup =
{
prefix,
count,
system ? "x86_64-linux",
extraModules ? [ ],
deviceOverrides ? { },
}:
lib.listToAttrs (
lib.concatMap (
i:
let
devConf = deviceOverrides.${toString i} or {};
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;
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 {};
externalModule = if externalFlake != null then externalFlake.nixosModules.default else { };
# Config override module (filesystem, users)
overrideModule = { ... }:
overrideModule =
{ ... }:
let
# Remove special keys that are not filesystem options
fsConf = builtins.removeAttrs devConf [ "extraUsers" "flakeUrl" ];
in lib.mkIf hasOverride {
fsConf = builtins.removeAttrs devConf [
"extraUsers"
"flakeUrl"
"hostname"
];
in
lib.mkIf hasOverride {
host.filesystem = fsConf;
modules.users.enabledUsers = devConf.extraUsers or [];
modules.users.enabledUsers = devConf.extraUsers or [ ];
};
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
mkHost {
hostName = "${prefix}${toString i}";
inherit system;
extraModules = extraModules ++ [ overrideModule ] ++ (lib.optional (externalFlake != null) externalModule);
};
}) (lib.range 1 count));
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:
hostGroups = lib.mapAttrsToList (
type: config:
let
typeFile = ./types + "/${type}.nix";
modules = if builtins.pathExists typeFile
then import typeFile { inherit inputs; }
else throw "Host type '${type}' not found in hosts/types/";
modules =
if builtins.pathExists typeFile then
import typeFile { inherit inputs; }
else
throw "Host type '${type}' not found in hosts/types/";
in
mkHostGroup {
prefix = type;
inherit (config) count;
extraModules = modules;
deviceOverrides = config.devices or {};
}
mkHostGroup {
prefix = type;
inherit (config) count;
extraModules = modules;
deviceOverrides = config.devices or { };
}
) hosts;
in
lib.foldl' lib.recursiveUpdate {} hostGroups
lib.foldl' lib.recursiveUpdate { } hostGroups

View File

@@ -1,24 +1,42 @@
{ inputs, ... }: [
({ config, lib, modulesPath, ... }: {
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
{ inputs, ... }:
[
(
{
config,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
boot.kernelParams = [
"quiet"
"splash"
"boot.shell_on_fail"
"udev.log_priority=3"
"rd.systemd.show_status=auto"
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"nvme"
"usb_storage"
"sd_mod"
"sdhci_pci"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
boot.kernelParams = [
"quiet"
"splash"
"boot.shell_on_fail"
"udev.log_priority=3"
"rd.systemd.show_status=auto"
];
host.filesystem.swapSize = lib.mkDefault "16G";
host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
})
{ modules.sw.enable = true; modules.sw.type = "desktop"; }
host.filesystem.swapSize = lib.mkDefault "16G";
host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
)
{
modules.sw.enable = true;
modules.sw.type = "desktop";
}
]

View File

@@ -1,12 +1,27 @@
{ inputs, ... }: [
({ config, lib, modulesPath, ... }: {
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
{ inputs, ... }:
[
(
{
config,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
boot.kernelParams = [
boot.initrd.availableKernelModules = [
"xhci_pci"
"thunderbolt"
"nvme"
"usb_storage"
"sd_mod"
"sdhci_pci"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
boot.kernelParams = [
"quiet"
"splash"
"boot.shell_on_fail"
@@ -17,21 +32,25 @@
"i915.enable_fbc=0"
];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
host.filesystem.swapSize = lib.mkDefault "34G";
host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
host.filesystem.swapSize = lib.mkDefault "34G";
# Suspend / logind behavior
services.upower.enable = true;
services.logind.settings = {
Login = {
HandleLidSwitch = "suspend";
HandleLidSwitchExternalPower = "suspend";
HandleLidSwitchDocked = "ignore";
# Suspend / logind behavior
services.upower.enable = true;
services.logind.settings = {
Login = {
HandleLidSwitch = "suspend";
HandleLidSwitchExternalPower = "suspend";
HandleLidSwitchDocked = "ignore";
};
};
};
})
{ modules.sw.enable = true; modules.sw.type = "desktop"; }
}
)
{
modules.sw.enable = true;
modules.sw.type = "desktop";
}
]

40
hosts/types/nix-lxc.nix Normal file
View File

@@ -0,0 +1,40 @@
{ inputs, ... }:
[
inputs.vscode-server.nixosModules.default
(
{
config,
lib,
modulesPath,
...
}:
{
nix.settings.trusted-users = [
"root"
"engr-ugaif"
];
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
imports = [
"${modulesPath}/virtualisation/proxmox-lxc.nix"
];
boot.isContainer = true;
boot.loader.systemd-boot.enable = lib.mkForce false;
disko.enableConfig = lib.mkForce false;
console.enable = true;
systemd.services."getty@".unitConfig.ConditionPathExists = [
""
"/dev/%I"
];
systemd.suppressedSystemUnits = [
"dev-mqueue.mount"
"sys-kernel-debug.mount"
"sys-fs-fuse-connections.mount"
];
services.vscode-server.enable = true;
system.stateVersion = "25.11";
}
)
]

View File

@@ -1,40 +1,58 @@
{ inputs, ... }: [
({ config, lib, pkgs, modulesPath, ... }:
let
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, ... }:
[
(
{
config,
lib,
pkgs,
modulesPath,
...
}:
let
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") ];
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
boot.kernelParams = [
"quiet"
"splash"
"boot.shell_on_fail"
"udev.log_priority=3"
"rd.systemd.show_status=auto"
"intel_ipu3_imgu"
"intel_ipu3_isys"
"fbcon=map:1"
"i915.enable_psr=0" # Panel Self Refresh breaks resume on Surface
"i915.enable_dc=0"
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"nvme"
"usb_storage"
"sd_mod"
"sdhci_pci"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
boot.kernelParams = [
"quiet"
"splash"
"boot.shell_on_fail"
"udev.log_priority=3"
"rd.systemd.show_status=auto"
"intel_ipu3_imgu"
"intel_ipu3_isys"
"fbcon=map:1"
"i915.enable_psr=0" # Panel Self Refresh breaks resume on Surface
"i915.enable_dc=0"
];
boot.kernelPackages = lib.mkForce refKernelPackages;
boot.kernelPackages = lib.mkForce refKernelPackages;
host.filesystem.swapSize = lib.mkDefault "8G";
host.filesystem.device = lib.mkDefault "/dev/mmcblk0";
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
})
host.filesystem.swapSize = lib.mkDefault "8G";
host.filesystem.device = lib.mkDefault "/dev/mmcblk0";
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
)
inputs.nixos-hardware.nixosModules.microsoft-surface-go
{ modules.sw.enable = true; modules.sw.type = "kiosk"; }
{
modules.sw.enable = true;
modules.sw.type = "kiosk";
}
]

View File

@@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
# ============================================================================
# User Configuration Module
@@ -11,19 +16,63 @@ 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 = []; };
flakeUrl = lib.mkOption { type = lib.types.str; default = ""; description = "URL of a flake to import Home Manager configuration from (e.g. github:user/dotfiles)."; };
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."; };
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."; };
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 = [ ];
};
flakeUrl = lib.mkOption {
type = lib.types.str;
default = "";
description = "URL of a flake to import Home Manager configuration from (e.g. github:user/dotfiles).";
};
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.";
};
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.";
};
};
};
in
@@ -36,71 +85,85 @@ in
};
accounts = lib.mkOption {
type = lib.types.attrsOf userSubmodule;
default = {};
default = { };
description = "User accounts configuration.";
};
enabledUsers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
default = [ ];
description = "List of users to enable on this system.";
};
};
config = {
# Default enabled users (always present)
modules.users.enabledUsers = [ "root" "engr-ugaif" ];
modules.users.enabledUsers = [
"root"
"engr-ugaif"
];
# Generate NixOS users
users.users =
users.users =
let
enabledAccounts = lib.filterAttrs (name: _: lib.elem name config.modules.users.enabledUsers) config.modules.users.accounts;
enabledAccounts = lib.filterAttrs (
name: _: lib.elem name config.modules.users.enabledUsers
) config.modules.users.accounts;
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 config.modules.users.shell;
}
) enabledAccounts;
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 config.modules.users.shell;
}
) enabledAccounts;
# Home Manager configs per user
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = { osConfig = config; };
extraSpecialArgs = {
osConfig = config;
};
users =
users =
let
enabledAccounts = lib.filterAttrs (name: _: lib.elem name config.modules.users.enabledUsers) config.modules.users.accounts;
enabledAccounts = lib.filterAttrs (
name: _: lib.elem name config.modules.users.enabledUsers
) config.modules.users.accounts;
in
lib.mapAttrs (name: user: { ... }:
lib.mapAttrs (
name: user:
{ ... }:
let
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 ++ lib.optional user.useNvimPlugins ../sw/nvim.nix;
in
if isExternal then {
# External users: Only apply requested system modules.
# The external flake is responsible for home.username, home.packages, etc.
imports = commonImports;
} else {
# Local users: Apply full configuration.
imports = user.extraImports ++ commonImports;
home.username = name;
home.homeDirectory = if name == "root" then "/root" else "/home/${name}";
home.stateVersion = "25.11";
home.packages = user.homePackages;
}
if isExternal then
{
# External users: Only apply requested system modules.
# The external flake is responsible for home.username, home.packages, etc.
imports = commonImports;
}
else
{
# Local users: Apply full configuration.
imports = user.extraImports ++ commonImports;
home.username = name;
home.homeDirectory = if name == "root" then "/root" else "/home/${name}";
home.stateVersion = "25.11";
home.packages = user.homePackages;
}
) enabledAccounts;
};
};