From 6b92936e69ac428409e429be38ae0267e0675a3d Mon Sep 17 00:00:00 2001 From: padreug Date: Sat, 1 Nov 2025 11:25:24 +0100 Subject: [PATCH] add CLAUDE.md --- CLAUDE.md | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d4092a0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,224 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is a NixOS multi-machine deployment system using **krops** with **Nix 25.05**. It manages multiple machines with different configurations, each potentially running services like LNBits (Lightning Network), pict-rs (image hosting), and custom web applications with machine-specific builds. + +## Key Architecture Concepts + +### Two-Stage Deployment Model + +This project uses a **two-stage deployment process**: + +1. **Local Build Stage** (`build-local.nix`): Builds web applications locally with machine-specific assets (`.env` files, images) +2. **Remote Deploy Stage** (`krops.nix`): Deploys NixOS configurations and pre-built artifacts to target machines + +### Configuration Inheritance Pattern + +- **`config/shared.nix`**: Base configuration inherited by all machines (takes `domain` parameter) +- **`config/machines/{machine-name}/configuration.nix`**: Machine-specific entry point that: + - Defines the `domain` variable + - Imports `shared.nix` with the domain + - Imports machine-specific modules (bootloader, hardware, services) + +### LNBits Flake Integration + +The project uses a sophisticated LNBits deployment via Nix flakes: + +- **Source deployed to**: `/var/src/lnbits-src/` via krops symlink +- **Flake reference**: `builtins.getFlake "path:/var/src/lnbits-src"` (mutable local source) +- **How it works**: Uses `uv2nix` to convert `uv.lock` into a reproducible Nix venv in `/nix/store` +- **Runtime**: Systemd service runs `/nix/store/xxx-lnbits-env/bin/lnbits` with `LNBITS_PATH` pointing to source +- **Lock file**: `flake.lock` is deployed with the source and automatically used by Nix + +See `docs/lnbits-flake-explanation.md` for detailed explanation. + +#### Ensuring flake.lock is Used + +Nix automatically uses `flake.lock` when present. To verify: + +```bash +# Check flake.lock exists locally +ls -lh lnbits/flake.lock + +# After deployment, verify on target machine +ssh root@machine "ls -lh /var/src/lnbits-src/flake.lock" + +# View locked input versions +nix flake metadata path:/var/src/lnbits-src +``` + +To update flake inputs (do this locally before deploying): +```bash +cd lnbits/ +nix flake update +# Or update specific input: +nix flake lock --update-input nixpkgs +``` + +**Important**: The krops `.file` source type copies all files including `flake.lock`. Since `lnbits/` is a symlink, krops follows it and deploys the entire directory tree. + +### Krops Source Deployment + +Files are deployed to target machines under `/var/src/`: + +- `/var/src/config-shared` → `config/shared.nix` +- `/var/src/config-machine` → `config/machines/{machine-name}/` +- `/var/src/web-app-dist` → `build/{machine-name}/dist/` +- `/var/src/lnbits-src` → `lnbits/` (full source with flake) +- `/var/src/lnbits-extensions` → `lnbits-extensions/` + +## Common Development Commands + +### Building Web Applications Locally + +```bash +# Build for a specific machine +nix-build ./build-local.nix -A machine1 && ./result/bin/build-machine1 + +# Build for all machines +nix-build ./build-local.nix -A all && ./result/bin/build-all +``` + +This copies web-app source to `./build/{machine}/`, adds machine-specific `.env` and images, then runs `npm run build`. + +### Deploying to Machines + +```bash +# Deploy to a specific machine +nix-build ./krops.nix -A machine1 && ./result + +# Deploy to all machines +nix-build ./krops.nix -A all && ./result +``` + +### Complete Workflow (Build + Deploy) + +```bash +# 1. Build web-apps locally +nix-build ./build-local.nix -A all && ./result/bin/build-all + +# 2. Deploy to all machines +nix-build ./krops.nix -A all && ./result +``` + +## Project Structure + +``` +. +├── krops.nix # Main deployment config (gitignored) +├── example-krops.nix # Template for krops.nix +├── build-local.nix # Local web-app build scripts (gitignored) +├── example-build-local.nix # Template for build-local.nix +├── config/ +│ ├── shared.nix # Shared config (takes domain parameter) +│ ├── nginx.nix # Nginx + ACME + fail2ban +│ ├── lnbits.nix # LNBits flake integration +│ ├── pict-rs.nix # Image hosting service +│ └── machines/ # Per-machine configs (gitignored) +│ ├── example-machine/ # Template (committed) +│ │ ├── configuration.nix # Sets domain, imports shared + modules +│ │ ├── boot.nix # Bootloader config +│ │ └── example-service.nix # WireGuard and service examples +│ ├── machine1/ # Your machines (gitignored) +│ └── machine2/ +├── build/ # Generated web-app builds (gitignored) +├── machine-specific/ # Machine-specific web-app assets (symlink) +│ └── {machine-name}/ +│ ├── env/.env # Environment variables +│ └── images/ # Logos and images +├── web-app/ # Shared web-app source (symlink) +├── lnbits/ # LNBits source with flake (symlink) +└── lnbits-extensions/ # Custom LNBits extensions (symlink) +``` + +## Adding a New Machine + +1. **Create machine configuration**: + ```bash + cp -r config/machines/example-machine config/machines/new-machine + ``` + +2. **Edit `config/machines/new-machine/configuration.nix`**: + - Set `domain = "yourdomain.com"` + - Add `hardware-configuration.nix` from `nixos-generate-config` + - Customize `boot.nix` for your bootloader + +3. **Create machine-specific web-app assets** (if needed): + ```bash + mkdir -p machine-specific/new-machine/{env,images} + # Add .env file and images + ``` + +4. **Update `build-local.nix`**: + - Add `new-machine = buildForMachine "new-machine";` to outputs + - Add to `all` build script + +5. **Update `krops.nix`**: + - Add machine deployment block + - Add to `inherit` list and `all` script + +6. **Build and deploy**: + ```bash + nix-build ./build-local.nix -A new-machine && ./result/bin/build-new-machine + nix-build ./krops.nix -A new-machine && ./result + ``` + +## Machine-Specific Services + +To add services that only run on certain machines (e.g., WireGuard on one machine): + +1. Create `config/machines/{machine}/custom-service.nix` +2. Import it in `config/machines/{machine}/configuration.nix` +3. Deploy only affects that machine + +See `config/machines/example-machine/example-service.nix` for WireGuard and other examples. + +## Service Configuration Details + +### Virtual Hosts Pattern + +All services use domain-based virtual hosts defined in `shared.nix` or service modules: + +- Web app: `app.${domain}` +- LNBits: `lnbits.${domain}` +- Pict-rs: `img.${domain}` + +All automatically get SSL via Let's Encrypt ACME. + +### LNBits Extensions + +Two deployment options in `config/lnbits.nix`: + +- **Option 1 (Symlink)**: Replace `/var/lib/lnbits/extensions` entirely (deletes UI-installed extensions) +- **Option 2 (Merge)**: Copy deployed extensions alongside UI-installed ones using rsync + +Currently using Option 1 (symlink) - see commented code in `config/lnbits.nix:96-122`. + +### Nginx Configuration + +- `recommendedProxySettings = false` (disabled for WebSocket compatibility) +- WebSocket support configured in LNBits vhost with upgrade headers +- ACME email: `admin@aiolabs.dev` (set in `config/nginx.nix:16`) + +## Important Files for Understanding + +- **`DEPLOYMENT-GUIDE.md`**: Comprehensive deployment instructions +- **`docs/lnbits-flake-explanation.md`**: How LNBits flake deployment works (uv2nix, path: references, etc.) +- **`example-krops.nix`** and **`example-build-local.nix`**: Templates for configuration + +## Configuration Management + +- **Gitignored**: `krops.nix`, `build-local.nix`, `config/machines/*` (except example-machine), `build/`, `machine-specific/*` +- **Committed**: Example configs, shared modules, service definitions +- **Secrets**: Managed separately (see `secrets/` directory with age encryption) + +## Notes for AI Assistants + +- When adding machines, update BOTH `krops.nix` and `build-local.nix` +- Always use the `domain` parameter pattern - it's passed to all modules +- LNBits requires deploying the FULL source tree (including flake.nix, uv.lock) to `/var/src/lnbits-src` +- Web-app builds happen locally to support machine-specific configurations +- The example-machine configuration is the canonical template - keep it updated