Auto-héberger un serveur de développement JupyterHub

Nicolas Mesnier

Mis à jour le 16/01/2023.

JupyterHub est un logiciel libre distribué sous licence BSD qui a pour objectif de fournir une solution de développement multi-utilisateurs basée sur Jupyter à travers des “notesbook”, c’est-à-dire une application web qui juxtapose sur un seul document :

Cette interactivité permet aux élèves d’expérimenter et de tester leur code au fur à mesure de l’avancée dans leur document de travail, devrait faciliter l’apprentissage de la programmation en Python.

On trouve dans ce document quelques éléments permettant d’auto-héberger un serveur de de développement JupyterHub, c’est-à-dire :

Pour la suite, j’utilise les variables :

${JUPYTER}      # le nom de la VM sur laquelle tourne JupyterHub
${PRIVATE_IP}   # l'IP privée de cette VM, du type 192.168.1.XX
${PUBLIC_IP}    # votre IP publique, celle de votre box
${MONDOMAINE}   # votre nom de domaine

Sur l’hôte de la VM

J’ai pris l’habitude d’administrer mes machines virtuelles avec KVM. Pour faire de même, sur l’hôte installer :

# apt install qemu-system qemu-system-x86 qemu-utils \
    libvirt-clients libvirt-daemon-system \
    virtinst bridge-utils

Connexion de type bridge

Pour que la VM partage la connexion réseau de l’hôte, il est nécessaire de définir une connexion de type bridge par exemple avec le script :

export MAIN_CONN=enp0s31f6
bash -x << EOF
systemctl stop libvirtd
nmcli c delete "$MAIN_CONN"
nmcli c delete "Wired connection 1"
nmcli c add type bridge ifname br0 autoconnect yes con-name br0 stp off
nmcli c modify br0 ipv4.addresses ${PRIVATE_IP}/24 ipv4.method manual
nmcli c modify br0 ipv4.gateway 192.168.1.1
nmcli c modify br0 ipv4.dns 192.168.1.1
nmcli c add type bridge-slave autoconnect yes con-name "$MAIN_CONN" \
    ifname "$MAIN_CONN" master br0
systemctl restart NetworkManager
systemctl start libvirtd
systemctl enable libvirtd
echo "net.ipv4.ip_forward = 1" \
    | sudo tee /etc/sysctl.d/99-ipforward.conf
sysctl -p /etc/sysctl.d/99-ipforward.conf
EOF

enp0s31f6 est le nom de votre carte réseau, obtenu avec :

$ nmcli con show

Machine virtuelle

Sur la machine virtuelle

Tester en local

Sur votre box Internet

Ouvrir les ports

Sur le serveur frontal

Dans le cas où JupyterHub n’est pas le seul service hébergé sur ${MONDOMAINE}, il est nécessaire de définir un reverse proxy pour rediriger les requêtes de votre sous-domaine

jupyter.${MONDOMAINE}

vers

http://${PRIVATE_IP}:8000

Pour le reverse proxy, on utilise ici NGINX.

Installer et configurer NGINX

Configuration TLS

Afin de sécuriser le protocole HTTP avec une couche de chiffrement SSL/TLS et garder privées les communications entre les utilisateurs et le serveur, on utilisera par défaut le HTTPS, en écoute du port TCP 443.

On se réfère aux recommandations de la fondation mozilla qui ne sont pas en contradiction avec celles de l’ANSSI. On utilise en particulier le générateur sur lequel on renseigne la version de [NGINX], obtenue avec :

$ nginx -v

et celle de openssl

$ openssl version

Pour intégrer ces recommandations, il faut :

Durcissement des réponses HTTP

On se base sur les recommandations de l’ANSII et sur l’article pour durcir les réponses HTTP du serveur, notamment :

Pour cela, éditer le fichier de configuration :

# vim /etc/nginx/nginx.conf

en ajoutant les lignes :

 server{
    ...
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()";
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Xss-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header 'Referrer-Policy' 'origin';
    ...
 }

puis relancer [NGINX] :

# service nginx restart

Vérifier ensuite votre configuration en faisant analyser votre site.

Configuration pour JupyterHub

Configurer le par-feu

Générer les certificats SSL

Tester

Enfin

Pour définir un service qui permette de lancer JupyterHub avec systemd dès le lancement de la VM :

virsh start ${JUPYTER}

sur la machine virtuelle

Mise à jour

Pour mettre à jour JupyterHub, il suffit d’utiliser le gestionaire de paquets du système

# apt update && apt full-upgrade

et avec pip3 :

# pip3 install --upgrade jupyterhub

En cas de problème avec la mise à jour de la base de données, quand la commande

# jupyterhub upgrade-db

n’a aucun effet, il faut la supprimer pour en créer une nouvelle

# find / -name "jupyterhub.sqlite" -delete

Ressources

Tutoriaux d’intsallation