Building a JupyterHub for 60 Students at KNUST with pygeovision Pre-Installed
By Samuel Appiah Kubi · 08 Jul 2026
In January 2025, we helped KNUST's Department of Geomatic Engineering deploy a shared JupyterHub server for 60 students enrolled in their new Geospatial AI course. This post is the technical setup guide we wish had existed when we started.
Hardware
KNUST provided a single server: Dell PowerEdge R750, 64-core Intel Xeon, 256 GB RAM, 4× NVIDIA A40 48 GB GPUs, 20 TB NVMe RAID. This is more than needed — TLJH works fine on a 16-core, 64 GB RAM machine for 30 students with CPU-only inference.
Installation
# Ubuntu 22.04 LTS
sudo apt update && sudo apt install python3 curl -y
# Install The Littlest JupyterHub
curl -L https://tljh.jupyter.org/bootstrap.py | sudo -E python3 - \
--admin samuel \
--show-progress-page
# Install shared packages for all users
sudo -E /opt/tljh/user/bin/pip install \
pygeofetch==1.4.2 \
pygeovision==2.0.9 \
rasterio==1.3.10 \
geopandas==1.0.1 \
torch==2.3.0 torchvision==0.18.0 \
jupyter-lab notebook ipywidgets
Shared Data Storage
Create a shared directory at /srv/shared/eo_data/ with group read permissions. Mount here: the 2019–2024 Sentinel-1 GRD archive for Accra (183 scenes, ~140 GB), the Ghana administrative boundary GeoJSON files, and the pre-downloaded Prithvi-EO-2.0 model weights. Students should not need to re-download data — slow internet connectivity is a reality in many Ghana campus environments.
sudo mkdir -p /srv/shared/eo_data
sudo chown root:jupyterhub-users /srv/shared/eo_data
sudo chmod 775 /srv/shared/eo_data
Copernicus Credentials
Create a shared service account on Copernicus Data Space for the institution. Do not use individual student credentials — Copernicus rate-limits by account. Store the service account credentials in a JupyterHub environment variable available to all users:
sudo tljh-config set user_environment.extra_env.COPERNICUS_USER "knust-eo@knust.edu.gh"
sudo tljh-config set user_environment.extra_env.COPERNICUS_PASS "institutional_password"
sudo tljh-config reload