Skip to content

Admin setup

This is the administrator’s entry point: what the chart needs from the cluster, what it derives on its own, and where each knob lives. For a five-minute install, start with Quick Start instead.

RequirementWhyOptional?
nebari-operatorReconciles the NebariApp into routing, TLS, and a Keycloak OIDC clientYes — set nebariapp.enabled: false
Envoy GatewayThe NebariApp’s HTTPRoute attaches to itWith the operator
cert-managerIssues the TLS certificate for the hub hostnameWith the operator
Keycloak (bitnami/keycloakx)Identity provider; the operator provisions the hub client in itWith the operator
A ReadWriteMany StorageClassPer-group shared directoriesYes — see Shared Storage
A default (RWO) StorageClassPer-user home PVCs and Nebi workspace PVCsNo
Namespace label nebari.dev/managed=trueThe operator ignores NebariApps in unlabeled namespacesNo, when the operator is used

Without the operator the chart still installs — dummy authenticator, no routing, no shared Keycloak. That is the local-development path, not a deployment mode.

The chart is built around a single input. Everything else is derived by subdomain convention and can be overridden individually:

keycloak:
hostname: keycloak.example.com

From that one value:

DerivedRuleExample
Base domainkeycloak.hostname minus its first labelexample.com
Hub hostname<subdomains.hub>.<base>hub.example.com
Nebi external URLhttps://<subdomains.nebi>.<base>https://nebi.example.com
Keycloak token URLhttps://<keycloak.hostname>/realms/<realm>/…/token
Hub OIDC client IDjupyterhub-<release>-<chart>jupyterhub-data-science-pack-nebari-data-science-pack
Nebi OIDC client IDnebi-<nebi.releaseName>-nebari-nebi-packnebi-nebi-pack-nebari-nebi-pack
Terminal window
helm repo add nebari https://raw.githubusercontent.com/nebari-dev/helm-repository/gh-pages/
helm repo update
kubectl create namespace data-science
kubectl label namespace data-science nebari.dev/managed=true
helm install data-science-pack nebari/nebari-data-science-pack \
--namespace data-science \
--set keycloak.hostname=keycloak.example.com

Also available as an OCI artifact:

Terminal window
helm install data-science-pack \
oci://quay.io/nebari/charts/nebari-data-science-pack --version <version>

Configuration splits across three layers. Knowing which one you are in explains most “my value did nothing” reports.

LayerPathWhat it is
Chart valueskeycloak, subdomains, nebariapp, singleuser, singleuserCuller, sharedStorage, nebi, rbacThis chart’s own values
Chart-derived hub configjupyterhub.custom.*Read by the Python files in jupyterhub_config.d/ via get_chart_config()
Upstream passthrougheverything else under jupyterhub.*Handed verbatim to Zero to JupyterHub

Field-by-field detail for all three is in the Values reference.

Beyond the z2jh subchart’s own objects:

ObjectTemplatePurpose
NebariAppnebariapp.yamlRouting, TLS, Keycloak client, landing-page card
Hub config ConfigMaphub-config.yamlThe four jupyterhub_config.d/ Python files
Singleuser config ConfigMapsingleuser-config.yamlPer-pod config mounted by the spawner
Nebi config ConfigMapsingleuser-nebi-config.yamlAdmin-provisioned Nebi registries — only when customized
Shared PVC (+ NFS server)shared-pvc.yaml, nfs-server.yamlPer-group shared storage
NFS client installernfs-client-installer.yamlDaemonSet installing nfs-common, opt-in
Keycloak RBAC bootstrap Jobkeycloak-rbac-bootstrap-job.yamlpost-install/upgrade hook; groups mapper + shared-mount role
Two NetworkPoliciessingleuser-gateway-egress.yaml, hub-nebi-networkpolicy.yamlEgress the subchart’s policy does not cover

rbac.bootstrap.enabled defaults to true. It runs as a post-install/post-upgrade hook in the keycloak namespace, authenticates with the admin credentials Secret, and is idempotent — it skips cleanly when kcAdminCredentialSecret is unset, so the chart still installs on clusters that have not surfaced one.

It does four things:

  1. Adds the oidc-group-membership-mapper to the groups client scope. Without it the groups claim is empty, and both shared storage and access: yaml profile gating silently fall back to “no groups”.
  2. Creates the allow-group-directory-creation-role client role on the hub client.
  3. Enables serviceAccountsEnabled on the hub client and binds realm-management.{view-clients,view-groups,view-realm} to its service account.
  4. Assigns the shared-mount role to the groups listed in rbac.bootstrap.sharedMountGroups.

Set enabled: false for BYO-Keycloak or local development. Override namespace, kcAdminCredentialSecret, and kcHost for non-bitnami Keycloak layouts.

  • Nebi — the environment manager. Ships into user pods via an init container and needs a matching OIDC client for token exchange.
  • MLflow — experiment tracking. Two values, one of which is a NetworkPolicy that has to name the pod port rather than the service port.
  • NebariApp — the CRD fields this chart sets and why.
Terminal window
kubectl -n data-science get pods
kubectl -n data-science get nebariapp,httproute,certificate
# The operator only acts on labeled namespaces
kubectl get namespace data-science -o jsonpath='{.metadata.labels}'
# The hub reads its OAuth client from this Secret; absent means dummy auth
kubectl -n data-science get secret data-science-pack-nebari-data-science-pack-oidc-client
# Did the Keycloak bootstrap hook succeed?
kubectl -n keycloak get jobs -l app.kubernetes.io/instance=data-science-pack

Then log in through Keycloak and check that the profile selector appears with the sizes you expect. An empty or unexpectedly short list usually means the groups claim is missing — see Server profiles.