chmonitor

chmonitor has two independent auth layers that work together on every /api/v1/* route:

  • Auth provider — one of none, clerk, or proxy. Controls whether browser sessions are authenticated. Set with CHM_AUTH_PROVIDER (server) and VITE_AUTH_PROVIDER (client, build-time inlined). Legacy Next.js app uses NEXT_PUBLIC_AUTH_PROVIDER instead of VITE_AUTH_PROVIDER.
  • API key layer — always active when CHM_API_KEY_SECRET is set. Authenticates programmatic clients (MCP, scripts, CI) with signed chm_ Bearer tokens, independent of the provider.

A request is allowed when either layer accepts it. The only fully public setup is CHM_AUTH_PROVIDER=none with no CHM_API_KEY_SECRET.

Summary

MethodWho reads itBrowser / proxy authcurl / MCP auth
Public (none)opennone needed
API keyProvider-agnostic; active when CHM_API_KEY_SECRET setAuthorization: Bearer chm_…
Clerkclerk providerClerk __session cookieClerk token or chm_ key
Clerk OAuth (MCP only)MCP serverOAuth bearer token
Proxy → Cloudflare Accessproxy providerCf-Access-Jwt-Assertion JWT
Proxy → trusted headerproxy providerX-Forwarded-User + shared secretshared secret header

How enforcement decides

For each /api/v1/* request, in order:

  1. If CHM_AUTH_PROVIDER=none and CHM_API_KEY_SECRET is not set → allow (public).
  2. The key-issuance route /api/v1/auth/api-key is exempt (it has its own auth).
  3. A valid chm_ Bearer token → allow.
  4. The active provider’s check runs; if it authenticates → allow.
  5. Otherwise → 401 { "error": "Authentication required" }.

All paths fail closed: a missing config or verification error resolves to “not authenticated”.

Which one should I use?

SituationRecommended setup
Local dev or internal network, no login neededPublic (none) — default
Hosted dashboard with user accounts and sign-inClerk
Behind Cloudflare Access or nginx/SSOProxy (cloudflare-access or trusted-header)
MCP clients, scripts, CI pipelinesAPI key (CHM_API_KEY_SECRET) — add alongside any provider

Provider pages