This page describes how the CLI resolves a gateway, authenticates with it, and where credentials are stored. For how to deploy or register gateways, refer to Gateways.
When any CLI command needs to talk to the gateway, it resolves the target through a priority chain:
--gateway-endpoint <URL> flag (direct URL).-g <NAME> flag.OPENSHELL_GATEWAY environment variable.~/.config/openshell/active_gateway.The CLI loads gateway metadata from disk to determine the endpoint URL and authentication mode.
The CLI uses one of these authentication modes depending on the gateway’s configuration.
The default mode for local Docker, Podman, and VM gateways without OIDC. The CLI presents a client certificate during the TLS handshake, and the gateway can map the verified certificate subject to a local user principal when mTLS user authentication is enabled.
mTLS user authentication is for local single-user gateways. Kubernetes deployments must use OIDC or a trusted access proxy for user authentication; the Helm chart does not render mtls_auth.
Set these environment variables before starting the gateway:
For local access, the server certificate must be valid for the endpoint the CLI uses. Include localhost and 127.0.0.1 in the certificate SANs when users connect to a local gateway through loopback.
Package-managed local gateways on Homebrew, Debian, and RPM generate this bundle automatically for the openshell gateway name and use https://127.0.0.1:17670 by default.
When you register a package-managed local gateway with openshell gateway add https://127.0.0.1:17670 --local --name openshell, the CLI refreshes its mTLS bundle from the package-managed TLS directory.
On Homebrew, the gateway service also mirrors the Docker sandbox client bundle into $HOME/.local/state/openshell/homebrew/tls before startup so Docker Desktop can bind-mount the files into sandbox containers.
The CLI loads its mTLS bundle from ~/.config/openshell/gateways/<name>/mtls/:
The connection flow:
Gateways can validate OpenID Connect access tokens on gRPC requests. Configure OIDC when you want users, operators, or automation to authenticate with an identity provider such as Keycloak, Entra ID, or Okta.
OIDC is application-layer authentication. TLS still controls the transport. If TLS client certificates remain required, the CLI must also have an mTLS bundle for the gateway.
Configure the gateway with an issuer and audience:
The same settings are available through environment variables:
For Helm deployments, set the same values under server.oidc:
Register an OIDC gateway with the CLI:
When you register or log in to an OIDC gateway, the CLI uses the Authorization Code flow with PKCE. It opens a browser, receives the authorization code on a localhost callback, exchanges the code for tokens, and stores the token bundle under the gateway credential directory. If OPENSHELL_OIDC_CLIENT_SECRET is set, the CLI uses the client credentials flow instead. Use that mode for CI and other non-interactive automation.
The connection flow:
authorization: Bearer <token> metadata to each gRPC request.If OPENSHELL_OIDC_SCOPES_CLAIM is set, the gateway also enforces scopes. It accepts space-delimited scope strings such as scope: "openid sandbox:read" and JSON arrays such as scp: ["sandbox:read"]. Standard OIDC scopes such as openid, profile, email, and offline_access are ignored for authorization. openshell:all grants access to all scoped methods.
Supervisor-to-gateway RPCs do not use user OIDC tokens or mTLS user identity. Each sandbox supervisor presents a gateway-minted Authorization: Bearer token scoped to its sandbox ID. On Kubernetes, the gateway mints that token only after TokenReview validates the projected ServiceAccount token, the pod UID matches the live pod, and the pod’s controlling Sandbox ownerReference matches the live Sandbox CR. Log upload, policy status, credential environment lookup, inference bundle lookup, and sandbox config sync run with sandbox-restricted scope, while CLI users authenticate with OIDC, edge auth, local mTLS user authentication, or an explicitly enabled unauthenticated local developer mode. GetInferenceBundle returns route material that includes provider credentials, so it requires a sandbox principal; user callers manage inference configuration through the user-facing inference APIs instead.
Re-authenticate an OIDC gateway with:
For gateways behind a reverse proxy that handles authentication (e.g. Cloudflare Access), the CLI uses a browser-based login flow and routes traffic through a WebSocket tunnel.
Registration flow (openshell gateway add https://gateway.example.com):
Connection flow (subsequent commands):
wss://) to the gateway, attaching the stored bearer token in the upgrade headers.This is transparent to the user. All CLI commands work the same regardless of whether the gateway uses mTLS, OIDC, or edge authentication.
Re-authentication: If the token expires, run openshell gateway login to open the browser flow again and update the stored token.
When a gateway is deployed with server.disableTls=true, TLS is disabled entirely. The CLI connects over plain HTTP/2. This mode is intended for local port-forwarding or gateways behind a trusted reverse proxy or tunnel that handles TLS termination externally.
Register a plaintext gateway with an explicit http:// endpoint:
For Kubernetes local development, the Helm Skaffold overlay enables [openshell.gateway.auth] allow_unauthenticated_users = true so a port-forwarded plaintext gateway works without OIDC or mTLS user credentials. Leave this disabled for shared and production clusters.
This stores the gateway with auth_mode = plaintext, skips mTLS client certificate lookup, and does not open the browser login flow.
All gateway credentials and metadata are stored under ~/.config/openshell/:
For OIDC gateways, metadata.json also stores the issuer, CLI client ID, optional audience, and requested scopes. Treat oidc_token.json as a credential. OpenShell writes it with owner-only file permissions.