Documentation Index Fetch the complete documentation index at: https://mintlify.com/soriphoono/homelab/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The homelab uses a modular architecture to organize configurations. Modules are reusable configuration components that can be enabled or disabled with simple options.
Module Types
There are three types of modules corresponding to the three configuration types:
NixOS Modules modules/nixos/System-level configuration for NixOS systems
Home Manager Modules modules/home/User-level configuration and applications
Droid Modules modules/droid/Android device configuration via Nix-on-Droid
Module Structure
All modules are automatically discovered and imported using a discovery mechanism:
modules/nixos/default.nix
{ lib , ... }: let
modules = lib . discover ./. ;
in
modules
// {
default = {
imports = builtins . attrValues modules ;
};
}
This means any .nix file you add to a module directory is automatically available in your configurations.
NixOS Modules
Located in modules/nixos/, these modules configure system-level settings.
Module Categories
Essential system configuration: modules/nixos/core/
├── boot.nix # Bootloader configuration
├── clamav.nix # Antivirus
├── gitops.nix # Automatic updates
├── nixconf.nix # Nix daemon configuration
├── secrets.nix # SOPS secrets management
├── users.nix # User management
├── hardware/
│ ├── default.nix # Hardware detection
│ ├── adb.nix # Android Debug Bridge
│ ├── bluetooth.nix # Bluetooth support
│ ├── gpu/ # GPU drivers
│ └── hid/ # Input devices
└── networking/
├── network-manager.nix
├── openssh.nix
├── tailscale.nix
└── ...
Usage: core = {
boot . enable = true ;
hardware . enable = true ;
networking . tailscale . enable = true ;
secrets . enable = true ;
} ;
Desktop environment configuration: modules/nixos/desktop/
├── default.nix
├── environments/
│ ├── kde.nix
│ ├── cosmic.nix
│ ├── display_managers/
│ └── managers/
├── features/
│ ├── gaming.nix
│ ├── printing.nix
│ └── virtualisation.nix
└── services/
├── asusd.nix
├── flatpak.nix
└── pipewire.nix
Usage: desktop = {
environments . kde . enable = true ;
features = {
gaming . enable = true ;
printing . enable = true ;
virtualisation . enable = true ;
};
services . asusd . enable = true ;
} ;
Server and hosting configuration: modules/nixos/hosting/
├── default.nix
├── single-node/
│ ├── default.nix
│ ├── modules/
│ └── standalone/
└── clustering/
├── default.nix
└── backends/
Usage: hosting . single-node . enable = true ;
or hosting . clustering = {
enable = true ;
backend = "k3s" ;
} ;
Home Manager Modules
Located in modules/home/, these modules configure user environments.
Module Categories
Essential user configuration: modules/home/core/
├── checks.nix # Configuration validation
├── git.nix # Git configuration
├── gitops.nix # Auto-update hooks
├── secrets.nix # User secrets
├── ssh.nix # SSH configuration
└── shells/
├── fish.nix
├── starship.nix
└── fastfetch.nix
Usage: core = {
git = {
userName = "user" ;
userEmail = "user@example.com" ;
};
shells . fish . generateCompletions = true ;
secrets . enable = true ;
} ;
User applications organized by category: modules/home/userapps/
├── browsers/
│ ├── firefox.nix
│ ├── chrome.nix
│ ├── librewolf.nix
│ └── floorp.nix
├── development/
│ ├── editors/
│ │ ├── neovim.nix
│ │ ├── vscode.nix
│ │ └── antigravity.nix
│ ├── terminal/
│ │ ├── kitty.nix
│ │ ├── ghostty.nix
│ │ └── warp.nix
│ ├── agents/
│ │ ├── mcp-servers.nix
│ │ └── clients/
│ └── domain_specific/
│ └── k8s.nix
├── communication/
│ └── discord.nix
├── data-fortress/
│ ├── bitwarden.nix
│ └── nextcloud.nix
└── office/
└── onlyoffice.nix
Usage: userapps = {
enable = true ;
browsers . firefox . enable = true ;
development = {
enable = true ;
editors . neovim . enable = true ;
terminal . ghostty . enable = true ;
};
communication . discord . enable = true ;
} ;
Droid Modules
Located in modules/droid/, these modules configure Nix-on-Droid environments.
modules/droid/
├── default.nix
├── nixconf.nix # Nix configuration
└── users.nix # User environment
Usage:
core . user . shell = pkgs . fish ;
Creating Custom Modules
Basic Module Structure
A module typically follows this pattern:
modules/nixos/example/feature.nix
{
lib ,
config ,
pkgs ,
...
}: let
cfg = config . example . feature ;
in {
options . example . feature = {
enable = lib . mkEnableOption "Enable example feature" ;
setting = lib . mkOption {
type = lib . types . str ;
default = "default-value" ;
description = "An example setting" ;
example = "custom-value" ;
};
};
config = lib . mkIf cfg . enable {
# Your configuration here
environment . systemPackages = with pkgs ; [
# packages
];
};
}
Real Module Example
Here’s the actual hardware module from the homelab:
modules/nixos/core/hardware/default.nix
{
lib ,
config ,
...
}: let
cfg = config . core . hardware ;
in {
imports = [
./gpu
./hid
./adb.nix
./bluetooth.nix
];
options . core . hardware = {
enable = lib . mkEnableOption "Enable hardware support" ;
reportPath = lib . mkOption {
type = lib . types . path ;
description = "The default report path for facter input modules" ;
example = ./facter.json ;
};
};
config = lib . mkIf cfg . enable {
facter = {
inherit ( cfg ) reportPath ;
};
};
}
Home Manager Module Example
The Git module with advanced options:
modules/home/core/git.nix
{
lib ,
config ,
...
}: let
cfg = config . core . git ;
in {
options . core . git = {
userName = lib . mkOption {
type = lib . types . str ;
description = "The git username to use for this user" ;
example = "john" ;
};
userEmail = lib . mkOption {
type = lib . types . str ;
description = "The git email to use for this user" ;
example = "john@gmail.com" ;
};
projectsDir = lib . mkOption {
type = lib . types . path ;
description = "The directory where git projects are stored" ;
default = config . home . homeDirectory + "/Documents/Projects" ;
example = "/run/media/john_doe/Projects" ;
};
extraIdentities = lib . mkOption {
type = with lib ; with types ;
attrsOf ( submodule {
options = {
directory = mkOption {
type = str ;
description = "The directory of the group of projects" ;
example = "Work" ;
};
name = mkOption {
type = str ;
description = "The name to use for this identity" ;
example = "john_work" ;
};
email = mkOption {
type = str ;
description = "The email to use for this identity" ;
example = "john_work@gmail.com" ;
};
signingKey = mkOption {
type = str ;
description = "The SSH public key for signing commits" ;
example = "ssh-ed25519 AAAA..." ;
};
};
});
default = {};
};
};
config = {
programs . git = {
enable = true ;
userName = cfg . userName ;
userEmail = cfg . userEmail ;
signing = {
format = "ssh" ;
key = config . core . ssh . publicKey ;
signByDefault = true ;
};
# Include conditional configs for extra identities
includes = lib . mapAttrsToList ( _ : identity : {
condition = "gitdir: ${ cfg . projectsDir } / ${ identity . directory } /" ;
contents . user = {
inherit ( identity ) name email signingKey ;
};
}) cfg . extraIdentities ;
};
};
}
Module Options
Common Option Types
Creates a boolean option that defaults to false enable = lib . mkEnableOption "Enable the feature" ;
Creates a custom option with type, default, and description setting = lib . mkOption {
type = lib . types . str ;
default = "value" ;
description = "Description" ;
example = "example" ;
} ;
Common Types
lib.types.bool - Boolean (true/false)
lib.types.str - String
lib.types.int - Integer
lib.types.path - File path
lib.types.package - Nix package
lib.types.listOf <type> - List of items
lib.types.attrsOf <type> - Attribute set
lib.types.submodule - Nested module
lib.types.enum [...] - One of the listed values
Conditional Configuration
Use lib.mkIf to apply configuration only when an option is enabled:
config = lib . mkIf cfg . enable {
# This only applies when enable = true
};
Use lib.mkMerge to merge multiple conditional blocks:
config = lib . mkMerge [
( lib . mkIf cfg . enable {
# Always enabled config
})
( lib . mkIf cfg . extraFeature {
# Extra feature config
})
] ;
Module Imports
Modules can import other modules:
modules/nixos/desktop/default.nix
{
lib ,
config ,
...
}: let
cfg = config . desktop ;
in {
imports = [
./environments
./features/gaming.nix
./features/printing.nix
./features/virtualisation.nix
./services/asusd.nix
./services/pipewire.nix
./services/flatpak.nix
];
options . desktop = {
enable = lib . mkEnableOption "Enable core desktop configurations" ;
};
config = lib . mkIf cfg . enable {
desktop . services = {
pipewire . enable = true ;
flatpak . enable = true ;
};
};
}
Best Practices
Use namespaces - Organize options under logical namespaces (core, desktop, userapps)
Provide defaults - Always provide sensible defaults for options
Document everything - Use description and example fields
Use enable options - Gate configuration behind enable flags
Keep modules focused - Each module should do one thing well
Use conditional imports - Only import what’s needed
Test modules - Test your modules on different systems
Module Discovery
The module system uses lib.discover to automatically find and import modules:
{ lib , ... }: let
modules = lib . discover ./. ;
in
modules // {
default = {
imports = builtins . attrValues modules ;
};
}
This means:
Any .nix file in the module directory is automatically loaded
Subdirectories are recursively scanned
No manual import list to maintain
Debugging Modules
Check Module Options
List all available options:
nixos-option desktop.environments.kde
View Module Values
See the current value of an option:
nixos-option desktop.environments.kde.enable
Test Module Configuration
Build without switching:
nixos-rebuild build --flake .#system-name
Common Patterns
Feature Flag Pattern
options . feature = {
enable = lib . mkEnableOption "Enable feature" ;
package = lib . mkOption {
type = lib . types . package ;
default = pkgs . feature ;
description = "Package to use" ;
};
extraOptions = lib . mkOption {
type = lib . types . lines ;
default = "" ;
description = "Extra configuration" ;
};
} ;
config = lib . mkIf cfg . enable {
environment . systemPackages = [ cfg . package ];
# More config...
} ;
Multiple Choice Pattern
options . backend = lib . mkOption {
type = lib . types . enum [ "option1" "option2" "option3" ];
default = "option1" ;
description = "Which backend to use" ;
} ;
config = lib . mkMerge [
( lib . mkIf ( cfg . backend == "option1" ) {
# Option 1 config
})
( lib . mkIf ( cfg . backend == "option2" ) {
# Option 2 config
})
] ;
Next Steps
Systems Configure NixOS systems
Home Manager Configure user environments
Creating Modules Learn how to create modules
Contributing Contribute your own modules