- 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
194 lines
5.5 KiB
Markdown
194 lines
5.5 KiB
Markdown
# Agent Guidelines for NixOS Configuration
|
|
|
|
## Project Overview
|
|
|
|
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**
|
|
|
|
### Core Commands
|
|
|
|
```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 .#<hostname> --target-host root@<ip>
|
|
```
|
|
|
|
## Code Style & Conventions
|
|
|
|
### 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
|
|
|
|
```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
|
|
| 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` |
|
|
|
|
### 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
|
|
```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, 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/<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
|
|
|
|
| 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
|