Authentication modes
Every public access entry on an application carries an authentication mode. The check happens at Caddy on the device hosting the workload, before any request reaches the workload itself. The five modes:
none — public
Section titled “none — public”policies: { auth: { modes: [none] } }Anyone who knows the URL can reach the service. No credential check. Use for marketing sites, public APIs, anything genuinely meant to be open.
If you don’t want the URL itself to be discoverable, pair none with a generated (random-suffix) hostname. The hostname acts as a weak shared secret — fine for low-stakes sharing, not fine as a real access control.
edgible-login — Edgible organization members only
Section titled “edgible-login — Edgible organization members only”policies: { auth: { modes: [edgible-login] } }A request reaches the workload only if the requester has a valid Edgible session for a member of your organization. Visiting in a browser triggers a sign-in flow; if the user is a member of the right org, the request goes through and the user stays logged in for the session.
Use for internal tools — dashboards, admin UIs, on-call runbooks. It removes the need to run a VPN: your team logs into Edgible (which they already do) and the existing session also serves as the authn for these tools.
The check is membership only — a per-app role model isn’t part of edgible-login mode. If you need finer-grained authorization, do it inside your application after the request lands. To restrict to a subset of organizations, set policies.auth.allowedOrganizations.
api-key — bearer token
Section titled “api-key — bearer token”policies: { auth: { modes: [api-key] } }The request must include a bearer token issued for this application. Caddy verifies the token against a list the agent receives from the control plane.
Issue a token with the CLI:
edgible application api-keys create \ --app-id <app-id> \ --name "ci-deploy-key" \ --expires 2026-12-31Send it on every request:
curl https://api.example.com/v1/things \ -H "Authorization: Bearer <key>"Tokens can be listed (api-keys list), deleted (api-keys delete), and given an expiry. Rotation is your responsibility — the platform doesn’t auto-rotate API keys.
Use for programmatic access from scripts, CI pipelines, partner integrations, or any other machine consumer.
short-code — rotating short-lived tokens
Section titled “short-code — rotating short-lived tokens”policies: { auth: { modes: [short-code] } }Like api-key, but the token is shorter, the lifetime is shorter, and it can be capped to a maximum number of uses. Designed for sharing brief access — “send this link to the contractor for the next two hours.”
edgible application short-codes create \ --app-id <app-id> \ --name "contractor-access" \ --expires "2026-04-30T18:00:00Z" \ --max-uses 50The created code is included in the URL or in a query parameter, depending on how the consumer wants to use it. Toggle a code on or off without deleting it (short-codes toggle).
Use when you want to share access without provisioning an account, and you want the access to disappear on its own.
app-native — your application’s own login is the control
Section titled “app-native — your application’s own login is the control”routes: - path: /* target: { workload: web, port: http } policies: { auth: { modes: [app-native] } }The platform passes the request through unchanged: the application’s own authentication is
the declared access control. This is deliberately distinct from none — none declares the
path genuinely anonymous, while app-native records that a check exists, just not a platform
one. Two constraints, both enforced:
- Exclusive.
app-nativecannot be combined with any other mode — pass-through plus a platform check is contradictory, and the platform rejects the combination. - Path-scoped. Declare it on a
routes[]entry (or a legacypathPoliciesentry), not as an access-levelpolicies.auth.modesvalue — the platform rejects it at the root.
Combining modes
Section titled “Combining modes”auth.modes is a set — list more than one and they are OR-combined: a request that satisfies any listed mode is served. The common case is letting both humans and machines reach the same endpoint:
policies: { auth: { modes: [edgible-login, api-key] } }A browser with no credential is redirected to the Edgible login (the edgible-login behavior), while a request carrying a valid Authorization: Bearer <key> is served directly (the api-key behavior) without the redirect.
none is exclusive — it means “no check at all,” so it cannot be combined with another mode; the platform rejects [none, …].
auth.modes combines auth methods on one endpoint — it is not how you give different
audiences different policies. For different auth per path on the same hostname, use a
routes[] table with per-route policies.auth. For
genuinely different surfaces — separate hostnames, separate TLS — declare multiple access
entries, one per audience, each with its own auth.modes (requires agent ≥ 1.2.0 on the
target device). See
Multiple access entries for the worked example.
What none of these modes are
Section titled “What none of these modes are”Edgible’s auth modes authenticate the caller — they don’t authorize the call beyond
membership. None of them inspect the request body, and none of them read JWT claims for your
application. Per-path scoping exists (routes[] carries per-route policies.auth), but the
check is still caller authentication, not authorization. Anything beyond “the caller has a
credential” lives inside your workload — Caddy hands the request through, and you decide what
the user is allowed to do.
For WAF-style request inspection, IP allow-lists, and rate-limiting, see the additional policies fields documented in the YAML reference.