Files
Oleks cbcf122422 Initial commit: nixbuild.net operator plugin
Haiku ops agent + 3 tools (nbshell expect+PTY admin-shell driver, nbapi
read-only HTTP client, nb-substituters guarded cache manager) + 2 skills
(nixbuild-settings, nixbuild-usage). Encodes the two-control-surface model
and the path-style-substituter-URL gotcha.
2026-06-01 11:17:40 +03:00

60 lines
4.0 KiB
Markdown

# nixbuild
Operator surface for the [nixbuild.net](https://nixbuild.net) remote build service. A Haiku **ops** agent fronts three tools and two skills for reading the metered account's usage and managing its settings — built from the hard-won knowledge of how nixbuild's two control surfaces actually behave.
## Install
```
claude plugin install nixbuild@oleks-local
```
## Why this exists
nixbuild has two completely separate control surfaces, and using the wrong one is the main failure mode:
- **HTTP API** (`https://api.nixbuild.net`, Bearer token) is **read-only** — usage, builds, summary. No settings endpoints.
- **Admin shell** (`ssh eu.nixbuild.net shell`) is the **only** place settings, SSH keys, tokens, and billing live, and it is interactive-only and fussy:
- `ssh -T … shell` + piped stdin → **silent** (needs a PTY).
- `ssh -tt … shell` → rejected: *"pty not supported"*.
- `ssh … shell <cmd>` (command as args) → hits the build-runner channel, needs `run:write`, fails *"Authorization failed"*.
The only thing that works is a **real local PTY** wrapping `ssh -T … shell`, fed one command at a time, synchronised on the `nixbuild.net>` prompt. The `nbshell` tool does exactly that via `expect`.
## Agent
- **ops** (Haiku) — answers account questions and applies settings changes safely. Read-mostly; confirms every mutation. Routes deeper workflows to the two skills.
## Tools (`bin/`)
- **`nbshell '<cmd>' ['<cmd>' …]`** — drive the admin shell non-interactively (expect+PTY). Output cleaned of banner/prompt noise. The foundation for all settings work.
- **`nbapi <usage|summary|builds|raw>`** — read-only HTTP API client. Token from `$NIXBUILD_API_TOKEN` or `pass show infra/nixbuild/api-token`.
- **`nb-substituters <list|add-cache|add-key|remove|remove-key|reset>`** — guarded substituter/key manager that catches nixbuild's path-style-URL rejection before it reaches the shell.
## Skills
- **nixbuild-settings** — manage substituters, trusted public keys, SSH keys, and any `settings <SETTING>` via the shell. Carries the path-style-URL guard and the path-less-cache recipe.
- **nixbuild-usage** — metered-account cost posture: free time left, billable CPU-seconds, build history, output/stored size.
## Hard-won facts encoded here
- **nixbuild rejects path-style substituter URLs** (`https://host/cache-name`*"invalid substituter"*, trailing slash doesn't help). Only host-root HTTPS, `s3://bucket/prefix`, or `cachix://name` are accepted. Reach a sub-path cache (Attic, nix-serve) **path-less** — front it at a host root with a reverse-proxy rewrite of `/<hash>.narinfo` and `/nar/*`. The oleks fleet does this for Attic at `https://nix-cache-custom.oleks.space` (Caddy root-rewrite); NCPS is `https://nix-cache-mirror.oleks.space`.
- **`builders-use-substitutes = true` on the client does NOT forward the client's substituters to nixbuild** — the remote uses its OWN (account-side) substituters. Caches only help remote builds when registered account-side (what `nb-substituters add-cache` does).
- **The account is metered.** Free tier resets monthly (`Free build time left: 25:00:00` on the 1st); when spent the banner reads *"You have no free build time left"* and builds are billed. Cache hits on registered substituters are the cost lever.
## Requirements
- `expect` on PATH, or `nix` (the tools fetch `expect` ephemerally via `nix run nixpkgs#expect` — no profile install).
- An SSH key registered on the nixbuild account **with admin permissions** for settings changes (configured via `~/.ssh/config` / system `ssh_config` for the `ssh_host`, default `eu.nixbuild.net`).
- `curl`, and `jq` (optional, for pretty JSON). `pass` for the API token unless `$NIXBUILD_API_TOKEN` is set.
## Configuration
| Key | Default | Purpose |
|-----|---------|---------|
| `ssh_host` | `eu.nixbuild.net` | SSH host alias for the admin/build endpoint |
| `api_token_pass_entry` | `infra/nixbuild/api-token` | `pass` path for the HTTP API token (overridden by `$NIXBUILD_API_TOKEN`) |
## License
MIT