Python - How to install jupyterhub on rocky linux

Python - How to install jupyterhub on rocky linux

Sat 06 August 2022

How to install jupyterhub on a rocky linux server.

Install jupytherhub on a rocky linux server

As part of a course I have found the need / interest to setup a jupyterhub instance. This short post is an overview of the steps needed to achieve a running server.

First I install conda, jupyterhub and notebooks:

(base) [adrock2nd@pythoncourse ~]$ curl -O # download the installer from anaconda
(base) [adrock2nd@pythoncourse ~]$ chmod +x # make the installer executable
(base) [adrock2nd@pythoncourse ~]$ ./ # this steps implies that you trust the installer
(base) [adrock2nd@pythoncourse ~]$ conda install jupyterhub  # installs jupyterhub and proxy
(base) [adrock2nd@pythoncourse ~]$ conda install jupyterlab notebook  # needed if running the notebook servers in the same environment

Test your installation:

(base) [adrock2nd@pythoncourse ~]$ jupyterhub -h
(base) [adrock2nd@pythoncourse ~]$ configurable-http-proxy -h

Generate a default configfile:

(base) [adrock2nd@pythoncourse ~]$ mkdir jupyterhub
(base) [adrock2nd@pythoncourse ~]$ jupyterhub --generate-config -f ~/jupyterhub/
Writing default config to: /home/adrock2nd/jupyterhub/

We want to encrypt the traffic to our service so we need a certificate. The easies way is probably to use letsencrypt:

(base) [adrock2nd@pythoncourse ~]$ sudo dnf install epel-release
(base) [adrock2nd@pythoncourse ~]$ sudo dnf upgrade
(base) [adrock2nd@pythoncourse ~]$ sudo yum install snapd
(base) [adrock2nd@pythoncourse ~]$ sudo systemctl enable --now snapd.socket
(base) [adrock2nd@pythoncourse ~]$ sudo ln -s /var/lib/snapd/snap /snap
(base) [adrock2nd@pythoncourse ~]$ sudo snap install core
(base) [adrock2nd@pythoncourse ~]$ sudo snap refresh core
(base) [adrock2nd@pythoncourse ~]$ sudo snap install --classic certbot
(base) [adrock2nd@pythoncourse ~]$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
(base) [adrock2nd@pythoncourse ~]$ sudo certbot certonly --standalone
(base) [adrock2nd@pythoncourse ~]$ sudo certbot renew --dry-run
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/
Key is saved at:         /etc/letsencrypt/live/

Edit your jupyterhub_config file with the following three changes:

c.JupyterHub.ssl_cert = '/etc/letsencrypt/live/'
c.JupyterHub.ssl_key = '/etc/letsencrypt/live/'
c.JupyterHub.bind_url = 'https://:443'

Start your jupyterhub with elevated priviliges:

(base) [adrock2nd@pythoncourse ~]$ sudo /opt/miniconda3/bin/jupyterhub

You are now ready to login to the jupyterserver.

Basic security

We want to secure the server a little bit more than what it is as default. We will do a couple of things related to encrypting the traffic between the internal components of jupyterhub, mainly traffic between the 'proxy' and the 'notebook server' and traffic between the 'notebook server' and the 'kernel'. We also disable the possibility for our users to load their own configuration:

c.JupyterHub.internal_certs_location = 'internal-ssl'
c.JupyterHub.internal_ssl = True
c.JupyterHub.recreate_internal_certs = True
c.JupyterHub.trusted_alt_names = ['']
c.Spawner.disable_user_config = True
c.Spawner.args = ['--transport="IPC"']
c.Spawner.ssl_alt_names = ['']

Then we generate the certs and start the server:

(base) [adrock2nd@pythoncourse ~]$ sudo /opt/miniconda3/bin/jupyterhub

Create a shared folder for all our users

We want to provide coursematerial and examplefiles to all our users. We solve this by creating a shared folder that everyone has read/exec permissions to. Then we symlink the shared folder into every users homefolder. For this to work we need a textfile with all our usernames, one for each line.

(base) [adrock2nd@pythoncourse ~]# mkdir -p /srv/data/shared
(base) [adrock2nd@pythoncourse ~]# for i in `cat users.txt` ; do ln -sf /srv/data/shared /home/$i ; done

To be continued / Disclaimer

The above steps works, and will result in a jupyterhub, with encrypted traffic to and from the server. However there might be some steps that will make the setup more robus. I.e using a frontend webserver like apache or nginx instead of the build-in webserver, using a dedicated user / group to run the services instead of root +++. Use this steps as a start and then expand the setup to your needs before putting it into production.