# ADR-0010: Authentication and security boundary **Status:** Accepted — 2026-05-23 ## Context Ollama itself has no authentication — anyone who can reach `:11434` can drive it. foreman sits in front of it and is the network-facing component. We need a real boundary without dragging in an auth framework (the kind of scope creep ADR-0001 guards against). ## Decision **Primary boundary is the network.** foreman and its Ollama target sit on a trusted segment: the target's `:11434` is firewalled to foreman only, and/or both are bound to the Tailscale interface. foreman is **not** exposed through a public Traefik entrypoint. **Optional static bearer token.** If a token is configured, foreman validates the `Authorization: Bearer ` header on incoming requests. This reuses headers that clients already send: - `go-llm` via `llm.Ollama()` sends no auth (fine on a trusted segment); via `ollama.New(key, baseURL)` it sends `Authorization: Bearer ` — so a configured foreman token slots straight into the existing provider with no new code. - The OpenAI-compat surface (if enabled, ADR-0003) carries the same header. foreman → target auth: an optional bearer the daemon attaches to its own calls to Ollama, for the Ollama-Cloud-style case; empty for a local/LAN target. ## Out of scope for v1 - Authentik / SSO. It is painful for service-to-service traffic and adds nothing over network isolation here. - Per-caller identities, scopes, rate limiting. Not needed for a single-tenant homelab daemon. ## Consequences - Minimal but real security: network isolation always, plus an optional shared secret that integrates with existing clients for free. - Webhook authenticity is handled separately by optional HMAC signing (ADR-0005). - No financial/identity/credential data ever transits foreman; it brokers chat jobs only. ## Alternatives considered - **No auth, network-only.** Acceptable on a fully trusted tailnet; the optional token exists for when foreman's reachability widens. - **Full auth framework / SSO.** Rejected as scope creep.