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
This commit is contained in:
steffen 2026-03-11 08:43:48 +01:00
parent 5ba78886d2
commit c021af7d80

248
AGENTS.md
View file

@ -1,114 +1,194 @@
# Agent Guidelines for NixOS Configuration # Agent Guidelines for NixOS Configuration
## Project Overview ## 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 ### Prerequisites
- **Nix** with Flakes enabled. - **Nix** with Flakes enabled
- **Git** - **Git**
### Core Commands ### Core Commands
- **Build Host Configuration**:
```bash
nix build .#nixosConfigurations.<hostname>.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 ```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 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 .#<hostname> --target-host root@<ip>
```
## Code Style & Conventions ## Code Style & Conventions
### General Nix Style ### Formatting
- **Formatting**: Strictly adhere to `nixfmt` style. Run `nix fmt` before committing. - **Tool**: `nixfmt` via pre-commit hooks
- **Indentation**: Use 2 spaces for indentation. - **Run**: `nix fmt` before every commit
- **Lines**: Limit lines to 80-100 characters where possible, but follow the formatter's lead. - **Indentation**: 2 spaces
- **Comments**: Use `#` for single-line comments. Avoid block comments `/* ... */` unless necessary for large blocks of text. - **Line length**: 80-100 characters (follow formatter)
### Module Structure ### Module Structure
- **Function Header**: Always use the standard module arguments pattern:
```nix ```nix
{ config, lib, pkgs, inputs, outputs, constants, ... }: # Standard module pattern
``` { 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**: let
- Define options in `options = { ... };`. cfg = config.services.myService;
- Implement configuration in `config = { ... };`. in
- Use `mkEnableOption` for boolean flags. {
- Use `mkOption` with types (e.g., `types.str`, `types.bool`) and descriptions. options.services.myService = {
- **Imports**: enable = lib.mkEnableOption "My service";
- Use relative paths for local modules: `imports = [ ./module.nix ];`. port = lib.mkOption {
- Use `inputs` or `outputs` for external/shared modules: `imports = [ outputs.nixosModules.common ];`. type = lib.types.port;
default = 8080;
description = "Port to listen on";
};
};
config = lib.mkIf cfg.enable {
# Implementation here
};
}
```
### Naming Conventions ### Naming Conventions
- **Files**: `kebab-case.nix` (e.g., `hardware-configuration.nix`). | Type | Convention | Example |
- **Options**: `camelCase` (e.g., `services.myService.enable`). |------|------------|---------|
- **Variables**: `camelCase` in `let ... in` blocks. | Files | kebab-case | `hardware-configuration.nix` |
| Options | camelCase | `services.myService.enable` |
| Variables | camelCase | `let myValue = ...;` |
| Hosts | kebab-case | `cryodev-main`, `cryodev-pi` |
### Flake Specifics ### Imports
- **Inputs**: Defined in `flake.nix`. ```nix
- `nixpkgs`: Main package set (typically following a stable release). # Local modules: relative paths
- `nixpkgs-unstable`: Unstable channel for latest packages. imports = [ ./hardware.nix ./networking.nix ];
- **Outputs**:
- `nixosConfigurations`: Host definitions. # Shared modules: via outputs
- `nixosModules`: Reusable modules exported by this flake. imports = [ outputs.nixosModules.common ];
- `packages`: Custom packages exported by this flake.
- `overlays`: Overlays to modify `nixpkgs`. # External inputs
- `templates`: Project templates for creating new hosts. 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 ### Error Handling
- Use `assert` for critical configuration invariants. ```nix
- Use `warnings` or `trace` for deprecation or non-critical issues during evaluation. config = lib.mkIf cfg.enable {
- Example:
```nix
config = lib.mkIf cfg.enable {
assertions = [ assertions = [
{ assertion = cfg.port > 1024; message = "Port must be non-privileged"; } { 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 ## Directory Structure
- `flake.nix`: Entry point, defines inputs and outputs.
- `hosts/`: Specific host configurations. ```
- `<hostname>/default.nix`: Host entry point. .
- `modules/`: Reusable NixOS modules. ├── flake.nix # Entry point, inputs/outputs
- `nixos/`: Modules specific to NixOS (e.g. `nixvim`, `comin`, `forgejo`). ├── constants.nix # Central config (domains, IPs, ports)
- `pkgs/`: Custom package definitions. ├── hosts/
- `overlays/`: Nixpkgs overlays. │ ├── cryodev-main/ # x86_64 server
- `templates/`: Templates for bootstrapping new hosts (`raspberry-pi`, `generic-server`). │ │ ├── default.nix # Host entry point
- `scripts/`: Helper scripts (e.g., `install.sh` for bootstrapping). │ │ ├── hardware.nix # Hardware configuration
- `constants.nix`: Central configuration for domains, IPs, and ports. │ │ ├── services/ # Service configurations
- `INSTRUCTIONS.md`: Setup and deployment instructions (DNS, SOPS, bootstrap). │ │ └── secrets.yaml # SOPS-encrypted secrets
- `README.md`: General project documentation and architecture overview. │ └── 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/<host>/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 ## 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 | Host | Strategy | Trigger |
- **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. | `cryodev-main` | Push via deploy-rs | Forgejo Actions on push to main |
- **Refactoring**: When moving code, update `imports` carefully. | `cryodev-pi` | Pull via Comin | Automatic polling |
- **Constants**: Use `constants.nix` for values like domains, IPs, and ports instead of hardcoding them in modules. | 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