Set up Jupyter Classroom
-
Install the package
Section titled “Install the package”Terminal window sudo /opt/tljh/hub/bin/pip install jupyter-classroom -
Create the JupyterHub config snippet
Section titled “Create the JupyterHub config snippet”TLJH uses
/opt/tljh/config/jupyterhub_config.d/*.pyas an escape hatch for arbitrary JupyterHub config. Create a new file:Terminal window sudo nano /opt/tljh/config/jupyterhub_config.d/classroom-manager.pyPaste 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 serversc.Spawner.args = ["--LabApp.collaborative=True"]Important notes on the config:
- If TLJH’s own config already defines
load_rolesorload_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.
- If TLJH’s own config already defines
-
Enable Real-Time Collaboration
Section titled “Enable Real-Time Collaboration”Install
jupyter-collaborationin 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-collaborationThis 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.
-
Reload JupyterHub
Section titled “Reload JupyterHub”Terminal window sudo tljh-config reload hubThis restarts JupyterHub with the new config. Running user servers are not affected.
-
Verify the service is running
Section titled “Verify the service is running”Navigate to:
https://<your-tljh-domain>/services/classroom-manager/You should be redirected through JupyterHub OAuth and land on the Classroom Manager dashboard.
Troubleshooting
Section titled “Troubleshooting”Check service logs
Section titled “Check service logs”sudo journalctl -u jupyterhub -fThe managed service stdout/stderr is captured by JupyterHub’s own journal. Look for lines referencing classroom-manager.
Port conflict
Section titled “Port conflict”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).
Dependency issues
Section titled “Dependency issues”If you get import errors, verify the deps are in the hub env:
sudo /opt/tljh/hub/bin/pip list | grep -i fastapiRole/group merge conflicts
Section titled “Role/group merge conflicts”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.
Updating
Section titled “Updating”sudo /opt/tljh/hub/bin/pip install --upgrade jupyter-classroomsudo tljh-config reload hub