Skip to content

Set up Jupyter Classroom

  1. Terminal window
    sudo /opt/tljh/hub/bin/pip install jupyter-classroom
  2. TLJH uses /opt/tljh/config/jupyterhub_config.d/*.py as an escape hatch for arbitrary JupyterHub config. Create a new file:

    Terminal window
    sudo nano /opt/tljh/config/jupyterhub_config.d/classroom-manager.py

    Paste the following:

    c.JupyterHub.services = [
    {
    "name": "classroom-manager",
    "url": "http://127.0.0.1:10101",
    "command": ["/opt/tljh/hub/bin/jupyter-classroom"],
    "oauth_client_allowed_scopes": ["identify"],
    "admin": True
    },
    ]
    c.JupyterHub.load_roles = [
    {
    "name": "classroom-manager-role",
    "services": ["classroom-manager"],
    "scopes": [
    "list:users",
    "read:users",
    "admin:servers",
    "admin:groups",
    "admin:users",
    "read:groups",
    "list:groups",
    ],
    },
    {
    "name": "user",
    "scopes": [
    "self",
    "access:services!service=classroom-manager",
    ],
    },
    ]
    # Enable real-time collaboration in student servers
    c.Spawner.args = ["--LabApp.collaborative=True"]

    Important notes on the config:

    • If TLJH’s own config already defines load_roles or load_groups (or if you have other config snippets that do), you will get conflicts. JupyterHub does not merge list-based config across files — the last assignment wins. If you have existing role/group config, you need to consolidate into a single file.
  3. Install jupyter-collaboration in the singleuser environment (not the hub environment) so that teachers can co-edit notebooks with students:

    Terminal window
    sudo /opt/tljh/user/bin/pip install jupyter-collaboration

    This enables the “Join” button in the Classroom Manager dashboard. When a teacher clicks “Join” on a running student server, they open the student’s JupyterLab with real-time collaborative editing.

  4. Terminal window
    sudo tljh-config reload hub

    This restarts JupyterHub with the new config. Running user servers are not affected.

  5. Navigate to:

    https://<your-tljh-domain>/services/classroom-manager/

    You should be redirected through JupyterHub OAuth and land on the Classroom Manager dashboard.

Terminal window
sudo journalctl -u jupyterhub -f

The managed service stdout/stderr is captured by JupyterHub’s own journal. Look for lines referencing classroom-manager.

If port 10101 is already in use, change it in both the "url" field in the service config and in app.py (the uvicorn bind port).

If you get import errors, verify the deps are in the hub env:

Terminal window
sudo /opt/tljh/hub/bin/pip list | grep -i fastapi

If Classroom Manager doesn’t appear or you get permission errors, check whether another config snippet is overwriting load_roles or load_groups. Consolidate all role/group definitions into one file.

Terminal window
sudo /opt/tljh/hub/bin/pip install --upgrade jupyter-classroom
sudo tljh-config reload hub