Skip to content

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 8000 by default; set the internal container port to 8000.
  • Spawn user pods can expose additional ports internally; manage them via JupyterHub configuration.
  • Persistent storage is required for /home directories and recommended for /srv/jupyterhub config/data.
  • Use Klutch.sh TCP apps for services like PostgreSQL (port 5432 internally, 8000 externally).

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 secrets

Store secrets only in Klutch.sh and avoid committing them to Git.


Installation (local) and starter commands

Install dependencies and test locally:

Terminal window
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
jupyterhub -f configs/jupyterhub_config.py

Optional helper start.sh for portability and Nixpacks fallback:

#!/usr/bin/env bash
set -euo pipefail
source .venv/bin/activate
exec jupyterhub -f configs/jupyterhub_config.py

Make 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 8000
CMD ["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=8000
  • JUPYTERHUB_CONFIG=/app/configs/jupyterhub_config.py
  • DB_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_URL as needed
  • LOG_LEVEL=INFO

If you deploy without a Dockerfile and need Nixpacks overrides:

  • NIXPACKS_BUILD_CMD=pip install -r requirements.txt
  • NIXPACKS_START_CMD=jupyterhub -f configs/jupyterhub_config.py
  • NIXPACKS_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)

  1. Push your repository (with the Dockerfile at the root) to GitHub.
  2. Open klutch.sh/app, create a project, and add an app.
  1. Connect the GitHub repository; Klutch.sh automatically detects the Dockerfile.
  2. Choose HTTP traffic for JupyterHub.
  3. Set the internal port to 8000.
  4. Add the environment variables above (database URL, secrets, authenticator settings, and any NIXPACKS_* overrides if you temporarily deploy without the Dockerfile).
  5. Attach persistent volumes for /home and /srv/jupyterhub (and /tmp/jupyter if needed), selecting sizes based on your retention plan.
  6. 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.