Skip to main content

Introduction

This homelab provides a comprehensive collection of reusable NixOS modules organized into three main categories:
  • Core - Essential system configuration (boot, networking, secrets, users)
  • Desktop - Desktop environment and features
  • Hosting - Single-node and clustering infrastructure

Module Structure

Modules are located in modules/nixos/ and follow a hierarchical structure:
modules/nixos/
├── core/           # Core system modules
│   ├── boot.nix
│   ├── gitops.nix
│   ├── hardware/
│   ├── networking/
│   ├── secrets.nix
│   ├── users.nix
│   └── clamav.nix
├── desktop/        # Desktop environment modules
│   ├── environments/
│   ├── features/
│   └── services/
└── hosting/        # Hosting/clustering modules
    ├── single-node/
    └── clustering/

Using Modules

Modules are imported automatically when you use the homelab flake. Simply enable them in your system configuration:
# systems/my-system/default.nix
{
  core = {
    boot.enable = true;
    networking.tailscale.enable = true;
    users.myuser = {
      admin = true;
      hashedPassword = "...";
    };
  };

  desktop = {
    environments.kde.enable = true;
  };

  hosting = {
    single-node.enable = true;
  };
}

Module Categories

Core Modules

Core modules provide essential system functionality:
  • Boot - Systemd-boot, ZRAM swap, Plymouth, secure boot
  • GitOps - Automated system updates from Git repositories
  • Hardware - GPU, Bluetooth, HID device support
  • Networking - Network Manager, Tailscale, OpenSSH
  • Secrets - SOPS-based secret management
  • Users - Declarative user management with home-manager integration
  • ClamAV - Antivirus scanning and protection
View Core Module Reference →

Desktop Modules

Desktop modules configure graphical environments:
  • Environments - KDE Plasma, COSMIC desktop
  • Display Managers - SDDM, greetd
  • Window Managers - Hyprland with UWSM
  • Features - Gaming, printing, virtualization
  • Services - PipeWire, Flatpak, ASUS laptop tools
View Desktop Module Reference →

Hosting Modules

Hosting modules enable container and cluster orchestration:
  • Single-Node - Docker-based container hosting with Traefik reverse proxy
  • Clustering - K3s Kubernetes clusters with multi-node support
View Hosting Module Reference →

Configuration Patterns

Basic System Configuration

A minimal desktop system:
{
  core = {
    boot.enable = true;
    hardware.enable = true;
    networking.network-manager.enable = true;
    users.alice = {
      admin = true;
      hashedPassword = "$y$j9T$...";
      publicKey = "ssh-ed25519 AAAA...";
    };
  };

  desktop.environments.kde.enable = true;
}

Server with Container Hosting

A server with Docker and Tailscale:
{
  core = {
    boot.enable = true;
    networking = {
      ipv4_address = "192.168.1.100";
      tailscale.enable = true;
    };
    secrets = {
      enable = true;
      defaultSopsFile = ./secrets.yaml;
    };
    users.sysadmin = {
      admin = true;
      publicKey = "ssh-ed25519 AAAA...";
    };
  };

  hosting = {
    single-node.enable = true;
    enableNvidiaSupport = true;
  };
}

Multi-Node Kubernetes Cluster

K3s leader node:
{
  core = {
    boot.enable = true;
    networking = {
      ipv4_address = "10.0.0.10";
      tailscale.enable = true;
    };
    secrets.enable = true;
  };

  hosting.clustering.backends.k3s = {
    enable = true;
    mode = "leader";
    nodeIP = "10.0.0.10";
  };
}
K3s agent node:
{
  hosting.clustering.backends.k3s = {
    enable = true;
    mode = "agent";
    leaderIP = "https://10.0.0.10:6443";
    nodeIP = "10.0.0.11";
  };
}

Module Development

Creating a New Module

Modules follow the standard NixOS module pattern:
{
  lib,
  config,
  pkgs,
  ...
}: let
  cfg = config.myCategory.myModule;
in {
  options.myCategory.myModule = {
    enable = lib.mkEnableOption "My module description";
    
    setting = lib.mkOption {
      type = lib.types.str;
      default = "default-value";
      description = "Description of this setting";
      example = "example-value";
    };
  };

  config = lib.mkIf cfg.enable {
    # Module implementation
  };
}

Best Practices

  1. Use enable options - Every module should have an enable option
  2. Provide defaults - Sensible defaults reduce configuration burden
  3. Add examples - Show real-world usage in option descriptions
  4. Document options - Clear descriptions for all configurable options
  5. Use assertions - Validate incompatible option combinations
  6. Integrate with home-manager - Extend user configurations when appropriate

Next Steps

Build docs developers (and LLMs) love