From c021af7d80189c6c1eddcda215c74f1cceeb08d2 Mon Sep 17 00:00:00 2001 From: steffen Date: Wed, 11 Mar 2026 08:43:48 +0100 Subject: [PATCH] Update AGENTS.md with SD image pipeline and current project structure - Add SD image build commands - Add deployment commands (deploy-rs, nixos-rebuild) - Update directory structure with docs/, lib/, apps/ - Add key patterns for new Pi hosts and SOPS - Add deployment workflows table - Remove reference to deleted INSTRUCTIONS.md --- AGENTS.md | 254 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 167 insertions(+), 87 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 91c1fbf..0a661f5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,114 +1,194 @@ # Agent Guidelines for NixOS Configuration ## Project Overview -This repository contains a NixOS configuration managed with Nix Flakes. It defines system configurations for one or more hosts (currently `cryodev-main` and `cryodev-pi`), custom packages, modules, overlays, and templates. -## Environment & Build Commands +This repository contains a NixOS configuration managed with Nix Flakes. It defines: +- **Hosts**: `cryodev-main` (x86_64 server), `cryodev-pi` (aarch64 Raspberry Pi) +- **Modules**: Reusable NixOS modules in `modules/nixos/` +- **Packages**: Custom packages in `pkgs/` +- **Templates**: `raspberry-pi`, `generic-server` for bootstrapping new hosts + +## Build & Development Commands ### Prerequisites -- **Nix** with Flakes enabled. -- **Git** +- **Nix** with Flakes enabled +- **Git** ### Core Commands -- **Build Host Configuration**: - ```bash - nix build .#nixosConfigurations..config.system.build.toplevel - # Examples: - nix build .#nixosConfigurations.cryodev-main.config.system.build.toplevel - nix build .#nixosConfigurations.cryodev-pi.config.system.build.toplevel - ``` -- **Format Code**: - ```bash - nix fmt - ``` - This uses the formatter defined in `flake.nix` (typically `nixfmt` via `pre-commit-hooks`). -- **Run Checks (Lint/Test)**: - ```bash - nix flake check - ``` - This validates the flake outputs and runs configured checks (including formatting checks and deploy-rs checks). -- **Update Flake Inputs**: - ```bash - nix flake update - ``` -### Development Shell -You can enter a development shell with necessary tools (if configured in `devShells`): ```bash +# Build host configuration +nix build .#nixosConfigurations.cryodev-main.config.system.build.toplevel +nix build .#nixosConfigurations.cryodev-pi.config.system.build.toplevel + +# Build Raspberry Pi SD image (requires binfmt on x86_64) +nix build .#nixosConfigurations.cryodev-pi.config.system.build.sdImage + +# Format code (required before committing) +nix fmt + +# Run all checks (lint, formatting, deploy-rs validation) +nix flake check + +# Quick evaluation test (faster than full build) +nix eval .#nixosConfigurations.cryodev-main.config.system.build.toplevel.name + +# Update flake inputs +nix flake update + +# Enter development shell nix develop ``` +### Deployment + +```bash +# Deploy to cryodev-main via deploy-rs +nix run github:serokell/deploy-rs -- .#cryodev-main + +# Manual deployment via SSH +nixos-rebuild switch --flake .# --target-host root@ +``` + ## Code Style & Conventions -### General Nix Style -- **Formatting**: Strictly adhere to `nixfmt` style. Run `nix fmt` before committing. -- **Indentation**: Use 2 spaces for indentation. -- **Lines**: Limit lines to 80-100 characters where possible, but follow the formatter's lead. -- **Comments**: Use `#` for single-line comments. Avoid block comments `/* ... */` unless necessary for large blocks of text. +### Formatting +- **Tool**: `nixfmt` via pre-commit hooks +- **Run**: `nix fmt` before every commit +- **Indentation**: 2 spaces +- **Line length**: 80-100 characters (follow formatter) ### Module Structure -- **Function Header**: Always use the standard module arguments pattern: - ```nix - { config, lib, pkgs, inputs, outputs, constants, ... }: - ``` - - Include `inputs`, `outputs`, and `constants` if you need access to flake inputs, the flake's own outputs, or the central constants. -- **Option Definitions**: - - Define options in `options = { ... };`. - - Implement configuration in `config = { ... };`. - - Use `mkEnableOption` for boolean flags. - - Use `mkOption` with types (e.g., `types.str`, `types.bool`) and descriptions. -- **Imports**: - - Use relative paths for local modules: `imports = [ ./module.nix ];`. - - Use `inputs` or `outputs` for external/shared modules: `imports = [ outputs.nixosModules.common ];`. + +```nix +# Standard module pattern +{ config, lib, pkgs, inputs, outputs, constants, ... }: + +let + cfg = config.services.myService; +in +{ + options.services.myService = { + enable = lib.mkEnableOption "My service"; + port = lib.mkOption { + type = lib.types.port; + default = 8080; + description = "Port to listen on"; + }; + }; + + config = lib.mkIf cfg.enable { + # Implementation here + }; +} +``` ### Naming Conventions -- **Files**: `kebab-case.nix` (e.g., `hardware-configuration.nix`). -- **Options**: `camelCase` (e.g., `services.myService.enable`). -- **Variables**: `camelCase` in `let ... in` blocks. +| Type | Convention | Example | +|------|------------|---------| +| Files | kebab-case | `hardware-configuration.nix` | +| Options | camelCase | `services.myService.enable` | +| Variables | camelCase | `let myValue = ...;` | +| Hosts | kebab-case | `cryodev-main`, `cryodev-pi` | -### Flake Specifics -- **Inputs**: Defined in `flake.nix`. - - `nixpkgs`: Main package set (typically following a stable release). - - `nixpkgs-unstable`: Unstable channel for latest packages. -- **Outputs**: - - `nixosConfigurations`: Host definitions. - - `nixosModules`: Reusable modules exported by this flake. - - `packages`: Custom packages exported by this flake. - - `overlays`: Overlays to modify `nixpkgs`. - - `templates`: Project templates for creating new hosts. +### Imports +```nix +# Local modules: relative paths +imports = [ ./hardware.nix ./networking.nix ]; + +# Shared modules: via outputs +imports = [ outputs.nixosModules.common ]; + +# External inputs +imports = [ inputs.sops-nix.nixosModules.sops ]; +``` + +### Constants +Use `constants.nix` for domains, IPs, and ports: +```nix +{ constants, ... }: +{ + services.nginx.virtualHosts."${constants.services.forgejo.fqdn}" = { ... }; +} +``` ### Error Handling -- Use `assert` for critical configuration invariants. -- Use `warnings` or `trace` for deprecation or non-critical issues during evaluation. -- Example: - ```nix - config = lib.mkIf cfg.enable { - assertions = [ - { assertion = cfg.port > 1024; message = "Port must be non-privileged"; } - ]; - }; - ``` +```nix +config = lib.mkIf cfg.enable { + assertions = [ + { assertion = cfg.port > 1024; message = "Port must be > 1024"; } + ]; + warnings = lib.optional (cfg.debug) "Debug mode enabled!"; +}; +``` + +### Option Conflicts +Use `lib.mkDefault` for default values that can be overridden: +```nix +services.nginx.enable = lib.mkDefault true; +``` ## Directory Structure -- `flake.nix`: Entry point, defines inputs and outputs. -- `hosts/`: Specific host configurations. - - `/default.nix`: Host entry point. -- `modules/`: Reusable NixOS modules. - - `nixos/`: Modules specific to NixOS (e.g. `nixvim`, `comin`, `forgejo`). -- `pkgs/`: Custom package definitions. -- `overlays/`: Nixpkgs overlays. -- `templates/`: Templates for bootstrapping new hosts (`raspberry-pi`, `generic-server`). -- `scripts/`: Helper scripts (e.g., `install.sh` for bootstrapping). -- `constants.nix`: Central configuration for domains, IPs, and ports. -- `INSTRUCTIONS.md`: Setup and deployment instructions (DNS, SOPS, bootstrap). -- `README.md`: General project documentation and architecture overview. + +``` +. +├── flake.nix # Entry point, inputs/outputs +├── constants.nix # Central config (domains, IPs, ports) +├── hosts/ +│ ├── cryodev-main/ # x86_64 server +│ │ ├── default.nix # Host entry point +│ │ ├── hardware.nix # Hardware configuration +│ │ ├── services/ # Service configurations +│ │ └── secrets.yaml # SOPS-encrypted secrets +│ └── cryodev-pi/ # aarch64 Raspberry Pi +├── modules/nixos/ # Reusable modules +│ ├── common/ # Shared base configuration +│ ├── sops/ # Secret management +│ ├── forgejo/ # Git server +│ ├── headscale/ # VPN control server +│ └── ... +├── lib/utils.nix # Helper functions +├── apps/ # Nix apps (rebuild) +├── pkgs/ # Custom packages +├── overlays/ # Nixpkgs overlays +├── templates/ # Host templates +├── scripts/ # Helper scripts (install.sh) +└── docs/ # Documentation +``` + +## Key Patterns + +### Adding a New Raspberry Pi Host +1. Copy template: `cp -r templates/raspberry-pi hosts/new-pi` +2. Update `hosts/new-pi/networking.nix` (hostname) +3. Add to `flake.nix`: `new-pi = mkNixosConfiguration "aarch64-linux" [ ./hosts/new-pi ];` +4. Add to `.forgejo/workflows/build-pi-image.yml` matrix +5. Push → SD image is built automatically + +### SOPS Secrets +- Secrets encrypted with age using SSH host keys +- Config in `.sops.yaml`, secrets in `hosts//secrets.yaml` +- Reference: `config.sops.secrets."path/to/secret".path` + +### Special Args Available in Modules +- `inputs`: Flake inputs (nixpkgs, sops-nix, etc.) +- `outputs`: This flake's outputs (nixosModules, packages) +- `constants`: Values from `constants.nix` +- `lib`: Extended nixpkgs.lib with `lib.utils` ## Deployment Workflows -- **cryodev-main**: Push-based deployment via Forgejo Actions using `deploy-rs`. -- **cryodev-pi**: Pull-based deployment using `comin` (polling the repository). -## Working with Agents -- **Context**: When asking for changes, specify if it's for a specific host (`hosts/cryodev-main`) or a shared module (`modules/`). -- **Verification**: Always run `nix flake check` after changes to ensure validity. -- **Refactoring**: When moving code, update `imports` carefully. -- **Constants**: Use `constants.nix` for values like domains, IPs, and ports instead of hardcoding them in modules. +| Host | Strategy | Trigger | +|------|----------|---------| +| `cryodev-main` | Push via deploy-rs | Forgejo Actions on push to main | +| `cryodev-pi` | Pull via Comin | Automatic polling | +| SD Images | Built in CI | Push to main (for Pi hosts) | + +## Verification Checklist + +Before committing: +- [ ] `nix fmt` passes +- [ ] `nix flake check` passes (or at least `nix eval` works) +- [ ] New hosts added to `flake.nix` +- [ ] Constants in `constants.nix`, not hardcoded +- [ ] Secrets use SOPS, not plaintext