Deploying a JupyterHub App
Introduction
JupyterHub lets teams run multi-user Jupyter notebooks with centralized identity and spawn controls. Deploying it with a Dockerfile on Klutch.sh gives you reproducible environments, managed secrets, and persistent storage for user data—all configured from klutch.sh/app. This guide outlines installation, repository preparation, a production-ready Dockerfile, deployment steps, Nixpacks overrides, and policies for secure notebook access.
Prerequisites
- A Klutch.sh account (create one)
- A GitHub repository with your JupyterHub configuration (GitHub is the only supported git source)
- Docker familiarity and Python 3.10+ knowledge
- Database credentials (PostgreSQL) for user and server persistence
- Storage for home directories and shared datasets
- Optional: OAuth or LDAP credentials for authentication
For onboarding guidance, reference the Quick Start.
Architecture and ports
- JupyterHub exposes HTTP on port
8000by default; set the internal container port to8000. - Spawn user pods can expose additional ports internally; manage them via JupyterHub configuration.
- Persistent storage is required for
/homedirectories and recommended for/srv/jupyterhubconfig/data. - Use Klutch.sh TCP apps for services like PostgreSQL (port
5432internally,8000externally).
Repository layout
jupyterhub/├── Dockerfile # Must live at repo root for auto-detection├── configs/ # Custom jupyterhub_config.py or auth setups├── notebooks/ # Shared notebooks (optional volume)├── requirements.txt├── start.sh # Optional helper└── .env.example # Template only; no secretsStore secrets only in Klutch.sh and avoid committing them to Git.
Installation (local) and starter commands
Install dependencies and test locally:
python -m venv .venvsource .venv/bin/activatepip install -r requirements.txtjupyterhub -f configs/jupyterhub_config.pyOptional helper start.sh for portability and Nixpacks fallback:
#!/usr/bin/env bashset -euo pipefailsource .venv/bin/activateexec jupyterhub -f configs/jupyterhub_config.pyMake it executable with chmod +x start.sh.
Dockerfile for JupyterHub (production-ready)
Place this Dockerfile at the repo root; Klutch.sh auto-detects it (no Docker option in UI):
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/*
COPY requirements.txt ./RUN pip install --no-cache-dir -r requirements.txt
COPY . .ENV PORT=8000
EXPOSE 8000CMD ["jupyterhub", "-f", "configs/jupyterhub_config.py"]Notes:
- Pin dependency versions for reproducibility.
- For GPU workloads, switch to a CUDA-enabled base with required packages.
Environment variables (Klutch.sh)
Set these in the Klutch.sh app settings (Secrets tab) before deploying:
PORT=8000JUPYTERHUB_CONFIG=/app/configs/jupyterhub_config.pyDB_URL=postgresql://<user>:<password>@<host>:<port>/<db>JUPYTERHUB_COOKIE_SECRET=<secure-hex>AUTHENTICATOR_CLASS=oauthenticator.GoogleOAuthenticator(if using OAuth)OAUTH_CLIENT_ID,OAUTH_CLIENT_SECRET,OAUTH_CALLBACK_URLas neededLOG_LEVEL=INFO
If you deploy without a Dockerfile and need Nixpacks overrides:
NIXPACKS_BUILD_CMD=pip install -r requirements.txtNIXPACKS_START_CMD=jupyterhub -f configs/jupyterhub_config.pyNIXPACKS_PYTHON_VERSION=3.11
These keep JupyterHub compatible with Nixpacks defaults when a Dockerfile is absent.
Attach persistent volumes
Add mount paths and sizes in Klutch.sh (no names required):
/home— user home directories./srv/jupyterhub— config, data, and state./tmp/jupyter— optional cache or temporary storage.
Ensure the notebook user can write to these paths inside the container.
Deploy JupyterHub on Klutch.sh (Dockerfile workflow)
- Push your repository (with the Dockerfile at the root) to GitHub.
- Open klutch.sh/app, create a project, and add an app.
- Connect the GitHub repository; Klutch.sh automatically detects the Dockerfile.
- Choose HTTP traffic for JupyterHub.
- Set the internal port to
8000. - Add the environment variables above (database URL, secrets, authenticator settings, and any
NIXPACKS_*overrides if you temporarily deploy without the Dockerfile). - Attach persistent volumes for
/homeand/srv/jupyterhub(and/tmp/jupyterif needed), selecting sizes based on your retention plan. - Deploy. Your hub will be accessible at
https://example-app.klutch.sh; map a custom domain if desired.
Health checks and production tips
- Add a reverse proxy health check hitting
/hub/health. - Enforce HTTPS at the edge and forward requests securely.
- Rotate secrets periodically and keep them in Klutch.sh secrets.
- Monitor disk usage on persistent volumes, resizing proactively.
- Keep dependencies and authenticator plugins pinned for compatibility.
JupyterHub on Klutch.sh combines reproducible Docker builds with managed secrets, persistent volumes, and flexible HTTP/TCP routing. With the Dockerfile at the repo root and ports set to 8000 for the hub (8000 externally for any TCP companions), you can host collaborative notebook environments without extra YAML or workflow overhead.