Configuration
JHub Apps (JupyterHub Apps) allows for flexible configuration to suit different deployment needs. The configurations
are defined in the jupyterhub_config.py file, setting various attributes via:
c.JAppsConfig.<CONFIG> = <CONFIG_VALUE>bind_url
Section titled “bind_url”The URL where JupyterHub binds the service.
- Example:
c.JupyterHub.bind_url = "http://127.0.0.1:8000"
- Notes: It sets the main address JupyterHub listens on for incoming requests.
jupyterhub_config_path
Section titled “jupyterhub_config_path”Specifies the path to the jupyterhub_config.py file. This is used internally by JHub Apps for
accessing configurations.
- Example:
c.JAppsConfig.jupyterhub_config_path = "jupyterhub_config.py"
conda_envs
Section titled “conda_envs”A list of conda environments that JHub Apps can access or use. This can either be a static list or a callable.
- Example:
c.JAppsConfig.conda_envs = ["env1", "env2"]
- Notes: Define any necessary environments for apps that rely on specific dependencies.
service_workers
Section titled “service_workers”Sets the number of service worker processes to be created for handling user requests.
- Example:
c.JAppsConfig.service_workers = 1
default_url
Section titled “default_url”The default URL users are directed to after login.
- Example:
c.JupyterHub.default_url = "/hub/home"
allowed_frameworks
Section titled “allowed_frameworks”A list of frameworks that are permitted to be launched through JHub Apps.
- Example:
c.JupyterHub.allowed_frameworks = ["jupyterlab", "bokeh"]
- Notes:
- Supports the following values for frameworks:
panelbokehstreamlitplotlydashvoilagradiojupyterlabcustom
- Allowing JupyterLab can potentially expose user to sharing their entire filesystem, if the created JupyterLab app is accidentally shared. It also allows the user to swap JupyterLab runtime, which could disable system extensions and let them run arbitrary and potentially dangerous extensions.
- Supports the following values for frameworks:
blocked_frameworks
Section titled “blocked_frameworks”Specifies frameworks that users are restricted from launching.
- Example:
c.JupyterHub.blocked_frameworks = ["voila"]
startup_apps
Section titled “startup_apps”A list of apps to automatically create or update when JHub Apps service starts. Apps can be created from a local file or from a git repo.
Servers will be created or modified if already existing to match the config. Removing items from this list won’t delete any servers.
- Example:
c.JAppsConfig.startup_apps = [# define app from git repo{"username": "my-user", # app will be created by this user"servername": "my-startup-server", # specify a unique server name"user_options": {"display_name": "My Startup Server","description": "description","thumbnail": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNkYPhfz0AEYBxVSF+FAP5FDvcfRYWgAAAAAElFTkSuQmCC", # base64 encoded image data to use for thumbnail"filepath": "panel_basic.py", # local file or path within git repo"framework": "panel","public": False, # Whether or not app is publicly accessible without authentication"keep_alive": False, # Whether or not to shut down app after a period of idleness"env": {"MY_ENV_VAR": "MY_VALUE"},"repository": {"url": "https://github.com/nebari-dev/jhub-apps-from-git-repo-example.git"}, # specify if pulling app from git repo"conda_env": "my-conda-env","profile": "my-compute-profile","share_with": {"users": ["my-other-user"], "groups": ["group1", "group2"]},},},# Define a startup app from local files{"username": "my-other-user","servername": "another-startup-server","user_options": {"filepath": "panel_basic.py","repository": None... # other fields as above},}]
jhub_app_proxy_version
Section titled “jhub_app_proxy_version”Specifies the version of jhub-app-proxy to install when deploying apps.
- Example:
c.JAppsConfig.jhub_app_proxy_version = "v0.6"
- Notes:
- This sets the default version globally for all apps
- Can be overridden per-app by setting the
JHUB_APP_PROXY_VERSIONenvironment variable in the app’s configuration - Priority: App-specific
JHUB_APP_PROXY_VERSIONenv var > Global config > Default
additional_services
Section titled “additional_services”List of additional external services to display in JupyterHub’s services menu. Services with pinned=True
will also appear in the quick access section for easy access.
- Example:
c.JAppsConfig.additional_services = [{"name": "Monitoring","url": "/grafana","description": "System monitoring dashboard","pinned": True,"thumbnail": "https://example.com/grafana-logo.svg",},{"name": "Argo","url": "/argo",},{"name": "Environments","url": "/conda-store","description": "Conda environment manager","pinned": True,"thumbnail": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNkYPhfz0AEYBxVSF+FAP5FDvcfRYWgAAAAAElFTkSuQmCC",},]
- Fields:
name(required): Display name of the serviceurl(required): URL path for the servicedescription(optional): Description of the service shown in the UIpinned(optional): Whether the service should appear in the quick access section (default:False)thumbnail(optional): URL or base64-encoded data URL for the service icon (e.g.,"https://..."or"data:image/png;base64,...")
- Notes:
- This replaces the older approach of manually extending
c.JupyterHub.serviceswith custom service dictionaries - For advanced use cases, you can still use the programmatic approach with the
service_for_jhub_appshelper:from jhub_apps import service_for_jhub_appsc.JupyterHub.services.extend([service_for_jhub_apps(name="Custom Service",url="/custom",description="My custom service",pinned=True,),])
- This replaces the older approach of manually extending
banners
Section titled “banners”Full-width text banners displayed above (top) and below (bottom) the JHub Apps UI,
e.g. for platform notices or classification markings (like on the Nebari landing
page). A banner is disabled while its text is empty, so no banners are shown by
default.
- Example:
c.JAppsConfig.banners = {"top": {"text": "This platform will be down for maintenance on Saturday","background": "#502b85","foreground": "#ffffff",},"bottom": {"text": "CUI",},}
- Fields (for each of
topandbottom, both optional):text(required to enable the banner): Banner text, always rendered as plain text (never HTML)background(optional): CSS background color; falls back to the theme’s foreground colorforeground(optional): CSS text color; falls back to the theme’s background color
- Notes:
- Banners appear on the React launcher pages and on JupyterHub’s server-rendered pages (login, admin, token, spawn) — both read the same runtime config.
- The values are served to the UI at runtime via
/services/japps/config.json, so changing them only requires restarting the hub — no frontend rebuild. - When omitted,
background/foregrounduse the theme’s inverted colors, which follow the user’s light/dark mode. Values containing CSS injection vectors (;, braces, quotes,url(, etc.) are ignored and fall back to the defaults. - When deploying with a Helm chart (e.g. Zero to JupyterHub or the Nebari data
science pack), set the option from your values via
hub.extraConfiglike any otherJAppsConfigoption:hub:extraConfig:01-banners: |c.JAppsConfig.banners = {"top": {"text": "This platform will be down for maintenance on Saturday"},}
Theme runtime configuration
Section titled “Theme runtime configuration”Branding is read from c.JupyterHub.template_vars and served to the UI at
runtime via /services/japps/config.json (React pages) and
/services/japps/theme.css (server-rendered JupyterHub pages), so a change only
needs a hub restart.
- Example:
from jhub_apps import themesc.JupyterHub.template_vars = {**themes.DEFAULT_THEME,"logo": "/services/japps/static/img/my-logo.svg","primary_color": "#005EA2","primary_color_light": "#005EA210","primary_color_dark": "#1A4480","navbar_color": "#ffffff","navbar_text_color": "#2E2F33","font_family": "'Inter', sans-serif","font_url": "https://fonts.googleapis.com/css2?family=Inter&display=swap",}
- Notes:
themes.DEFAULT_THEMEonly sets the logo, favicon and font. With no colour keys set, the UI renders the Nebari design-system theme in both light and dark mode.- Some keys apply in light mode only (
navbar_color,navbar_text_color,navbar_hover_color,text_color,h1_color,h2_color). - See Branding for every supported key, the CSS variable each one becomes, what it affects on the React pages versus the server-rendered pages, how the dark-mode logo is chosen, and screenshots.