# AGENTS.md - NixOS Configuration Repository This document provides guidelines for AI agents working on this NixOS flake configuration. ## Repository Overview Multi-host NixOS flake managing servers and workstations with home-manager integration. - **Hosts**: m3-aether, m3-ares, m3-atlas, m3-helios, m3-kratos - **User**: m3tam3re - **Key inputs**: nixpkgs (unstable), home-manager, agenix, disko, nix-colors ## Build/Rebuild Commands ```bash # NixOS system rebuild sudo nixos-rebuild switch --flake .# sudo nixos-rebuild switch --flake .#m3-atlas # Home-manager rebuild home-manager --flake . switch home-manager --flake .#m3tam3re@m3-daedalus switch # Flake operations nix flake check # Validate flake nix flake update # Update all inputs nix flake lock --update-input # Update single input # Development shell nix develop .#infraShell # OpenTofu + nixos-anywhere # Format Nix files alejandra . # Format all .nix files alejandra # Format single file ``` ## Testing No formal test suite. Verification is done via: ```bash nix flake check # Syntax and evaluation check nix build .#nixosConfigurations..config.system.build.toplevel --dry-run ``` ## Directory Structure ``` . ├── flake.nix # Flake definition with all hosts ├── secrets.nix # Agenix public key mappings ├── home/ │ ├── common/ # Shared home-manager config (overlays, nix settings) │ ├── features/ # Modular features │ │ ├── cli/ # Shell tools (fish, nushell, starship, zellij) │ │ ├── coding/ # Development tools │ │ └── desktop/ # GUI apps, Hyprland, theming │ └── m3tam3re/ # Per-host user configs ├── hosts/ │ ├── common/ # Shared NixOS config │ │ ├── extraServices/ # Toggle-able services (ollama, podman, flatpak) │ │ ├── users/ # User definitions │ │ └── ports.nix # Port allocations │ └── m3-*/ # Host-specific configs │ ├── default.nix # Entry point (imports common + host modules) │ ├── configuration.nix # Core system config │ ├── hardware-configuration.nix │ ├── programs.nix # Host-specific programs │ ├── secrets.nix # Agenix secret declarations │ └── services/ # Service configurations │ └── containers/ # OCI container definitions ├── modules/ # Custom NixOS/home-manager modules ├── overlays/ # Nixpkgs overlays (stable, locked, pinned, master) ├── pkgs/ # Custom package definitions └── secrets/ # Encrypted .age files ``` ## Code Style Guidelines ### Module Pattern Standard Nix module structure: ```nix { config, lib, pkgs, ... }: { imports = [ ./submodule.nix ]; # Configuration here } ``` ### Formatting - **Formatter**: Use `alejandra` (included in CLI packages) - **Indentation**: 2 spaces - **Line length**: No strict limit, but keep readable - **Trailing commas**: Required in lists and attrsets - **Semicolons**: Required after each attribute ### Naming Conventions | Type | Convention | Example | |------|------------|---------| | Files | lowercase, hyphenated | `hardware-configuration.nix` | | Hosts | `m3-` | `m3-atlas`, `m3-kratos` | | Options | camelCase path | `extraServices.ollama.enable` | | Feature flags | `features...enable` | `features.cli.nushell.enable` | | Secrets | `-env.age` or descriptive | `n8n-env.age`, `wg-DE.age` | ### Option Definitions Use lib functions for custom options: ```nix { config, lib, pkgs, ... }: with lib; let cfg = config.features.cli.myFeature; in { options.features.cli.myFeature.enable = mkEnableOption "enable myFeature"; config = mkIf cfg.enable { # Configuration when enabled }; } ``` ### Imports - Import order: inputs/modules first, then local files - Use relative paths: `./subdir` or `../common` - Group related imports together ### Package Lists ```nix home.packages = with pkgs; [ package1 package2 # Commented packages for reference # disabled-package ]; ``` ## Secrets Management Uses **agenix** for encrypted secrets. ### Adding a New Secret 1. Create the secret file: ```bash agenix -e secrets/my-secret.age ``` 2. Register in `secrets.nix`: ```nix "secrets/my-secret.age".publicKeys = systems ++ users; ``` 3. Declare in host's `secrets.nix`: ```nix age.secrets.my-secret = { file = ../../secrets/my-secret.age; owner = "service-user"; # Optional mode = "644"; # Optional }; ``` 4. Reference in config: ```nix environmentFiles = [config.age.secrets.my-secret.path]; ``` ## Container Services Pattern OCI containers via podman: ```nix {config, ...}: { virtualisation.oci-containers.containers."service-name" = { image = "registry/image:tag"; environmentFiles = [config.age.secrets.service-env.path]; ports = ["127.0.0.1:8080:8080"]; volumes = ["service_data:/data"]; extraOptions = ["--network=web"]; }; # Traefik routing services.traefik.dynamicConfigOptions.http = { services.service-name.loadBalancer.servers = [ { url = "http://localhost:8080/"; } ]; routers.service-name = { rule = "Host(`service.domain.com`)"; tls.certResolver = "godaddy"; service = "service-name"; entrypoints = "websecure"; }; }; } ``` ## Theming Uses **nix-colors** with Dracula scheme: ```nix colorScheme = inputs.nix-colors.colorSchemes.dracula; # Reference colors "#${config.colorScheme.palette.base00}" # Background "#${config.colorScheme.palette.base05}" # Foreground ``` ## Overlays Custom overlays in `overlays/default.nix`: - `stable-packages`: nixpkgs-stable as `pkgs.stable.*` - `locked-packages`: Pinned nixpkgs as `pkgs.locked.*` - `master-packages`: nixpkgs-master as `pkgs.master.*` Use when you need a specific package version: ```nix home.packages = [ pkgs.stable.somePackage ]; ``` ## Common Pitfalls 1. **Missing imports**: Ensure new files are imported in parent `default.nix` 2. **Secret paths**: Use `config.age.secrets..path`, not hardcoded paths 3. **Rebuild required**: Changes need `nixos-rebuild` or `home-manager switch` 4. **Overlay scope**: Overlays must be added to both `home/common` and `hosts/common` 5. **Port conflicts**: Check `hosts/common/ports.nix` before allocating new ports ## Commit Style Short, descriptive messages: - `flake update` - Dependency updates - `+package` - Adding new package - `service-name: description` - Service changes - `host: description` - Host-specific changes