JupyterLab Extension Manager on JupyterHub for individual users

I am using JupyterHub 1.1.0 on Ubuntu 18.04 LTS installed in /opt/jupyterhub. The JupyterHub is started as a root service. I use JupyterLab 2.1.2 as my default interface. However, when I log in to JupyterLab as a single user, I cannot install extensions. When I try to install an extension, I get this error:

Error communicating with server extension. Consult the documentation for how to ensure that it is enabled.

Reason given:

Error: 500 (Internal Server Error)

I have run JupyterLab standalone from the terminal with the debug flag and I can see it is a permissions issue. If I run JupyerLab with “sudo” I can install extensions. The same is true if I install from the terminal with “sudo”. Is there any way to create this behavior when starting an instance through the JupyterHub spawner? Ideally, I’d like for other users to be able to install extensions as well.

Are there any restrictions you wish? Because some extensions are just installed through pip or conda - and pip allows to install arbitrary code. That means if anybody can install extensions though that methods, they can tamper with the system. I don’t know whether this is relevant for your use case.

Can you share the exact commands you used to install the extensions?

There are only a few of us using the server. I think I’ll be the only one using JupyterLab extensions.
Here’s an example for a theme I just installed.

sudo /opt/jupyterhub/bin/jupyter labextension install @oriolmirosa/jupyterlab_materialdarker

I can also achieve this through the extension manager if I first start JupyterLab like this.

sudo /opt/jupyterhub/bin/jupyter lab --allow-root

I’d like to be able to install extensions from my user/admin account with a JupyterLab session spawned by JupyterHub. Is it possible to restrict install permissions to a user or group?

From my understanding of the documentation this is not possible if all users should share one existing jupyterlab instance. In that case, each user can activate or deactivate installed extensions independently. So would that also serve your purpose? You can install all labextensions for yourself and just tell the others not to activate them? Otherwise maybe (!) a conda environment specific jupyterlab extension for each user could work? Somebody would need to confirm this.

I am pretty sure that spawners like dockerspawner which have a higher degree of isolation would suit your requirements because there each user works on their own jupyterlab installation which they can modify as they wish.

I’ve been playing with DockerSpawner all day and haven’t succeeded in implementing it. Initially, I was hoping to have something similar to RStudio Server, but for Python. I suspect if I were able to get the DockerSpawner functional, it would be similar. It looks like there’s talk of developing a proper guide here - https://github.com/jupyterhub/jupyterhub/issues/3007. I might hold off on trying to sort through the DockerSpawner option until there are more coherent instructions.

For now though, my priority is to have JupyterLab spawned for me via JupyterHub and to be able to add extensions freely through my interface. Is there a way to make it so my user can add extensions via the Extension Manager? Or do I just need to issue “sudo” labextension installs from the terminal? Thanks for your help!

I am not sure what you struggle with when working with DockerSpawner. I have one (oldish) example configuration at this repository.

For the second paragraph, I can’t tell you. Either somebody else has an idea or you need to dig deeper into the documentation about whether and how each user can have their personal (conda) environment with their personal jupyterlab installation on the JupyterHub I guess.

Your repository was very helpful! I was able to successfully spawn notebooks using DockerSpawner. I still have some work to do to understand how to implement this using my own Dockerfile. Right now, I’m just using the docker stacks found here. The important thing is that it works, though! Thanks for the help.

I am happy that I could help you about this. Good luck with adjusting the configuration to your needs!

1 Like

Hello again! Is it possible to make installed extensions in JupyterLab persist when using DockerSpawner? Each time the server is restarted, the user must reinstall any packages or extensions.

Well, you must be careful about what you exactly want to persist because of update issues. Of course you can persist more and more files in docker volumes, shared drives etc. and disable that they are deleted. But then if you want to update the old user environments on your server, you run into issues as described in Run a specific script .

Other way round: Why are you frequently restarting the server?

Third option: If it is a small JupyterHub, maybe you could maintain individual docker containers for each user? You can create if-else-branches in your configuration like in How to enable user specific kernels like PY2, PY3 and R in Jupyterhub

I run a server for my research group of about 5 people. All of us use some combination of R and Python. I’d like for the system users to all have access to the JupyterHub similar to the way current users interact with RStudio. I’d like to them to be able to set up their environment in a way that works for them. Setting up individual docker containers might be the way to go.

Alternatively, I could just configure my Dockerfile to install the Jupyter labextensions that I think would be most useful. If a user requests a new extension, I can add it to the Dockerfile. From what I can tell, this would load all the extensions and the user can choose to use them or not. Is there a better solution for what I’m trying to implement?

To me that sounds solid but I haven’t takne care for that many different installations

1 Like

I have a similar situation as yours and what I did was to create a docker image that contains a proxy server so that I can manage multiple users. See github joequant/bitquant under bitstation.

I’ve run into the problem with installing extensions and although I haven’t implemented the fix, the solution seems to be to designate some users as administrative users with the ability to reconfigure the environment.

Also for DockerSpawner. Docker by default will reset the environment, but you can look at saving old environments in a docker volume. If you look at my github, and the docker-compose.yml it has a list of volumes which I’m saving, and these will get saved between instances of docker. Also the nice thing about volumes is that they can be shared between different docker images.

One reason I didn’t go the DockerSpawner route is that I’m trying to integrate jupyterlab with other application like dokuwiki and nextcloud so i have the model of multiple kernels within one monster docker image.

Since the link got some attention, I have added an English readme part with slight improvements.