Skip to content

Configuration

The chart aims to need only one field for a fresh deploy — keycloak.hostname — with everything else derived by subdomain convention. Every derived value can still be overridden explicitly. Values under jupyterhub.* are passed straight through to the upstream Zero to JupyterHub chart.

SectionControls
keycloakExternal Keycloak FQDN, realm name, in-cluster service host
subdomainsSubdomain convention (hub, nebi) used to derive hostnames from keycloak.hostname
nebariappWhether/how the NebariApp CRD is rendered — routing, auth, landing-page card. See NebariApp Integration
singleuserEgress NetworkPolicy allowing user pods to reach the Nebari gateway
singleuserCullerIn-pod idle culling for kernels, terminals, and the server itself (separate from the hub-level jupyterhub.cull)
vscodeActivityInteraction-based idle culling for VS Code; enabled: false reverts to counting raw proxied traffic as activity
sharedStoragePer-group RWX directories and the transitional in-cluster NFS mode. See Shared Storage
nebiThe companion Nebi service — image, external/internal URLs, namespace, release name
rbac.bootstrapOne-shot Keycloak Job that adds the groups-claim mapper and the shared-mount client role
jupyterhubPassed through verbatim to the jupyterhub subchart (proxy, hub, singleuser images, auth, etc.)

For the full set of fields and their defaults, read values.yaml directly — it is heavily commented and is the source of truth. The Values reference covers the same ground field by field, including the derivation rules and the defaults worth knowing about before you override them.

The dummy authenticator is used by default so any username/password works without a Keycloak dependency. To test against real OAuth, configure jupyterhub.hub.config per the Zero to JupyterHub authentication docs.

An open VS Code tab holds a websocket whose keepalives used to count as Jupyter activity, so pods with an idle VS Code tab were never culled (#208). The pack now handles VS Code idleness like notebook idleness:

  • Real interaction counts. A bundled extension (nebari-activity-reporter, installed automatically on every spawn) reports typing, scrolling, terminal use, and window focus to the Jupyter server. A running terminal command also counts as active — same policy as cullBusy: false for kernels — provided the shell has VS Code shell integration (automatic for bash/zsh; exotic shells running long jobs are not detected).
  • Raw traffic no longer defeats the in-pod culler. The /vscode/ proxy route runs with update_last_activity disabled, so keepalives from an idle tab no longer keep jupyter-server’s own activity clock fresh. The hub-level jupyterhub.cull culler is not fixed by this: proxied websocket traffic is still visible to configurable-http-proxy at the route level, so the hub keeps seeing activity for as long as a tab stays connected, regardless of update_last_activity. The setting that actually culls an idle-tab pod is the in-pod singleuserCuller.server.shutdownNoActivityTimeout (default 900 seconds / 15 minutes), which jupyter-server evaluates from its own activity clock; set it to 0 to disable this feature.
  • Disconnected sessions exit promptly. CODE_SERVER_IDLE_TIMEOUT_SECONDS is set to singleuserCuller.server.shutdownNoActivityTimeout (skipped when the value is ≤ 60 seconds, which code-server rejects — including 0, i.e. in-pod culling disabled), so a code-server process whose last browser connection has closed exits on the same schedule that culls idle pods instead of lingering.
  • Delivery failure fails safe. The proxy-activity opt-out only takes effect when the reporter extension is actually present in the extensions directory. If the per-spawn install fails, proxied traffic counts as activity again — the pod over-spends rather than culling an active user who has no keep-alive channel.

To revert to the previous behavior (any open tab keeps the pod alive), set:

vscodeActivity:
enabled: false

For a hard cost cap regardless of activity — e.g. a tab left open on an always-awake machine — the hub culler’s max-age is available separately:

jupyterhub:
cull:
maxAge: 86400 # kill servers after 24h no matter what