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.
Charts render the NebariApp through the shared nebari-app.nebariApp template
provided by the nebari-app chart, instead of hand-writing the manifest.
Add the dependency in Chart.yaml, then run helm dependency build to fetch it:
dependencies:
-name:nebari-app
repository:oci://quay.io/nebari/charts
version:">=0.1.1"
Set any NebariApp spec field under nebariapp: in values.yaml. Everything
under nebariapp: (except enabled) is passed through to the NebariApp spec,
so all fields documented above can be set here. Each {{ ... }} value is rendered
with the chart context and must produce valid JSON, so a template that renders a string
ends with | toJson. Numbers such as the port below don’t need it:
nebariapp:
enabled:false
hostname:'{{ fail "nebariapp.hostname is required when nebariapp.enabled is true" }}'
service:
name:'{{ include "my-pack.fullname" . | toJson }}'
port:'{{ .Values.service.port }}'
routing:
routes:
-pathPrefix:/
pathType:PathPrefix
tls:
enabled:true
auth:
enabled:false
provider:keycloak
provisionClient:true
scopes:
-openid
-profile
-email
gateway:public
Render the NebariApp in templates/nebariapp.yaml. The if makes it optional,
so the chart works both standalone and on Nebari:
{{- if .Values.nebariapp.enabled}}
{{- include "nebari-app.nebariApp" (dict
"metadata"(dict
"name"(include "my-pack.fullname" .)
"namespace".Release.Namespace
"labels"(include "my-pack.labels" . | fromYaml)
)
"spec"(omit .Values.nebariapp "enabled")
"tplCtx".
) -}}
{{- end}}
"tplCtx" . passes the chart context into the template, so the {{ ... }}
values in values.yaml are rendered with access to .Values, .Release, and
the chart’s named templates.