Header: JupyterLab

Running JupyterLab behind Caddy with Supervisor

2024-09-22

It seems simple to use Supervisor to start multiple JupyterLab instances and a Caddy reverse proxy to access them. But there are some tricks to know, especially used with uv for environment management.

 

I use uv to manage different virtual environments for Python. And I also use it for managing JupyterLab environments. One day, I want to run two different instances of JupyterLab on the same server. It's easy for the environment part thanks to uv. But if I don't want to open too many ports, I have to use a reverse proxy to connect. Caddy seems a good choice since its simplicity. Furthermore, a process manager is favorable, so I plan to add Supervisor.

The set-up should be simple, but it turns out that it wasn't.

Modify Caddy config #

I'm using Debian 12 for the server, and the getting started guide of Caddy is misleading. After installing Caddy with

sudo apt install caddy
bash

I'm having problem with modifying the config. I created a Caddyfile in the current directory and run caddy adapt. It shows

INFO     using adjacent Caddyfile
{"apps":{"http":{"servers":{"srv0"...
text

From the output, I thought the config had taken effect, but in fact it didn't. Instead, I have to use caddy reload to update the config. However, the config updated like this will not survive after system restart. A better way is to directly modify /etc/caddy/Caddyfile and run:

sudo systemctl restart caddy
bash

Use Unix socket for communication #

I don't want to open too many ports, and fortunately, both JupyterLab and Caddy supports using Unix sockets. I want to make JupyterLab run as the default user (debian). Therefore, to enable communications with Caddy, the easiest way is to configure Caddy to run as user debian. Edit /lib/systemd/system/caddy.service and change the User and Group:

User=debian
Group=debian
ini

Then, we need to create a directory /run/debian for storing the socket files.

sudo mkdir /run/debian
sudo chown debian:debian /run/debian
bash

However, the /run directory is cleared after restart, we need to automate the creation of /run/debian by putting the following content into /etc/tmpfiles.d/debian-run.conf:

d /run/debian 0755 debian debian
text

And the Caddyfile looks like this:

:8888

reverse_proxy /jlab/* unix//run/debian/jlab.sock
reverse_proxy /notebook/* unix//run/debian/notebook.sock
caddy

Configuring Supervisor #

After installing Supervisor

apt install supervisor
bash

We store the configs in /etc/supervisor/conf.d/jupyterlab.conf:

[program:jupyterlab]
command=/home/debian/.cargo/bin/uv run jupyter-lab --no-browser --sock=/run/debian/jlab.sock --IdentityProvider.token='...' --ServerApp.base_url='/jlab' --ServerApp.allow_remote_access=True
directory=/home/debian/jupyterlab
user=debian
stopasgroup=true
autostart=true
autorestart=true
stderr_logfile=/var/log/jupyterlab/jupyterlab.err.log

[program:notebook]
...
text

Explanation:

After editing the config file, we need to create the log directory:

sudo mkdir -p /var/log/jupyterlab
sudo chown debian:debian /var/log/jupyterlab
bash

Then we run the following command to reload:

sudo supervisorctl reread
sudo supervisorctl update
bash
Leave your comments and reactions on GitHub