# AI builder (gbrgames worker) The panel's **AI builder** (Admin → Games → AI Config Generator) is run by a worker on our own hardware, not on the panel's droplet and not in CI: ``` Panel (droplet) Builder VM (home lab) ─────────────── ───────────────────────────────────────────── admin starts a job ──► queued ◄─poll── gbrgames worker (Docker) progress / log / variants ◄─post── research: SearXNG + page reader + Ollama (3090) "Review draft PR" build: first boot → draft → boot with the node-agent → branch draft/- + PR as gbr-bot ──► CI (validate + boot test) ``` 1. **Research** (`gbrgames research -name N`): searches the web, reads the best pages, and has the model list the server's variants (edition, image or SteamCMD app, startup, ports). Every image and Steam app is checked for real (`docker manifest inspect`, anonymous `steamcmd +app_info_print`) before the admin sees it. 2. The admin picks a variant in the panel. 3. **Build** (`gbrgames build -name N -variant @v.json`): first boot of the image untouched (`first-boot`), a draft by the model (`draft`, rules in `AUTHORING.md`), then the draft is deployed with the node-agent's `BootTest`, the same check CI runs. Failures (crash, error lines, saves written outside `/server`) go back to the model, three boots at most. 4. The worker pushes `games//` to a branch and opens a pull request as **gbr-bot**. A draft that validates but never booted still gets a PR, titled `WIP:`, with what's left listed. Nothing reaches players until a person merges it and enables the game. The worker only connects out (to the panel, Gitea, Ollama, SearXNG); nothing needs to reach the VM. ## The VM A Proxmox VM of its own, so builds never compete with CI boot tests on VM 126: Debian 13, 4+ cores (`host` CPU type), 24 GB RAM (ARK-sized servers need ~16 GB), 150 GB disk (SteamCMD downloads), Docker. ```bash # as root curl -fsSL https://get.docker.com | sh git clone https://www.gitea.gbreed.com/gbreed-public/gbr-games.git /opt/gbr-games ``` **Isolated network:** game servers booted here must not reach the LAN. Same setup as the runner (`RUNNER.md`, step 1): ```bash mkdir -p /opt/gbr-boottest cp /opt/gbr-games/scripts/runner/setup-boottest-network.sh /opt/gbr-boottest/ chmod +x /opt/gbr-boottest/setup-boottest-network.sh cp /opt/gbr-games/scripts/runner/gbr-boottest-network.service /etc/systemd/system/ systemctl daemon-reload && systemctl enable --now gbr-boottest-network ``` **Worker:** ```bash mkdir -p /opt/gbr-builder/work && cd /opt/gbr-builder cp /opt/gbr-games/scripts/builder/docker-compose.yml . cp /opt/gbr-games/scripts/builder/env.example .env && chmod 600 .env # then fill it in docker compose up -d && docker logs -f gbr-builder ``` `gbr-builder:latest` is published by `.gitea/workflows/builder-image.yml` whenever `cmd/` changes on main; watchtower on the VM updates the worker within five minutes. ## Accounts and secrets | Where | Name | What | | --- | --- | --- | | Builder `.env` | `GITEA_TOKEN` | Token of the **gbr-bot** Gitea user (Write on `gbr-games`, scope repository read/write) | | Builder `.env` + panel env | `BUILDER_TOKEN` | Shared secret the panel checks on `/api/v1/builder/**`; any long random string | | Builder `.env` | `OLLAMA_URL`, `SEARXNG_URL`, `READER_URL` | The 3090's Ollama, SearXNG, and the page reader | ## Running a build by hand On any machine with Docker and the `gbr-boottest` network (the builder VM, or the runner): ```bash export OLLAMA_URL=http://192.168.4.30:11434 SEARXNG_URL=http://192.168.4.38:8080 READER_URL=http://192.168.4.38:3000 go run ./cmd/gbrgames research -name Valheim -out research.json # pick a variant from research.json into v.json, then: go run ./cmd/gbrgames build -name Valheim -variant @v.json -out build.json ``` The draft lands in `games//`, first-boot reports in `firstboot-out/`. ## Housekeeping Like the runner: a weekly `docker system prune -af --filter "until=168h"` keeps images and SteamCMD downloads in check. Each job removes its clone; boot tests remove their containers and volumes.