Files
nixos/CLAUDE.md
T
finn.markwitz 621ca5dde6 docs: sops-nix secrets workflow
Operator runbook for adding a secret, adding a new host, and rotating
keys, plus a pointer from CLAUDE.md's architecture overview.
2026-09-08 15:43:50 +02:00

3.8 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

# Apply configuration (switch/boot/test)
sudo nixos-rebuild switch --flake '.#jupiter'
sudo nixos-rebuild switch --flake '.#mibook'

# Build without switching (CI-style check)
nix build '.#nixosConfigurations.jupiter.config.system.build.toplevel'

# Update all flake inputs
nix flake update

# Format Nix files
nixfmt-rfc-style <file>   # or: find . -name '*.nix' | xargs nixfmt-rfc-style

Architecture

This is a flake-parts NixOS configuration for two machines:

  • jupiter — home server running media/automation services
  • mibook — laptop running KDE desktop + development tools

Module Loading Chain

flake.nix
└── machines/configuration.nix        # flake-parts module; defines nixosConfigurations
    ├── machines/core/                 # base modules applied to every machine
    │   ├── core.nix                   # system packages, locale, timezone
    │   ├── network.nix
    │   ├── nix.nix
    │   ├── sops.nix                   # sops-nix decryption config, sops/age/ssh-to-age on PATH
    │   └── users.nix
    ├── modules/                       # custom NixOS option modules (my.profiles.*, my.hardware.*, my.services.*)
    │   ├── environments/              # per-service/app profiles
    │   ├── hardware/                  # hardware profiles (nvidia, bluetooth, sound, wifi)
    │   └── services/                  # infrastructure services (vpn, webserver)
    └── machines/<name>/
        ├── configuration.nix          # machine-specific NixOS settings
        ├── environments.nix           # enables profiles via my.profiles.* / my.hardware.* options
        ├── secrets.nix                # sops.secrets declared for this host
        ├── disks.nix
        └── hardware-configuration.nix

Secrets (sops-nix)

Secrets are encrypted with sops, decrypted per-host from that host's SSH host key. .sops.yaml defines who can decrypt what; secrets/<host>.yaml holds the encrypted values; machines/<host>/secrets.nix declares which secrets that host exposes and consumes them via config.sops.secrets.<name>.path. Always git add a secrets file before nix build — untracked files are invisible to flake evaluation. Full workflow (adding a secret, adding a host, rotating keys): see docs/secrets.md.

Profile / Module Pattern

Every module under modules/ follows the same structure:

{ config, lib, pkgs, ... }:
let cfg = config.my.profiles.<name>; in
{
  options.my.profiles.<name>.enable = lib.mkEnableOption "...";
  config = lib.mkIf cfg.enable { ... };
}

Namespaces in use:

  • my.profiles.* — application/service profiles
  • my.hardware.* — hardware profiles
  • my.services.* — infrastructure services

Profiles are enabled per-machine in machines/<name>/environments.nix.

Unstable Packages

pkgs.unstable is available everywhere via an overlay defined in machines/configuration.nix. Use it when a package isn't in the pinned stable channel (nixpkgs/nixos-25.11).

Homepage Dashboard Integration

Modules that expose a web UI can self-register with the homepage dashboard by adding to my.homepage.services:

my.homepage.services = [{
  group = "Services";
  name = "My Service";
  description = "...";
  href = "http://${hostName}:PORT";
  icon = "si-iconname";  # optional
}];

Adding a New Service Module

  1. Create modules/environments/<name>/default.nix following the profile pattern above.
  2. Add ./environments/<name> to modules/environments/default.nix (or the relevant default.nix).
  3. Enable it in the target machine's machines/<name>/environments.nix.