3.2 KiB
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
# Enter development shell (sets up MCP configs)
nix-shell
# Test configuration before deployment (required before PRs)
./scripts/test-configuration <hostname>
./scripts/test-configuration -v <hostname> # with --show-trace
# Edit encrypted secrets
nix-shell -p sops --run 'sops hosts/<hostname>/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/<hostname>/ contains:
configuration.nix- Main entry point importing moduleshardware-configuration.nix- Machine-specific hardware configsecrets.yaml- SOPS-encrypted secretsmodules/- Host-specific service configurationsfleet.nix→ symlink to rootfleet.nix(SFTP user provisioning)utils/→ symlink to rootutils/(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 overlayspkgs/- Custom package derivationsbento.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/<hostname>/secrets.yaml - Shared module secrets in
utils/modules/<module>/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:
nix-shell -p sops --run 'sops hosts/<hostname>/secrets.yaml'
Deployment
The Git runner handles deployment automatically when changes merge to main. A successful ./scripts/test-configuration <host> 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:
- Fetch latest version from upstream (npm, GitHub, etc.)
- Update version string in
default.nix - Update source hash using
nix-prefetch-url - Update dependency hashes (e.g.,
npmDepsHash) by triggering a build with a fake hash - Verify the final build succeeds
Example structure:
utils/pkgs/<package-name>/
├── default.nix
├── update.sh # Always include this
└── (other files like patches, lock files)
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)