Files
nixos/CLAUDE.md

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 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/<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:

  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/<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)