---
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.
