# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Build and Deployment Commands ### Building Configurations ```bash # Build a NixOS configuration (creates ./result symlink) just build # or nixos-rebuild build --flake .# # Build home-manager configuration home-manager build --flake .#sajenim@ ``` ### Deploying Changes ```bash # Apply NixOS configuration locally (requires sudo) just switch # or sudo nixos-rebuild switch --flake .# # Deploy to remote host just deploy # or nixos-rebuild switch --flake .# --target-host --use-remote-sudo # Apply home-manager configuration home-manager switch --flake .#sajenim@ ``` ### Code Quality ```bash # Format all Nix files using alejandra nix fmt # Check flake and evaluate all configurations nix flake check ``` ### Secret Management ```bash # Rekey secrets using YubiKey (after adding/modifying secrets) agenix-rekey edit agenix-rekey rekey ``` ## Architecture Overview ### Flake Structure This is a NixOS flake-based configuration managing two hosts: - **fuchsia**: Desktop workstation (gaming, development, XMonad) - **viridian**: Server (multimedia, services, containers) The flake follows the standard structure from Misterio77's starter configs. ### Configuration Layers **NixOS System Configuration** (`nixos/`): ``` nixos/ ├── common/ │ ├── global/ # Base system config for all hosts │ │ ├── age.nix # Agenix secret management with YubiKey │ │ ├── env.nix # Environment variables │ │ ├── nix.nix # Nix daemon, flakes, garbage collection │ │ └── ssh.nix # SSH server config │ ├── optional/ # Opt-in features │ │ ├── ephemeral-btrfs.nix # Impermanence with btrfs root wipe │ │ ├── persist.nix # Persistence paths for ephemeral root │ │ └── yubikey.nix # YubiKey support │ └── users/ # User-specific system settings ├── fuchsia/ │ ├── configuration.nix │ └── services/ # Desktop services (X11, pipewire, flatpak, etc.) └── viridian/ ├── configuration.nix ├── services/ # Server services (traefik, minecraft, IRC, etc.) └── multimedia/ # *arr stack (sonarr, radarr, jellyfin, etc.) ``` **Home-Manager User Configuration** (`home-manager/`): ``` home-manager/sajenim/ ├── global/ # Base home config ├── features/ # Modular user features │ ├── cli/ # Shell, terminal utilities │ ├── desktop/ # GUI applications, window manager │ ├── editors/ # Text editors configuration │ ├── games/ # Gaming-related configs │ ├── printing/ # Printer utilities │ └── university/ # Academic tools ├── fuchsia.nix # Desktop profile └── viridian.nix # Server profile (minimal) ``` ### Key Architectural Patterns **Module Organization**: Configuration is split between: - `nixos/common/global/`: Imported by ALL hosts (mandatory base config) - `nixos/common/optional/`: Opt-in features imported per-host - `nixos//`: Host-specific hardware and services - `home-manager/sajenim/features/`: Composable user environment features **Imports Pattern**: Each host's `configuration.nix` composes its full system by: 1. Importing `../common/global` (base system) 2. Importing selected `../common/optional/*` modules 3. Importing `../common/users/` (user accounts) 4. Importing host-specific services from `./services/` 5. Setting host-specific options (hostname, firewall, etc.) **Impermanence**: Uses opt-in persistence with ephemeral btrfs root: - Root filesystem (`/`) wiped on every boot - Only `/nix`, `/persist`, and `/boot` survive reboots - Services must explicitly declare what to persist in `/persist` - Secrets use persistent SSH keys at `/persist/etc/ssh/` for decryption **Secret Management**: - Encrypted with agenix using host SSH keys - Master key stored on YubiKey for rekeying - Rekeyed secrets stored in `nixos/common/global/secrets/rekeyed//` - Decryption happens during system activation using persistent SSH keys **Overlays**: Applied globally via `nixos/common/global/default.nix`: - `additions`: Custom packages from `pkgs/` - `modifications`: Patches to existing packages (e.g., dmenu theming) - `unstable-packages`: Makes `pkgs.unstable.*` available for newer versions **Unfree Packages**: Allowlist is centralized in `nixos/common/global/default.nix` - Default policy: only free software - Exceptions listed explicitly (steam, minecraft-server) - Do NOT use `allowUnfreePredicate` in other modules (won't merge) ### Flake Inputs External dependencies include: - `nixpkgs` (25.05 stable), `nixpkgs-unstable` - `home-manager` (follows nixpkgs) - `agenix`, `agenix-rekey` (secret management) - `impermanence` (ephemeral root filesystem) - `crowdsec` (security) - `nixvim` (personal Neovim config, external flake) - `xmonad-config` (personal XMonad config, external flake) - `nix-minecraft` (declarative Minecraft server) Personal flakes (nixvim, xmonad-config) are maintained in separate repositories and imported as flake inputs. They are updated independently via `nix flake update`. ## Working with This Configuration ### Adding a New Host 1. Create `nixos//` directory 2. Add `configuration.nix` and `hardware-configuration.nix` 3. Add SSH host keys (ed25519 and RSA) to the host directory 4. Update `flake.nix` to add the new `nixosConfiguration` 5. Configure secrets: update age.rekey to include new host key ### Adding a Service Services are organized by host in `nixos//services/`: - Create a subdirectory for complex services (e.g., `traefik/`) - Each service gets its own `default.nix` - Import in `nixos//services/default.nix` or `configuration.nix` - Declare persistence paths if using ephemeral root - Use agenix for any credentials ### Modifying Packages - **Custom packages**: Add to `pkgs/` and reference in `pkgs/default.nix` - **Patching packages**: Add patches to `overlays/patches/`, modify overlay in `overlays/default.nix` - **Unfree packages**: Add to allowlist in `nixos/common/global/default.nix` ### Testing Changes 1. Build configuration: `just build ` 2. Check for evaluation errors: `nix flake check` 3. Review changes before switching 4. Switch: `just switch ` (local) or `just deploy ` (remote) ### Managing Secrets - Secrets are encrypted per-host and stored in `nixos/common/global/secrets/rekeyed//` - Edit secrets: `agenix-rekey edit ` - After editing, rekey all hosts: `agenix-rekey rekey` - YubiKey required for rekeying operations - Host SSH keys at `/persist/etc/ssh/` are used for automatic decryption ## Important Conventions ### Line Length Keep all Nix code to a maximum of 100 characters per line for consistency. ### Module Naming - System-level services: `nixos//services//default.nix` - User-level features: `home-manager/sajenim/features//.nix` ### Persistence Declarations When adding services to hosts with ephemeral root, declare persistence: ```nix environment.persistence."/persist" = { directories = [ "/var/lib/service-name" ]; files = [ "/var/lib/service-name/config.conf" ]; }; ``` ### Comments This codebase uses structured comments to explain configuration choices: - Block comments at file top explain module purpose - Inline comments explain non-obvious configuration decisions - Group related options with visual separators when helpful