Overview
Caddy’sforward_auth
asks another service whether a request may proceed. Point it at GoModel’s
GET /v1/auth/verify and Caddy
gates traffic on GoModel API keys — without a copy of those keys anywhere in
the proxy.
Two things this is good for:
- Reject unauthenticated traffic at the edge. Requests without a usable key never reach the gateway, so scanners and misconfigured clients do not open connections to it or land in its audit log. GoModel still authenticates every request it serves; the edge check is a filter in front, not a replacement.
- Gate other services on GoModel keys. An internal dashboard, a docs site, or a metrics endpoint on the same host can require a valid GoModel key without implementing authentication of its own.
/v1/auth/verify is disabled by default. Enable it with
AUTH_VERIFY_ENABLED=true (server.auth_verify_enabled). It is not an
/admin route, so it keeps working with ADMIN_ENDPOINTS_ENABLED=false.
Why it works
forward_auth decides on the status code alone:
GoModel’s
401 body is its normal OpenAI-shaped error envelope, so a client
that already understands GoModel errors sees a familiar shape from the proxy.
The 200 body (valid, method, key_id, user_path) is ignored by Caddy —
it is there for scripts and services that want to know which key answered.
Gate another service on GoModel keys
The upstream here is any app you want behind GoModel’s keys.forward_auth sends the incoming request’s own headers to GoModel, so the
caller’s Authorization: Bearer sk_gom_... (or x-api-key) is what gets
checked. Nothing else is needed to make the credential reach the gateway.
copy_headers X-Gomodel-Auth-User forwards GoModel’s answer about who the
caller is: for a managed key bound to a user path, the
upstream receives that path and can scope what it shows. The header is empty
for master-key callers and for keys with no bound path.
Check it:
Filter traffic in front of the gateway
To put the same check in front of GoModel itself, verify against the gateway and proxy to it:Notes
- Caddy re-checks the key on every request. There is no result cache in
forward_auth, so the gateway sees one verification call per proxied request;/v1/auth/verifydoes no provider work and answers from the key store. - The endpoint answers
Cache-Control: no-store— the answer describes one caller’s credential and must not be served to anyone else. - Enabling the endpoint exposes a key oracle: anyone who can reach it can test whether a key is valid. Expose it only where you need it, and keep GoModel’s rate limits in front of untrusted callers.
- Caddy adds
X-Forwarded-MethodandX-Forwarded-Urito the verification subrequest. GoModel ignores both; the check is about the credential, not the route being requested.