--- name: gururmm-log-analysis-claude-cutover description: GuruRMM log analysis cut over from Ollama-on-Beast to Claude Haiku 4.5; why, and the deploy shape metadata: type: project --- GuruRMM server log analysis (`server/src/api/logs.rs`, `analyze_logs_with_*`) was cut over from **Ollama (qwen3:14b on Beast, `100.101.122.4:11434`)** to the **Anthropic API (Claude Haiku 4.5)** on 2026-06-12 (decision: Mike). **Why — the "Ollama unreachable" error was a mislabeled timeout, not reachability.** The GuruRMM server `.30` (gururmm, `172.16.3.30` — a **physical box**, Ubuntu 26.04; the VM-on-Jupiter was retired and the physical server took over the `.30` IP) reaches Beast fine for `/api/tags` and short warm `/api/chat` (warm "say OK" = 1.1s), but a fleet-sized `/api/chat` (~1500 log lines / ~17KB) never completes — it hit the curl 300s ceiling even warm. Cause is qwen3:14b's minutes-long inference on a big prompt over a flaky cross-LAN tailnet (`.30` is behind symmetric NAT — `MappingVariesByDestIP:true`; Beast is on Wi-Fi `10.2.51.228`). reqwest's 120s timeout surfaced as `error sending request ... Check Tailscale`, which read as "unreachable." Beast also had a **duplicate-Ollama bind conflict** (the desktop tray app's `ollama serve` couldn't bind 11434; the older standalone PID 14144 held `0.0.0.0:11434` and served) — noisy but not the cause. See [[gururmm-beast-windows-build-host]] for Beast. **The fix.** `analyze_logs_with_claude()` POSTs `https://api.anthropic.com/v1/messages` with `x-api-key` from env, reading `ANTHROPIC_API_KEY` (required) and `ANTHROPIC_MODEL` (default `claude-haiku-4-5`). Uses **structured outputs** (`output_config.format` + json_schema) so the reply is guaranteed-parseable findings JSON (no fence stripping). Cloud over plain HTTPS — no tailnet, no Beast. Validated end-to-end against Haiku (200, ~1-6s, correct findings). `cargo check` clean. **Secrets / privacy.** Key vaulted at `projects/gururmm/anthropic-api` (vault convention: per-project key, mint its own). **ZDR requested from Anthropic, pending** — org-level, not a console toggle (email sales@anthropic.com). Test fleet OK to run before ZDR confirms; don't point a production fleet at it until ZDR is live. **Deploy shape (DONE 2026-06-12).** Production server is a **native binary** `/opt/gururmm/gururmm-server` via systemd, `EnvironmentFile=/opt/gururmm/.env` (root-owned). A Gitea webhook → CI builds+ships the binary on push to gururmm `main` (no cargo on `.30`). `guru` CAN do root ops via `sudo` with the password in vault `infrastructure/gururmm-server` `credentials.password` (SSH via `~/.ssh/gururmm-physical`). Shipped: gururmm `c869e4d` → CI redeployed the binary; `ANTHROPIC_API_KEY` appended to `/opt/gururmm/.env`; `gururmm-server` restarted; `/api/logs/analyze` verified end-to-end (1500 logs → 10 findings in 24s). **Migration note:** the key lives in `.30`'s local `.env`, not the repo — already on the physical `.30`, so nothing to re-add.