Code Showcase

Everything on this page is copied from the repository, not written for the brochure. Each block links to the file it came from.


▸ One builder, not nine

Adding a machine is one function call. The machine type is a parameter, not a separate function — per-variant wrappers are an anti-pattern this repo explicitly avoids.

flake.nixregister a host
nixosConfigurations = flakeUtils.allConfigurations // {

my-desktop = flakeUtils.mkSystem {
hostname = "my-desktop"; # must match the hosts/ directory name
profile = "workstation"; # workstation, server, laptop,
}; # gaming, development, minimal

my-server = flakeUtils.mkSystem {
hostname = "my-server";
profile = "server";
system = "aarch64-linux"; # defaults to x86_64-linux
extraModules = [ ./hosts/my-server/services.nix ];
};
};

mkSystem wires in Home Manager, agenix and a flake-metadata module for every host, so you never repeat that boilerplate.

lib/flake-utils.nixwhat you get for free
modules = [
  ../hosts/${hostname}/configuration.nix
  home-manager.nixosModules.home-manager
  agenix.nixosModules.default

({ lib, ... }: {
home-manager = {
useGlobalPkgs = lib.mkDefault true;
useUserPackages = lib.mkDefault true;
extraSpecialArgs = { inherit inputs; };
};
})
] ++ extraModules;

▸ Profiles compose, hosts override

A host’s home.nix imports the profiles it wants and overrides only what is genuinely machine-specific. No copy-pasted package lists.

hosts/desktop-template/home.nixcomposition
{
  imports = [
    ../../home/profiles/base.nix         # git, shell, core CLI tools
    ../../home/profiles/desktop.nix      # GUI apps and desktop tooling
    ../../home/profiles/development.nix  # languages and dev tools
  ];

home = {
username = "user";
homeDirectory = "/home/user";
};

# Override only what differs on this machine

programs.git = {
userName = "Desktop User";
userEmail = "<user@example.com>";
};
}

The profiles themselves stay DRY. Shell aliases are defined once and shared by both shells rather than duplicated:

home/profiles/base.nixdefine once, use twice
let
  commonAliases = {
    ll = "ls -alF";
    la = "ls -A";
    ".." = "cd ..";
    gs = "git status";
    ga = "git add";
    gc = "git commit";
    #
  };
in
{
  programs.bash = {
    # mkDefault so hosts can override individual aliases without conflicts
    shellAliases = lib.mkDefault commonAliases;
  };
  programs.zsh = {
    shellAliases = lib.mkDefault commonAliases;
  };
}

▸ Modules are options, not opinions

Every module declares typed options and stays inert until enabled, so you can compose them without fighting defaults.

modules/hardware/gpu/nvidia.nixtyped options
let
  cfg = config.modules.hardware.gpu.nvidia;
  gpuCfg = config.modules.hardware.gpu;
  isDesktop = builtins.elem gpuCfg.profile [ "desktop" "gaming" ];
  isCompute = builtins.elem gpuCfg.profile [ "ai-compute" "server-compute" ];
in
{
  options.modules.hardware.gpu.nvidia = {
    enable = lib.mkEnableOption "NVIDIA GPU support";

    driver = lib.mkOption {
      type = lib.types.enum [
        "stable" "beta" "production" "legacy_470" "legacy_390" "open"
      ];
      default = "stable";
      description = "NVIDIA driver branch to use";
    };

};
}

Turning it on is a line in your host:

hosts/<host>/configuration.nixenable it
modules.hardware.gpu.nvidia = {
  enable = true;
  driver = "production";
};

▸ The anti-patterns this repo refuses

These came out of real community review. The rules live in NIXOS-ANTI-PATTERNS.md and are enforced by statix, deadnix and code review.

✗ don'tmkIf true
services.myservice.enable =
  mkIf cfg.enable true;

light.enable =
mkIf (cfg.profile == "laptop") true;
✓ dotrust the module system
services.myservice.enable = cfg.enable;

light.enable =
cfg.profile == "laptop";
✗ don'tmagic auto-discovery
discoverModules = dir:
  let
    entries = builtins.readDir dir;
    # ... 30+ lines of filtering
  in modulePaths;
✓ doexplicit imports
imports = [
  ./core
  ./desktop
  ./development
  ./hardware
];
✗ don'tsecrets at eval time
# Copies the secret into the
# world-readable Nix store
services.myservice.password =
  builtins.readFile "/secrets/pw";
✓ doagenix, read at runtime
age.secrets.db-password.file =
  ../secrets/db-password.age;

services.myservice.passwordFile =
config.age.secrets.db-password.path;

▸ Secrets stay encrypted in git

agenix is wired into every host built by mkSystem. Secrets are age-encrypted in the repository and decrypted to tmpfs at boot — never into the Nix store.

modules/security/agenix.nixruntime decryption
options.modules.security.agenix = {
  enable = mkEnableOption "Age-based secret management with agenix";

secretsPath = mkOption {
type = types.str;
default = "/run/agenix"; # tmpfs — in memory, not on disk
description = "Base path where decrypted secrets are stored at runtime.";
};
};

See AGENIX-SECRETS.md for the full workflow.


▸ Desktops are Wayland-only, and configured as modules

GNOME, Hyprland and niri. All three are Wayland-native; there is no X11 session and no KDE. The two tiling compositors take their configuration from Home Manager, so a host overrides one binding instead of replacing a whole file.

home/profiles/hyprland.nixstructured, not a string
wayland.windowManager.hyprland = {
  enable = true;
  xwayland.enable = true;   # Steam and older Electron apps still work

  settings = {
    "$mod" = "SUPER";
    decoration.rounding = 10;

    bind = [
      "$mod, Q, exec, alacritty"
      "$mod, R, exec, wofi --show drun"
    ]
    # 20 workspace bindings, generated rather than written out twice
    ++ builtins.concatMap (i: [
      "$mod, ${toString i}, workspace, ${toString i}"
      "$mod SHIFT, ${toString i}, movetoworkspace, ${toString i}"
    ]) (builtins.genList (n: n + 1) 10);
  };
};

niri has no module in nixpkgs or Home Manager, so the template pulls in niri-flake for one — actions are real Nix values, not strings in a KDL blob.

home/profiles/niri.nixtyped actions
programs.niri.settings.binds =
  with config.lib.niri.actions;
  {
    "Mod+T".action = spawn "alacritty";
    "Mod+Q".action = close-window;

    # niri's `spawn` has no shell, so a pipeline needs spawn-sh.
    # The old config passed "$(slurp)" and "|" as literal argv.
    "Print".action = spawn-sh ''grim -g "$(slurp)" - | wl-copy'';

    "Mod+WheelScrollDown" = {
      action = focus-workspace-down;
      cooldown-ms = 150;
    };
  };
Why this matters. These were a 158-line hyprland.conf and a 228-line config.kdl, written as inline Nix strings into /etc. System-wide, so nothing could be overridden per user, and a config language embedded in a Nix string gets no LSP, no formatter and one extra indent on every line.

▸ Quality is a build gate, not a promise

nix flake check evaluates every host and builds every lint gate. If a host stops evaluating, CI goes red.

flake.nixchecks
checks = forAllSystems (system: {
  statix-check     = ...;   # lints every .nix file
  deadnix-check    = ...;   # fails on unused declarations
  shellcheck-check = ...;   # every script in scripts/
  treefmt          = ...;   # nixfmt + shfmt + mdformat + yamlfmt + prettier
  pre-commit-check = ...;
  vm-test-desktop  = ...;   # boots a real VM and asserts on services
  vm-test-server   = ...;
}
// nixpkgs.lib.optionalAttrs (system == "x86_64-linux") {
  wsl2-config = self.nixosConfigurations.wsl2-template.config.system.build.toplevel;
  wsl2-home   = self.homeConfigurations."nixos@wsl2-template".activationPackage;
});

The VM tests boot an actual machine and assert against it:

flake.nixvm-test-server
machine.start()
machine.wait_for_unit("multi-user.target")

machine.wait_for_unit("sshd.service")
machine.succeed("systemctl is-active sshd")
machine.succeed("systemctl is-active firewall")

machine.shutdown()
Run it yourself. nix flake check reproduces the whole suite locally — the same thing CI runs, with no extra setup.