cryodev/AGENTS.md
steffen 10bb0c8e34 add deploy/create/install apps, fix templates and docs
- Add apps: create (scaffold host from template), deploy (multi-host
  deployment with -n filter), install (NixOS installation from live ISO)
- Register all apps in flake.nix (create, deploy, install, rebuild)
- Add deploy.json config (cryodev-main, SSH port 2299)
- Fix generic-server template: was using Pi hardware/boot config,
  now correct x86_64 with systemd-boot, UEFI, ROOT/BOOT/SWAP labels
- Fix template networking.nix: use HOSTNAME placeholder instead of
  hardcoded cryodev-pi (both templates)
- Fix headplane upstream pnpm-deps hash mismatch via overlay
- Fix all docs: replace root@ with user@, --ssh-option with
  NIX_SSHOPTS, add deploy app references, update first-install guide
  to use create app and document service deactivation steps
2026-03-14 12:08:30 +01:00

5.9 KiB

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

# 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

# Deploy all hosts via deploy app (uses deploy.json)
nix run .#deploy

# Deploy to cryodev-main via deploy-rs
nix run github:serokell/deploy-rs -- .#cryodev-main

# Manual deployment via SSH
NIX_SSHOPTS="-p 2299" nixos-rebuild switch --flake .#<hostname> \
  --target-host <user>@<ip> --use-remote-sudo

Apps

# Create a new host from template
nix run .#create -- -t generic-server -n <hostname>

# Install NixOS on a new machine (run from NixOS live ISO)
nix run .#install -- -n <hostname> -r <REPO_URL>

# Deploy to all configured hosts
nix run .#deploy

# Rebuild NixOS/Home Manager configuration
nix run .#rebuild -- nixos

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

# 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

# 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:

{ constants, ... }:
{
  services.nginx.virtualHosts."${constants.services.forgejo.fqdn}" = { ... };
}

Error Handling

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:

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