incus-contrib/CLAUDE.md

9.6 KiB

CLAUDE.md - Project context for AI assistants

What this repository is

A collection of peripheral tools, scripts, and snippets for working with Incus, IncusOS, and the broader ecosystem (Operations Center, Migration Manager). Primarily targeting home lab environments but aiming for production-quality scripts.

Repository structure

incus-contrib/
├── CLAUDE.md              # This file -- behavioral rules + project overview
├── .claude/rules/         # Topic-specific context (auto-loaded by paths:)
├── .claude/skills/        # Slash commands: /screenshot, /proxmox-api
├── README.md              # Main overview
├── .gitignore
├── ansible/               # Ansible playbooks for AWX/Aether lifecycle hooks
│   ├── ansible.cfg
│   └── playbooks/
│       ├── post-deploy.yml    # Runs after Aether creates an instance
│       └── decommission.yml   # Runs before Aether deletes an instance
├── incusos/               # IncusOS installation tooling
│   ├── README.md
│   ├── incusos-iso        # ISO/IMG builder (wraps flasher-tool)
│   ├── incusos-seed       # Seed archive generator (Linux + macOS)
│   ├── incusos-proxmox    # Declarative Proxmox VM deployment + lab lifecycle
│   ├── deploy-awx         # AWX deployment + management on Incus cluster
│   ├── deploy-haproxy     # HAProxy LB deployment + management via Aether
│   ├── deploy-observability # Prometheus + Grafana + Loki observability stack
│   ├── awx-manifests/     # K8s manifests for AWX Operator + instance
│   ├── observability-dashboards/  # Grafana dashboard JSON exports
│   ├── helpers/
│   │   ├── proxmox-screenshot  # VMID -> PNG console screenshot
│   │   ├── proxmox-api         # Authenticated API calls (handles ! in token)
│   │   ├── aether-browser      # Playwright browser automation for Aether web UI
│   │   ├── ovn-inspect         # OVN/OVS topology inspection (--nb/--sb/--ovs/--trace)
│   │   └── incus-mitm         # API traffic capture and analysis (--capture/--live/--analyze)
│   ├── lab-test           # Guided lab validation (12 test phases)
│   ├── observe-deploy     # Single-VM deploy with console screenshots
│   ├── proxmox.yaml       # Proxmox connection (gitignored)
│   ├── TESTING.md
│   └── examples/          # Example seed + Proxmox YAML files
├── env                    # PROXMOX_TOKEN_SECRET, PROXMOX_ROOT_PASSWORD, AETHER_ADMIN_PASSWORD (gitignored)
└── notes/                 # Reference guides (clustering, networking, OC, AWX, etc.)

Capabilities you have

Proxmox VM screenshots

Take console screenshots during deploys to see boot progress or errors:

incusos/helpers/proxmox-screenshot VMID [/tmp/output.png]

Use the Read tool on the PNG to view it. USE THIS PROACTIVELY during deploy scenarios to monitor boot progress, diagnose hangs, and verify installs.

Proxmox API calls

Make authenticated API calls (handles the ! in automation@pve!deploy):

incusos/helpers/proxmox-api GET /nodes/pve/qemu/900/status/current --json
incusos/helpers/proxmox-api GET /nodes/pve/status --json
incusos/helpers/proxmox-api POST /nodes/pve/qemu/900/status/stop

Aether API

Aether has a documented REST API at https://192.168.102.160:8443/api/.

  • Swagger UI: https://192.168.102.160:8443/api/docs
  • OpenAPI spec: https://192.168.102.160:8443/api/swagger.yaml
  • Auth: JWT via POST /api/auth/token with {"username":"...","password":"..."} Credentials in env file (AETHER_ADMIN_PASSWORD). Token valid 24h.
# Get JWT
TOKEN=$(curl -sk -X POST https://192.168.102.160:8443/api/auth/token \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"admin\",\"password\":\"$AETHER_ADMIN_PASSWORD\"}" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")

# Use it
curl -sk https://192.168.102.160:8443/api/clusters \
  -H "Authorization: Bearer $TOKEN"

Current API coverage (v6.4.317, API v1.0.0):

  • Authentication: POST /api/auth/token
  • Clusters: GET /api/clusters
  • Local ACLs: CRUD on /api/clusters/{id}/rules
  • Global ACLs: CRUD on /api/global/rules

Not yet in the API: AWX endpoints, deploys, blueprints, instance management, health checks. These are available through the web UI only. The API is actively being developed — check /api/swagger.yaml for new endpoints in future Aether versions.

Live AWX job output

Capture output while a job is running (don't just poll status):

curl -sk http://192.168.102.161:30080/api/v2/jobs/{JOB_ID}/stdout/?format=txt \
  -H "Authorization: Bearer $AWX_TOKEN"

Aether browser automation (Playwright)

Many Aether features (HAProxy management, blueprints, deploys) are not in the JWT API — they use session-authenticated routes with CSRF protection that curl cannot handle reliably. USE PLAYWRIGHT for these interactions.

MCP server: Configured in .mcp.json — provides browser_navigate, browser_click, browser_fill, browser_screenshot etc. as tools when the Playwright MCP server is running. Prefer MCP tools when available.

Helper script: incusos/helpers/aether-browser provides standalone Playwright automation when MCP tools aren't loaded:

source env  # loads AETHER_ADMIN_PASSWORD
NODE_PATH=~/node_modules node incusos/helpers/aether-browser <action> [args]

Actions:

  • login — authenticate and save session cookies to /tmp/aether-cookies.json
  • screenshot <path> — navigate to path, take screenshot
  • navigate <path> — navigate and show page title/URL
  • haproxy-status — screenshot HAProxy management page
  • haproxy-images — list built HAProxy images via session API
  • api-get <endpoint> — authenticated GET using browser session
  • api-post <endpoint> <json> — authenticated POST with CSRF handling
  • eval <js> — evaluate JavaScript on the current page

When to use what:

  • JWT API (/api/* endpoints): use curl with bearer token
  • Session-authenticated routes (/haproxy/*, UI actions): use Playwright
  • Never use curl for session auth — CSRF protection requires browser cookies

Key technical detail: Aether login is at / (root), NOT /login. The form POSTs to /login. CSRF token is in a hidden <input> field, not in cookies.

Critical safety rules

  • Proxmox SSH is screenshots-only. Full rules in .claude/rules/proxmox-ssh-rules.md.
  • Never hard-stop VMs during first boot -- corrupts TPM permanently.
  • Boot timeout is 180s -- do not reduce (sysext download takes 30-120s).
  • No force_reboot in seeds for Proxmox -- causes crontab race condition.
  • VMID ranges: 400-499 (OC), 800-809 (single), 900-939 (clusters).

Interacting with external systems (Aether, AWX, Incus, etc.)

Strict priority order — follow this hierarchy in all guides, scripts, and automation flows:

  1. API first: if the system has a documented REST API, use it. Authenticate as a regular user (JWT, PAT), never as root / DB superuser.
  2. Web UI fallback: if the API doesn't cover a feature yet, document the UI steps (navigation path, form fields, expected result).
  3. Never use root / direct DB access in guides or automation. Poking around in containers, editing databases directly, or using incus exec into Aether is acceptable only for investigation and learning — never as the documented path for users to follow.

APIs improve over time. When a feature is UI-only today, note it and check /api/swagger.yaml (or equivalent) in future versions before assuming it's still UI-only. The API endpoint may have been added since the guide was written.

Coding conventions

  • Shell: bash with set -euo pipefail
  • Arithmetic: var=$((var + 1)) not ((var++)) (set -e safety)
  • Colors: support NO_COLOR=1 and TERM=dumb; use setup_colors() pattern
  • Flags: both short (-d) and long (--defaults)
  • Defaults: useful behavior with zero flags
  • Dry run: all scripts support --dry-run
  • Cert detection: files on disk first (~/.config/incus/client.crt), CLI second
  • Errors: include actionable remediation steps
  • No hardcoded package managers: say "install the Incus client" with a link

Technical context loading

Detailed technical context loads automatically from .claude/rules/ based on which files are being edited:

Rule file Loads when editing
incusos-scripts.md incusos-iso, incusos-seed, incusos-proxmox, helpers
proxmox-deployment.md incusos-proxmox, observe-deploy, helpers, examples
clustering.md lab-test, incusos-proxmox, clustering/production guides
operations-center.md OC guide, incusos-proxmox, OC example configs
networking-storage.md networking, storage, migration, UTM guides
awx-integration.md ansible/, deploy-awx, awx-manifests, AWX guide
haproxy-lb.md deploy-haproxy, HAProxy guide
observability.md deploy-observability, observability dashboards/guide
ovn-internals.md ovn-inspect, ovn-deep-dive
aether-api-payloads.md incus-mitm, api-interception
proxmox-ssh-rules.md Always loaded (no paths filter)
lab-infrastructure.md incusos-proxmox, lab-test, examples

For deep reference, see the guides in notes/.

Git workflow

  • Main branch: master
  • Remotes:
    • origin: ssh://git@192.168.1.200:2222/maarten/incus-contrib.git (private Gitea)
    • aether: _gitea@code.sovereignprivatecloud.nl:maarten/incus-contrib.git
  • Push to both remotes when committing
  • Development happens on feature branches