Skip to content

Forward auth

Forward auth puts a login page in front of an application that has none. Caddy asks CPM about every request; CPM either says yes or redirects the visitor to sign in.

A host has one sign-in, but it can add a bot challenge in front of it: Anubis is a separate switch, checked first, so bots never reach the login page.

No external identity provider required. CPM serves the login page itself, issues a session cookie, and validates each request against it. Visitors sign in with a local account or through an OAuth provider. A local account with two-factor sign-in is asked for its code here too.

Access is granted per host, by user or by group. Groups are the maintainable form - add someone to staff once and they reach every host staff can reach, rather than being added to each host individually.

Some paths must not be authenticated: a webhook receiver, a health check, an API the application serves to machines. Excluded paths bypass the portal while the rest of the host stays protected.

Forward auth on a proxy hostUntick everything to see what it refuses to save.DemoNothing you change here is saved
CPM Forward AuthRequire users to authenticate via Caddy Proxy Manager before accessing this host
Leave empty to protect the entire domain. Comma-separated paths to protect specific routes only.
Paths to exclude from authentication. These paths bypass forward auth while all other paths remain protected. Ignored if Protected Paths is set.
When a CAPTCHA is configured under Settings → Authentication, the portal asks for it before the password for this host. Turn off only for a host whose users cannot solve one - it leaves this host's sign-in open to scripted password guessing.
Allowed Groups
  • adminsRuns the stack2 members
  • staff11 members
Allowed Users
  • Averyavery@example.com
  • Samsam@example.com

Once a visitor is authenticated, their identity can be forwarded to the application as headers, so an app that understands “trusted proxy told me who this is” does not need its own login at all.

Header Carries
X-CPM-User The sign-in username, or the email address for an account without one
X-CPM-Email The email address
X-CPM-Groups The user’s groups, comma-separated
X-CPM-User-Id An opaque UUID that never changes for the account

Key an application’s accounts on X-CPM-User-Id when it can: a username or email can be edited, the id cannot. Installs upgraded from before the UUID keep sending the sequential account number here, which their upstreams were already keyed on; Settings → Forward Auth → Numeric forward-auth user IDs switches between the two, and changes the id every upstream sees for every user.

A host can instead be pointed at a forward-auth server you already run - Authelia, tinyauth, anything that answers a forward-auth subrequest. Pick the Authelia preset and the endpoint and identity headers are filled in; pick Custom and you supply them. Settings → Forward Auth → Forward Auth Defaults sets what new hosts inherit.

The identity headers the auth server returns are stripped from every inbound request before the upstream sees it, on protected and unprotected paths alike, so a caller cannot forge Remote-User by simply sending it.

An auth server answers an unauthenticated browser with a redirect to its login page. An API client or a WebSocket handshake cannot follow that, and gets an HTML page where it expected JSON.

Answer non-browser callers with 401 splits the two: a request that asked for HTML keeps the redirect, everything else gets a bare 401.

Where the application has its own API credential - Moonraker’s X-Api-Key, say - list that header under Bypass headers. A request carrying it skips forward auth entirely and the application checks the credential itself.

If you already run Authentik, CPM can point at its outpost instead of serving the portal itself, with configurable header forwarding and protected paths. Settings → Forward Auth → Authentik Defaults sets what new hosts inherit, and each host can override it.

Pointing a host at an Authentik outpostBlank fields fall back to the global defaults.DemoNothing you change here is saved
Authentik Forward AuthProxy authentication via Authentik outpost

The route that proxies the outpost’s own paths (such as /outpost.goauthentik.io/*) drops the client’s Authorization header: none of the host’s other handlers run there to strip it, and the outpost’s start, callback and sign-out endpoints work from cookies.