# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Repository Overview This is a NixOS infrastructure repository managing multiple hosts (servers and personal machines) using a modular Nix configuration approach with SOPS for secrets management and Bento for deployment. ## Build and Test Commands ```bash # Enter development shell (sets up MCP configs) nix-shell # Test configuration before deployment (required before PRs) ./scripts/test-configuration ./scripts/test-configuration -v # with --show-trace # Edit encrypted secrets nix-shell -p sops --run 'sops hosts//secrets.yaml' # Update secrets keys after adding new age keys ./scripts/update-secrets-keys # Format Nix files nix run nixpkgs#nixpkgs-fmt . # Compute hash for new packages nix hash to-sri --type sha256 $(nix-prefetch-url https://example.com/file.tar.gz) ``` ## Architecture ### Host Structure Each host in `hosts//` contains: - `configuration.nix` - Main entry point importing modules - `hardware-configuration.nix` - Machine-specific hardware config - `secrets.yaml` - SOPS-encrypted secrets - `modules/` - Host-specific service configurations - `fleet.nix` → symlink to root `fleet.nix` (SFTP user provisioning) - `utils/` → symlink to root `utils/` (shared modules) Current hosts: `fw` (firewall/router), `nb` (notebook), `web-arm`, `mail`, `amzebs-01` ### Shared Components (`utils/`) - `modules/` - Reusable NixOS modules (nginx, sops, borgbackup, lego, promtail, etc.) - `overlays/` - Nixpkgs overlays - `pkgs/` - Custom package derivations - `bento.nix` - Deployment helper module ### Secrets Management - SOPS with age encryption; keys defined in `.sops.yaml` - Each host has its own age key derived from SSH host key - Host secrets in `hosts//secrets.yaml` - Shared module secrets in `utils/modules//secrets.yaml` **IMPORTANT: Never modify secrets files directly.** Instead, tell the user which secrets need to be added and where, so they can edit the encrypted files themselves using: ```bash nix-shell -p sops --run 'sops hosts//secrets.yaml' ``` ### Deployment The Git runner handles deployment automatically when changes merge to main. A successful `./scripts/test-configuration ` dry-build is the gate before pushing. ## Custom Packages When creating a new package in `utils/pkgs/`, always include an `update.sh` script to automate version updates. See `utils/pkgs/claude-code/update.sh` for the pattern: 1. Fetch latest version from upstream (npm, GitHub, etc.) 2. Update version string in `default.nix` 3. Update source hash using `nix-prefetch-url` 4. Update dependency hashes (e.g., `npmDepsHash`) by triggering a build with a fake hash 5. Verify the final build succeeds Example structure: ``` utils/pkgs// ├── default.nix ├── update.sh # Always include this └── (other files like patches, lock files) ``` ## Workflow **IMPORTANT: Always run `./scripts/test-configuration ` after making any changes** to verify the NixOS configuration builds successfully. This is required before committing. ## Conventions - Nix files: two-space indentation, lower kebab-case naming - Commits: Conventional Commits format (`fix:`, `feat:`, `chore:`), scope by host when relevant (`fix(mail):`) - Modules import via explicit paths, not wildcards - Comments explain non-obvious decisions (open ports, unusual service options)