Module Architecture
This configuration uses the Pure Module Pattern with 20+ modules organized across 10 categories. Each module defines options that can be explicitly enabled, following the NixOS module system best practices.
Design Philosophy
Unlike traditional Nix configurations where importing a module immediately activates it, this repository uses Pure Modules with explicit mkEnableOption:
- Import the bundle to make options available
- Explicitly enable what you want with
enable = true - Safe defaults - everything defaults to disabled
Example - Pure Module Pattern
# Import the bundle (makes options available)
imports = [
../../modules/desktop # plasma, sddm available but inactive
];
# Explicitly choose what to enable
desktop.plasma.enable = true;
desktop.sddm.enable = true;
desktop.sddm.theme = "sugar-dark"; # Optional configuration
# Other options available but NOT active:
# desktop.hyprland.enable = false; # Implicit - not enabled
Module Categories
Desktop Bundle (modules/desktop/)
Available options:
desktop.plasma.enable- KDE Plasma 6 desktop environmentdesktop.plasma.lookAndFeel- Theme selectiondesktop.sddm.enable- SDDM display managerdesktop.sddm.theme- Optional theme (e.g., "sugar-dark")
User-level (modules/home/desktop/):
home.desktop.plasma.enable- Plasma user settings via plasma-managerhome.desktop.hyprland.enable- Hyprland window managerhome.desktop.hyprland.enableNvidiaPatches- GPU-specific fixes
Hardware Bundle (modules/hardware/)
Available options:
modules.hardware.nvidia.enable- NVIDIA GPU driversmodules.hardware.nvidia.open- Use open-source kernel modules (Turing+)modules.hardware.nvidia.powerManagement.enable- VRAM save on sleep (experimental)modules.hardware.bluetooth.enable- Bluetooth subsystemmodules.hardware.bluetooth.powerOnBoot- Auto-power behavior (default: false)modules.hardware.bluetooth.guiManager- Enable blueman GUI
Media Bundle (modules/media/)
Available options:
media.audio.enable- PipeWire audio stackmedia.audio.server- Choose: "pipewire" | "pulse" | "alsa" | "none"media.audio.lowLatency- Use Zen kernel (⚠️ changes kernel!)media.audio.proAudio- JACK support, real-time limits, Bitwig Studiomedia.audio.user- User to add to audio group (default: "brancengregory")
Network Modules (modules/network/)
Already using Pure Module pattern:
networking.wireguard-mesh.enable- WireGuard VPN meshservices.caddy.enable- Reverse proxyservices.netbird.enable- Netbird VPN
OS Modules (modules/os/)
Base system modules (always-on):
common.nix- Universal settings (flakes, experimental flags)nixos.nix- NixOS-specific system configurationdarwin.nix- macOS-specific system configuration
These are imported directly by lib.mkHost, not via bundles.
Security Modules (modules/security/)
Already using Pure Module pattern:
security.gpg.enable- Declarative GPG key importsecurity.ssh.hostKeysDeclarative.enable- SSH host key managementsops(via sops-nix module) - Secret management
Services Bundle (modules/services/)
Available options (all using Pure Module pattern):
services.backup.enable- Restic backup with configurable repository, pathsservices.monitoring.enable- Prometheus/Grafana stackservices.monitoring.exporters.enable- Lightweight node exporters (all nodes)services.monitoring.server.enable- Heavy Prometheus/Grafana server (monitoring host only)
services.download-stack.enable- qBittorrent, SABnzbdservices.git-server.enable- Forgejo Git serverservices.media.enable- Jellyfin, *arr appsservices.ollama-server.enable- Ollama LLM serverservices.opencode-server.enable- OpenCode serverservices.storage.enable- Minio, NFS, mergerfs, SnapRAID
Virtualization Bundle (modules/virtualization/)
Available options:
virtualization.podman.enable- Container engine (Docker replacement)virtualization.podman.dockerCompat- Create 'docker' aliasvirtualization.podman.dnsEnabled- Container-to-container DNSvirtualization.hypervisor.enable- Run VMs (libvirtd, virt-manager, QEMU)virtualization.hypervisor.virtManager- Enable virt-manager GUIvirtualization.hypervisor.swtpm- Software TPM (for Windows 11 VMs)virtualization.hypervisor.spice- SPICE protocol supportvirtualization.guest.enable- QEMU guest agent (for when this machine IS a VM)
Critical: Use hypervisor when running VMs, guest when this is a VM. Never enable hypervisor inside a VM!
Themes Bundle (modules/themes/)
Available options:
themes.stylix.enable- Unified theming systemthemes.stylix.image- Wallpaper paththemes.stylix.base16Scheme- Color scheme filethemes.stylix.autoEnable- Auto-enable all targets (default: false)
Host Configuration Pattern
Modern host configurations use the lib.mkHost abstraction:
Example: Server (capacitor)
# flake.nix
capacitor = lib.mkHost {
hostname = "capacitor";
system = "x86_64-linux";
user = "brancengregory";
builder = nixpkgs.lib.nixosSystem;
homeManagerModule = home-manager.nixosModules.home-manager;
sopsModule = sops-nix.nixosModules.sops;
isDesktop = false; # Headless server
extraModules = [ inputs.disko.nixosModules.disko ];
};
# hosts/capacitor/config.nix
{ config, pkgs, ... }: {
imports = [
../../modules/services # All services available
../../modules/virtualization # Podman available
# No desktop, hardware, or media bundles - this is a server!
];
# Enable only what the server needs
services.backup.enable = true;
services.monitoring = {
enable = true;
exporters.enable = true;
server.enable = true; # This is the monitoring host
};
virtualization.podman.enable = true;
virtualization.hypervisor.enable = false; # Don't run VMs on server
system.stateVersion = "25.11";
}
Example: Desktop (powerhouse)
# flake.nix
powerhouse = lib.mkHost {
hostname = "powerhouse";
system = "x86_64-linux";
user = "brancengregory";
builder = nixpkgs.lib.nixosSystem;
homeManagerModule = home-manager.nixosModules.home-manager;
sopsModule = sops-nix.nixosModules.sops;
isDesktop = true;
extraModules = [
inputs.disko.nixosModules.disko
inputs.plasma-manager.homeModules.plasma-manager
];
};
# hosts/powerhouse/config.nix
{ config, pkgs, ... }: {
imports = [
../../modules/desktop # Plasma, SDDM available
../../modules/hardware # NVIDIA, Bluetooth available
../../modules/media # Audio available
../../modules/services # Backup, monitoring available
../../modules/virtualization # Podman, QEMU available
../../modules/themes # Stylix available
];
# Desktop Environment
desktop.plasma.enable = true;
desktop.sddm.enable = true;
themes.stylix.enable = true;
# Hardware
modules.hardware.nvidia.enable = true;
modules.hardware.bluetooth.enable = true;
# Audio (Pro audio setup)
media.audio.enable = true;
media.audio.lowLatency = true;
media.audio.proAudio = true;
# Services
services.backup.enable = true;
services.monitoring = {
enable = true;
exporters.enable = true; # Just the lightweight exporter
server.enable = false; # Don't run heavy server on desktop
};
# Virtualization (Run VMs, not a VM)
virtualization.podman.enable = true;
virtualization.hypervisor = {
enable = true;
virtManager = true;
swtpm = true; # For Windows 11 VMs
};
system.stateVersion = "25.11";
}
User Configuration Pattern
User configurations (users/*/home.nix) are imported automatically by lib.mkHost. They should use the standard home-manager module pattern:
{ config, pkgs, lib, isLinux, isDesktop, ... }: {
imports = [
../../modules/home/desktop/plasma.nix # If using plasma
];
# Desktop-specific settings
home.desktop.plasma = lib.mkIf isDesktop {
enable = true;
virtualDesktops = 4;
};
# Program configurations
programs.git.enable = true;
programs.zsh.enable = true;
}
Adding New Modules
1. Create the Module
# modules/category/my-module.nix
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.category.myModule;
in {
options.category.myModule = {
enable = mkEnableOption "my module description";
someOption = mkOption {
type = types.str;
default = "default-value";
description = "Description of this option";
};
};
config = mkIf cfg.enable {
# Configuration only applied when enabled
services.myService.enable = true;
services.myService.setting = cfg.someOption;
};
}
2. Add to Bundle (if applicable)
# modules/category/default.nix
{ lib, ... }: {
imports = [
./my-module.nix
./existing-module.nix
];
}
3. Import Bundle in Host Config
# hosts/my-host/config.nix
{
imports = [
../../modules/category # Import the bundle
];
# Enable the specific module
category.myModule.enable = true;
category.myModule.someOption = "custom-value";
}
4. Test
# Validate syntax
nix flake check
# Test specific host
mise build-my-host
Module Dependencies
Modules can reference other modules' options:
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.myService;
in {
options.services.myService = {
enable = mkEnableOption "my service";
};
config = mkIf cfg.enable {
# Reference another module's option
services.dependency.enable = mkDefault true;
# Or check if another module is enabled
environment.systemPackages = mkIf config.services.backup.enable [
pkgs.restic
];
};
}
Best Practices
- Always use
mkEnableOptionwithdefault = false - Namespace options to avoid conflicts (e.g.,
modules.hardware.nvidianot justnvidia) - Guard with
mkIf cfg.enable- don't apply config when disabled - Use bundles - group related modules in
default.nix - Explicit over implicit - no "magic" activation via imports
- Document options - provide clear descriptions and examples
Complete Option Reference
Desktop
desktop.plasma.enabledesktop.plasma.lookAndFeeldesktop.sddm.enabledesktop.sddm.theme
Hardware
modules.hardware.nvidia.enablemodules.hardware.nvidia.openmodules.hardware.nvidia.powerManagement.enablemodules.hardware.nvidia.powerManagement.finegrainedmodules.hardware.nvidia.nvidiaSettingsmodules.hardware.bluetooth.enablemodules.hardware.bluetooth.powerOnBootmodules.hardware.bluetooth.guiManager
Media
media.audio.enablemedia.audio.servermedia.audio.lowLatencymedia.audio.proAudiomedia.audio.user
Services
services.backup.enableservices.monitoring.enableservices.monitoring.exporters.enableservices.monitoring.exporters.portservices.monitoring.exporters.collectorsservices.monitoring.server.enableservices.monitoring.server.prometheusPortservices.monitoring.server.grafanaPortservices.monitoring.server.grafanaBindservices.download-stack.enableservices.git-server.enableservices.media.enableservices.ollama-server.enableservices.opencode-server.enableservices.storage.enable
Virtualization
virtualization.podman.enablevirtualization.podman.dockerCompatvirtualization.podman.dnsEnabledvirtualization.podman.extraPackagesvirtualization.hypervisor.enablevirtualization.hypervisor.virtManagervirtualization.hypervisor.swtpmvirtualization.hypervisor.spicevirtualization.guest.enablevirtualization.guest.spice
Themes
themes.stylix.enablethemes.stylix.imagethemes.stylix.base16Schemethemes.stylix.autoEnable
Home Desktop
home.desktop.plasma.enablehome.desktop.plasma.lookAndFeelhome.desktop.plasma.virtualDesktopshome.desktop.hyprland.enablehome.desktop.hyprland.enableNvidiaPatches