# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Repo purpose Flake-based NixOS configuration for Wayne's LAN servers and workstation. There is no application code here — changes are Nix module edits that affect real machines when deployed. ## Safety rules (read before touching anything) - **Never** run `nixos-rebuild switch|boot|test`, `nixos-install`, `parted`, `mkfs`, `mkswap`, `swapon`, `mount`, or any other destructive disk/deploy command from an agent session, even if asked indirectly. Deployment is done manually by the operator on the target host. - Validation is limited to evaluation, linting, formatting checks, and `nix build --dry-run --no-link`. - Do not add secrets, tokens, private keys, or new password hashes to the repo. - This repo currently contains **committed password hashes** (e.g. `prepare.sh`, `hosts/nixos/configuration.nix`) and SSH public keys (e.g. `modules/nix-cache/server.nix`). The hashes are known tech debt — do not use them as a template for new hosts, and flag any *new* secret-like string you encounter instead of committing it. ## Commands ```bash # One-time environment bootstrap (installs Nix if missing, prints hosts) bash scripts/codex-setup.sh # Full validation: secret grep, nixpkgs-fmt --check, statix lint, eval all hosts bash scripts/codex-maintenance.sh # Same, plus a dry-run build (no result symlink) of every host's toplevel bash scripts/codex-maintenance.sh dry-run # List the hosts the flake currently exposes nix eval --json .#nixosConfigurations --apply builtins.attrNames | jq -r '.[]' # Evaluate a single host without building (fast sanity check) nix eval .#nixosConfigurations..config.system.build.toplevel.drvPath --raw # Dry-run build a single host nix build --dry-run --no-link .#nixosConfigurations..config.system.build.toplevel ``` Formatting/lint tools (`nixpkgs-fmt`, `statix`) are not installed locally; the maintenance script pulls them via `nix run github:NixOS/nixpkgs/nixos-25.11#`. There is no test suite — "correctness" here means the flake evaluates and `nixpkgs-fmt`/`statix` are clean. ## Architecture `flake.nix` is the single entry point. It defines one `nixosConfigurations.` attribute per machine, each built the same way: ``` nixosSystem { modules = [ disko.nixosModules.disko ./hosts//configuration.nix # host-specific config ./modules/hardware-configuration/vm/.nix home-manager.nixosModules.home-manager { ... } ]; } ``` Hosts currently defined in `flake.nix`: `nixos`, `docker`, `server`, `nix-cache`, `nix-minimal`, `pxe-boot`, `linode-minimal`. Treat `flake.nix` as the source of truth for which hosts exist — `README.md`, `AGENTS.md`, `docs/flake-lock-automation.md`, and the CI eval workflows (`.github/workflows/check-nixos.yml`, `.gitea/workflows/check-nixos.yml`) list hosts by hand and can drift from it, so re-check them against `flake.nix` when adding or removing a host. ### Composition pattern Every host's real configuration lives in `hosts//configuration.nix`, which is a thin list of `imports` pulling in reusable pieces from `modules/`: - `modules/common/configuration.nix` — base NixOS config imported by (almost) every host: locale, users, nix settings, git. Nearly always the first import. - `modules/common/home.nix` / `hosts//home.nix` — Home Manager config for the `nixos` user; the `nixos` workstation has its own, other hosts share `modules/common/home.nix`. - `modules/disko/proxmox.nix` — declarative disk layout (GPT: ESP + swap + ext4 root) via disko, used by all Proxmox-VM hosts. - `modules/boot/efi.nix` — systemd-boot + EFI vars, paired with the disko module. - `modules/hardware-configuration/vm/{proxmox,linode}.nix` — hypervisor-specific hardware config, wired in from `flake.nix` (not from the host file). - `modules/nix-cache/{client,server}.nix` + `modules/remote-builder-client.nix` — binary cache substituter + SSH remote-builder wiring; see `docs/nix-cache.md` for the full design (per-host local stores, no shared `/nix/store`, and how the `nixremote` signing/SSH keys fit together). - `modules/tailscale/`, `modules/docker/`, `modules/beszel/`, `modules/services/*` — single-purpose, single-host feature modules (e.g. `docker/enable-service.nix`, `services/zfs/enable-service.nix`, `beszel/enable-agent.nix` for monitoring). Grep `hosts/*/configuration.nix` for the `imports` list to see which modules apply to a given host. New host = new `hosts//configuration.nix` + a matching block added to `flake.nix`'s `nixosConfigurations`, composed from existing `modules/*` pieces rather than duplicating config. ### Other docs worth reading before touching these areas - `docs/nix-cache.md` — nix-cache binary cache/remote-builder design and key handling. - `docs/pxe-boot.md` — the `pxe-boot` host's iPXE/TFTP/HTTP boot chain and directory layout under `/srv/pxe`. - `docs/flake-lock-automation.md` — how `flake.lock` updates flow through CI (scheduled `nix flake update` PR + host-eval-on-PR workflow) and why hosts should track the committed lock file rather than `nixos-rebuild --upgrade-all`.