2.0 KiB
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 <token> header on incoming requests. This reuses headers
that clients already send:
go-llmviallm.Ollama()sends no auth (fine on a trusted segment); viaollama.New(key, baseURL)it sendsAuthorization: Bearer <key>— 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.