Setting Up Jupyter Notebook and Lab with venv

The objectives of this setup, aside of replacing my older notebook server, are:

  • running both jupyter 6 and 7
  • running them in venv

Set Up directories and venv

My holding directory /data/websites.

cd /data/websites
mkdir jupyter
cd jupyter
mkdir jupyter_6
mkdir jupyter_7

Setting Up Jupyter 6

cd jupyter_6
python3.10 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install wheel
pip install jupyter

Creating here another directory, jupyter which will hold the notebooks:

mkdir jupyter

Creating a user for Jupyter 6

groupadd -g 2000 jupyter
useradd -u 2000 -g 2000 -c "jupyter" -s /bin/bash -d /data/websites/jupyter/jupyter_6/jupyter -M jupyter

The home directory for the user will be the directory which will hold the notebooks.

Directories ownership

chown jupyter:jupyter /data/websites/prod/jupyter
chown jupyter:jupyter /data/websites/prod/jupyter/jupyter_6
chown jupyter:jupyter /data/websites/prod/jupyter/jupyter_6/jupyter

Creating a password hash

Creating a password hash to add it to the config file so we will have the password enabled instead of using token.

(venv) jupyter@srv7:~$ python
Python 3.10.5 (main, Dec 11 2022, 14:11:09) [GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from notebook.auth import passwd
>>> passwd()
Enter password: 
Verify password: 
'argon2:$argon2id$v=19$m=10240,t=10,p=8$asm7s98mCWvciYkb2NwlXQ$fR3hLmOl+yRQaKbJiimHSniisdjvRWDPZrpcRgi35I0'
>>> 
(venv) jupyter@srv7:~$

Configuring Jupyter 6

jupyter notebook --generate-config

The config file .jupyter/jupyter_notebook_config.py in the jupyter user's home directory.

Changes to the config file

c.NotebookApp.allow_remote_access = True
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.password = 'argon2:$argon2id$v=19$m=10240,t=10,p=8$asm7s98mCWvciYkb2NwlXQ$fR3hLmOl+yRQaKbJiimHSniisdjvRWDPZrpcRgi35I0'
c.NotebookApp.quit_button = False

I am also creating a Notebooks directory within the jupyter directory which is also the home directory for jupyter user.
The idea would be to just have the notebooks separated from the other things in that directory.

(venv) jupyter@srv7:~$ mkdir Notebooks

Creating a systemd service file for Jupyter 6

/etc/systemd/system/jupyter.service

[Unit]
Description=Jupyter Notebook v6

[Service]
Type=simple
PIDFile=/run/jupyter.pid
ExecStart=/data/websites/jupyter/jupyter_6/venv/bin/jupyter notebook --config=/data/websites/jupyter/jupyter_6/jupyter/.jupyter/jupyter_notebook_config.py
User=jupyter
Group=jupyter
WorkingDirectory=/data/websites/jupyter/jupyter_6/jupyter/Notebooks
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Creating an nginx config file

/etc/nginx/conf.d/notebook.conf

upstream notebook {
    server localhost:8888;
}
server{
       listen 80;
       server_name notebook.domain.dom;

       access_log /var/log/nginx/notebook.access.log;
       error_log /var/log/nginx/notebook.error.log;
       client_max_body_size 20m;

       location / {
            proxy_pass            http://notebook;
            proxy_set_header      Host $host;
       }

        location ~ /api/kernels/ {
            proxy_pass            http://notebook;
            proxy_set_header      Host $host;
            proxy_http_version    1.1;
            proxy_set_header      Upgrade "websocket";
            proxy_set_header      Connection "Upgrade";
            proxy_read_timeout    86400;
        }
        location ~ /terminals/ {
            proxy_pass            http://notebook;
            proxy_set_header      Host $host;
            proxy_http_version    1.1;
            proxy_set_header      Upgrade "websocket";
            proxy_set_header      Connection "Upgrade";
            proxy_read_timeout    86400;
        }
}

Accessing it: http://notebook.domain.dom

Setting Up Jupyter 7 (with JupyterLab)

The steps are pretty much like the ones for jupyter 6.

cd jupyter_7
python3.10 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install wheel
pip install notebook==7.0.0b2

Creating here (inside jupyter_7) another directory, jupyter which will hold the notebooks:

mkdir jupyter

Creating a user for Jupyter 7

Using the same group created with jupyter user.

useradd -u 2001 -g 2000 -c "jupyterlab" -s /bin/bash -d /data/websites/prod/jupyter/jupyter_7/jupyter -M jupyterlab
chown jupyterlab:jupyter /data/websites/prod/jupyter/jupyter_7
chown jupyterlab:jupyter /data/websites/prod/jupyter/jupyter_7/jupyter

The home directory for the user will be the directory which will holds the notebooks.

Using the same password like the one for jupyter 6.

Configuring Jupyter 7

Creating the config file:

(venv) jupyterlab@srv7:~$ jupyter-lab --generate-config
Writing default config to: /data/websites/prod/jupyter/jupyter_7/jupyter/.jupyter/jupyter_lab_config.py
(venv) jupyterlab@srv7:~$ 

Changes to the config file

c.ServerApp.allow_remote_access = True
c.ServerApp.ip = '0.0.0.0'
c.ServerApp.password = 'argon2:$argon2id$v=19$m=10240,t=10,p=8$asm7s98mCWvciYkb2NwlXQ$fR3hLmOl+yRQaKbJiimHSniisdjvRWDPZrpcRgi35I0'

I am also creating a Notebooks directory within the jupyter directory which is also the home directory for jupyter user.
The idea would be to just have the notebooks separate from the other things in that directory.

(venv) jupyterlab@srv7:~$ pwd
/data/websites/prod/jupyter/jupyter_7/jupyter
(venv) jupyterlab@srv7:~$ mkdir Notebooks

Creating a systemd service file for Jupyter 7

/etc/systemd/system/jupyterlab.service

[Unit]
Description=JupyterLab

[Service]
Type=simple
PIDFile=/run/jupyterlab.pid
ExecStart=/data/websites/jupyter/jupyter_7/venv/bin/jupyter-lab --config=/data/websitesjupyter/jupyter_7/jupyter/.jupyter/jupyter_lab_config.py
User=jupyterlab
Group=jupyter
WorkingDirectory=/data/websites/prod/jupyter/jupyter_7/jupyter/Notebooks/
Restart=always
RestartSec=10
#KillMode=mixed

[Install]
WantedBy=multi-user.target

Creating an nginx config file

/etc/nginx/conf.d/jupyterlab.conf

upstream jupyterlab {
    server localhost:8889;
}

server{
       listen 80;
       server_name jupyterlab.domain.dom;

       access_log /var/log/nginx/jupyterlab.access.log;
       error_log /var/log/nginx/jupyterlab.error.log;
       client_max_body_size 20m;

       http2_push_preload on; # Enable HTTP/2 Server Push

       location / {
            proxy_pass         http://jupyterlab;
            proxy_http_version 1.1;
            proxy_buffering    off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;          
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection "Upgrade";
            proxy_set_header   X-Scheme $scheme;
            proxy_set_header   X-Forwarded-Proto https;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
       }
}

Accessing it: http://jupyterlab.domain.dom