apiVersion:reconcilers.nebari.dev/v1kind:NebariAppmetadata:name:my-packnamespace:my-packspec:hostname:my-pack.nebari.example.comserviceAccountName:my-packservice:name:my-packport:80routing:routes:- pathPrefix:/pathType:PathPrefixpublicRoutes:- pathPrefix:/healthzpathType:Exacttls:enabled:trueannotations:argocd.argoproj.io/tracking-id:my-packauth:enabled:trueprovider:keycloakprovisionClient:trueenforceAtGateway:trueforwardAccessToken:false# redirectURI defaults to /oauth2/callback - omit to use the operator defaultscopes:- openid- profile- emailgroups:- admingateway:publiclandingPage:enabled:truedisplayName:My Packdescription:A short description for the landing page card.icon:jupytercategory:Developmentpriority:100
FQDN where the app will be accessible. Used to generate the HTTPRoute and TLS certificate. Must match pattern ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$.
Routing behavior including path rules, TLS, and HTTPRoute annotations. Omitting routing disables operator-managed routing entirely - the operator skips HTTPRoute creation and cleans up any existing HTTPRoute. TLS is also considered disabled in that case.
Which shared Gateway to use. Valid values: public, internal.
serviceAccountName
string
No
NebariApp name
Name of the ServiceAccount used by the app’s pods. The operator scopes RBAC on the OIDC client Secret to this ServiceAccount, so only the app’s pods can read its credentials.
Port number on the Service to route traffic to. Range: 1-65535.
namespace
string
No
NebariApp’s namespace
Namespace of the Service. Allows referencing services in other namespaces for centralized service architectures. The operator has cluster-scoped read permission on Services.
Paths that bypass OIDC authentication. When auth.enabled=true and auth.enforceAtGateway=true, these paths are routed via a separate HTTPRoute that is not protected by the SecurityPolicy. Default pathType is Exact here (vs PathPrefix for routes) - safer for auth bypass.
Additional annotations merged onto the generated HTTPRoute. Useful for tools like ArgoCD that track resources via annotations (e.g. argocd.argoproj.io/tracking-id). Operator-managed annotations always take precedence.
Auto-provision an OIDC client in the provider. Only supported for keycloak. The operator creates the client and stores credentials in a Secret named <name>-oidc-client. The client ID follows the convention <namespace>-<nebariapp-name>. See Authentication Flow for the full secret structure.
enforceAtGateway
*bool
No
true
Create an Envoy Gateway SecurityPolicy for gateway-level auth. When false, the operator provisions the client and Secret but does NOT create a SecurityPolicy - the app handles OAuth natively. See Authentication Flow for wiring guidance.
forwardAccessToken
*bool
No
false
When enforceAtGateway: true, forward the user’s OAuth access token to the upstream service via the Authorization: Bearer <token> header. Use when the app needs to read the JWT itself (e.g., to inspect the groups claim for per-user authorization). Without this, the gateway only stores the token in an encrypted session cookie that the backend cannot decode.
Headers that, when matched, prevent the OIDC filter from redirecting to the IdP and instead return 401. Helps avoid PKCE race conditions when SPAs fire multiple parallel requests on page load. Only applies when enforceAtGateway: true.
redirectURI
string
No
"/oauth2/callback"
OAuth2 callback path. The full URL is https://<hostname><redirectURI>.
clientSecretRef
string
No
-
Name (string) of a Secret in the same namespace containing keys client-id and client-secret. Note: the spec field is a plain string (the Secret name), not the {name, namespace} object reference used by status.clientSecretRef. If omitted and provisionClient is true, the operator creates a Secret named <nebariapp-name>-oidc-client with keys: client-id, client-secret, and issuer-url.
scopes
[]string
No
["openid", "profile", "email"]
OIDC scopes to request during authentication.
groups
[]string
No
-
Groups that have access. When specified, only users in these groups are authorized. Case-sensitive.
issuerURL
string
No
-
OIDC issuer URL. Required when provider=generic-oidc, ignored for keycloak. Example: https://accounts.google.com.
Provisions a public Keycloak client for browser-based PKCE flows (e.g., React apps using keycloak-js). Distinct from the confidential client used by gateway-enforced auth.
Keycloak-specific configuration: realm groups (with optional member assignments) and client-level protocol mappers. Only applied when provider=keycloak and provisionClient=true.
OAuth 2.0 Token Exchange (RFC 8693). When enabled, other NebariApp clients in the same Keycloak realm can exchange their access tokens for tokens with this client’s audience. Requires KC_FEATURES=token-exchange on the Keycloak server.
Client-level protocol mappers applied directly to the OIDC client. When specified, the operator’s default mappers (e.g., group-membership) are not auto-created.
Enable authorization services on the Keycloak client and create policies allowing other NebariApp clients in the same realm to exchange tokens for this client’s audience.
Most recent metadata.generation observed by the controller.
hostname
string
Mirror of spec.hostname for easy reference.
gatewayRef
object {name, namespace}
The Gateway resource routing traffic to this app.
clientSecretRef
object {name, namespace}
The Secret containing OIDC client credentials.
authConfigHash
string
SHA-256 hash of the last successfully provisioned OIDC client config. Used to skip re-provisioning when the spec is unchanged. To force re-provisioning, set the nebari.dev/force-reprovision annotation; the operator removes it once the forced re-provision completes.
serviceDiscovery
object
URL-resolved view of spec.landingPage for the webapi/landing-page watcher. Includes enabled, displayName, description, url, icon, category, priority, visibility, requiredGroups.