I already wrote about Jupyter and JupyterLab which is my standard sandbox environment nowadays. There is even a blog post about how to install JupyterLab in an OCI Compute instance. But, JupyterLab is a single-user environment: how can you have the same for multiple users?
Jupyter has an answer for you, it’s named JupyterHub. A tool giving you Jupyter for multiple users, each will have a separate instance and not interfere one with the other (you crash yours, your colleague will not be impacted by it).
Reading the official JupyterHub page I had the impression the installation was tedious and that’s why they suggested a Kubernetes approach or to use another tool which is a packaged installer.
In practice the install is simpler than it looks like! The main downside is that, by default, your JupyterHub will be executed by root. This is something I’m never too comfortable with: I prefer when nothing use root.
The JupyterHub documentation covers all the steps needed to be able to run it as a standard user, which requires to allows sudo privileges for a single command, the one which will start the various JupyterLab instances for the users logging in.
Be default JupyterHub will authenticate users with the users existing locally in the linux environment. This means that only users having a valid linux username and password will be allowed to connect. It’s possible to use external authentications (in a future post I will explain how you can use Oracle IDCS) or even developer a custom authenticator, but the default is by using the local users.
Install JupyterHub in an OCI Compute instance
You maybe have read that I had to setup an environment for a hands-on lab and it was using 16 compute instances setup in the same identical way. For the lab I had to provide a JupyterLab instance for up to 55 users, a perfect use case for JupyterHub.
That’s why I wrote a simple script which does the whole JupyterHub install. Starting from the required Python (only Python 3 is supported), installing the various components needed, creating the required users and groups and, when everything is done, creating a service to automatically start JupyterHub with the compute instance and opening the port in the firewall.
I start with a new Compute instance using Oracle Linux 7.8 where I upload the scrip and execute it.
The script is the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
#!/bin/bash # set basic variables JUPYTERHUB_USER=jupyterhub HUB_USERS_GROUP=hub-users SHADOW_GROUP=shadow # Install the required system packages sudo yum install -y --disablerepo=ol7_developer_EPEL python3 python3-devel oracle-nodejs-release-el7 sudo yum install -y --disablerepo=ol7_developer_EPEL nodejs # Add users and groups sudo groupadd ${JUPYTERHUB_USER} sudo groupadd ${HUB_USERS_GROUP} sudo useradd -d /home/${JUPYTERHUB_USER} -g ${JUPYTERHUB_USER} -G ${HUB_USERS_GROUP} -m -s /bin/bash ${JUPYTERHUB_USER} # Install python packages sudo python3 -m pip install --upgrade pip sudo npm install -g configurable-http-proxy sudo python3 -m pip install jupyterlab jupyterhub notebook sudospawner # Prepare folders for JupyterHub sudo mkdir -p /opt/jupyterhub sudo chown -R ${JUPYTERHUB_USER}.${HUB_USERS_GROUP} /opt/jupyterhub # Configure JupyterHub # - access to /etc/shadow sudo groupadd -r ${SHADOW_GROUP} sudo chown root.${SHADOW_GROUP} /etc/shadow sudo chmod 0640 /etc/shadow sudo usermod -a -G ${SHADOW_GROUP} ${JUPYTERHUB_USER} # - sudo for spawner cat <<EOT >> ~/95-jupyterhub # JupyterHub sudospawner to start Jupyter instances Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin Cmnd_Alias JUPYTER_CMD = /usr/local/bin/sudospawner jupyterhub ALL=(%${HUB_USERS_GROUP}) NOPASSWD:JUPYTER_CMD EOT sudo mv ~/95-jupyterhub /etc/sudoers.d/ sudo chmod 0440 /etc/sudoers.d/95-jupyterhub sudo su - root -c "chown 0.0 /etc/sudoers.d/95-jupyterhub" # - configure JupyterHub sudo su - jupyterhub -c "cd /opt/jupyterhub; /usr/local/bin/jupyterhub --generate-config" sudo tee -a /opt/jupyterhub/jupyterhub_config.py > /dev/null <<EOT c.Spawner.default_url = '/lab' c.JupyterHub.spawner_class = 'sudospawner.SudoSpawner' c.Spawner.notebook_dir = '~' c.PAMAuthenticator.open_sessions = False EOT # Setup service and firewall # - create service file cat <<EOT >> ~/jupyterhub.service [Unit] Description=JupyterHub After=network-online.target [Service] User=${JUPYTERHUB_USER} ExecStart=/usr/local/bin/jupyterhub WorkingDirectory=/opt/jupyterhub [Install] WantedBy=multi-user.target EOT sudo chown root.root ~/jupyterhub.service sudo chmod 0644 ~/jupyterhub.service sudo mv ~/jupyterhub.service /lib/systemd/system/jupyterhub.service # - enable and start service sudo systemctl enable jupyterhub.service sudo systemctl start jupyterhub.service # - open firewall sudo firewall-cmd --zone=public --permanent --add-port=8000/tcp sudo firewall-cmd --reload |
I’m not going to explain every step as it would be like duplicating the JupyterHub documentation. The important part is to configure the 3 variables on top based on your needs/wishes:
- JUPYTERHUB_USER : the name of the user executing JupyterHub (instead of ‘root’ in a default install)
- HUB_USERS_GROUP : the name of the group whose members will be allowed to login in JupyterHub (to not allow any user existing in the linux environment)
- SHADOW_GROUP : the name of the group which will be set as owner of the /etc/shadow file, by default in Oracle Linux the group is ‘root’, but the JupyterHub user must be allowed to read this file to authenticate users.
JupyterHub will be installed in /opt/jupyterhub (edit the script if that location doesn’t suit you).
Once the install is done you can do some tests to see if everything has been created properly.
If everything is correct and you also allowed the connection to port TCP 8000 in the security list of the virtual cloud network, point your browser to the instance address port 8000, http://xxx.xxx.xxx.xxx:8000 .
As said by default it will authenticate only local users with linux username and password defined and being part of the group configured in the script, hub-users if you didn’t change it.
If you want a user not allowed to login by SSH to the instance, but still with a valid login for JupyterHub you can use this kind of commands to create the local users in your linux:
1 2 |
sudo useradd -d /home/jupyhub01 -G hub-users -m -s /sbin/nologin jupyhub01 sudo su - root -c "echo \"MyP4s__1\" | passwd --stdin jupyhub01" |
If you want your user to be able to use the “Terminal” in JupyterLab you will need to use another shell than /sbin/nologin, like for example the default /bin/bash.
As simple as that: install JupyterHub in an OCI Compute instance by executing a single script.