This is a Nix-based dotfiles and homelab management repository using Clan.lol for infrastructure orchestration. It manages NixOS systems, home-manager configurations, and secrets across multiple machines.
- Nix/NixOS: Primary build system and package manager (flakes-based)
- Clan.lol: Infrastructure management and deployment (
nixos-anywhere,disko,nixos-facter) - Home Manager: User environment configuration
- SOPS: Secrets management with age encryption
- flake-parts: Modular flake composition
# Build a machine configuration
nix build .#nixosConfigurations.<machine>.config.system.build.toplevel
# Build a package
nix build .#<package>
# Deploy configuration to a machine
clan machines update <machine>
# Update system with nh (Nix Helper)
nh os switch
# Format all project files with treefmt
nix fmtdesktop- Main desktop workstationlaptop- Laptop configurationserver- Homelab servernas- NAS/storage servermiro- Additional machinetester- Testing environment
nix build .#nixosConfigurations.<host>.config.system.build.toplevel
# Format all files (Nix, Lua, Python, Shell, YAML, TOML, Markdown)
nix fmt
# Verify formatting in CI mode (exits 1 if unformatted)
nix fmt -- --ci
# Check flake evaluation and formatting
nix flake check
# Lint Lua files (for Neovim configs)
luacheck <file>├── flake.nix # Flake entry point
├── settings.nix # Shared settings module (username, email, etc.)
├── overlays.nix # Nixpkgs overlays
├── machines/ # Per-machine configurations
│ ├── flake-module.nix # Machine definitions for clan
│ ├── desktop/
│ ├── laptop/
│ └── server/
├── homeModules/ # Home-manager modules
│ ├── home/ # Home configuration
│ ├── desktop/ # Desktop environment
│ ├── dev/ # Development tools
│ └── cybersec/ # Security tools
├── nixosModules/ # NixOS system modules
│ ├── base/ # Base system configuration
│ ├── core/ # Core system features
│ └── homelab/ # Homelab services
├── pkgs/ # Custom packages
├── sops/ # SOPS secrets configuration
├── terranix/ # Infrastructure as code (Terraform)
└── vars/ # Clan variables
Formatting:
- Indentation: 2 spaces
- Line length: ~100 characters (soft limit)
- Use
let ... infor local variable bindings - Use
inheritto bring values into scope
Module Structure:
{lib, ...}: {
options.modules.<name> = {
enable = lib.mkEnableOption "description";
optionName = lib.mkOption {
type = lib.types.str;
default = "value";
description = "Option description";
};
};
imports = [
./submodule.nix
];
}Naming Conventions:
- Module options:
modules.<category>.<name> - Enable options:
enable(within the module namespace) - Variables:
snake_caseorcamelCase(prefersnake_casein Nix) - Constants:
UPPER_CASEfor special values - Function parameters: Destructure with
{lib, config, pkgs, ...}:
Imports and Dependencies:
- Always include
libas first parameter - Use
inherit (lib) mkOption mkEnableOption types;for frequently used functions - Follow inputs with
inputsattribute for flake inputs - Use
specialArgsto pass additional arguments to modules
Comments:
- Inline comments after option definitions:
# brief description - Avoid redundant comments that repeat the code
- Use comments for non-obvious behavior or rationale
Formatting:
- Indentation: 4 spaces
- Line length: 88 characters (Black default)
- 2 blank lines between top-level functions
- 1 blank line between methods
Type Hints:
- Use type hints for function parameters and return types
- Use
|for union types (Python 3.10+):str | None
Style:
def function_name(param: str) -> tuple[str | None, str | None]:
"""Brief docstring."""
if condition:
return None, None
return value1, value2Formatting:
- Use
stylua.tomlconfiguration - Indentation: 2 spaces
- Sort requires alphabetically
- Collapse simple statements for functions only
Linting:
- Use
luacheckwith.luacheckrc - Globals:
vim,Status,Header,ui,cx,ya
- Secrets are encrypted using SOPS (Secrets OPerationS) with age
- Key location:
age1n2ct0ecqtnhpcf8q27f0yvf6n3y0jjcuwer9rhxv9fqkfj0ktdfsycxfu0 - Pattern:
secrets/[^/]+\.(yaml|json|env|ini)$ - Store in
sops/directory (notsecrets/which is deprecated) - Never commit plaintext secrets
- Main branch:
main - Use meaningful commit messages
- CI builds all machine configurations on PRs affecting
flake.lock - Supported hosts: server, desktop, laptop
- Create directory in
machines/<name>/ - Add
default.nixwith machine-specific configuration - Add
disko.nixfor disk partitioning (if needed) - Add to
machines/flake-module.nixinventory - Generate SSH host keys in
vars/per-machine/<name>/
- Create file in
homeModules/<category>/<name>.nix - Export from
homeModules/<category>/default.nix - Import in
homeModules/<category>/default.nixif applicable - Follow existing module pattern with
optionsandconfig
- Create package definition in
pkgs/<name>.nix - Add to
pkgs/pkgs.nixexports - Update package versions using
nurlornix-update
GitHub Actions workflows in .github/workflows/:
build.yml- Builds all machine configurationsformat-check.yml- Verifies all files are formatted with treefmtupdate-flake-lock.yml- Updates flake.lock automaticallyopencode.yml- OpenCode integration