Redirect user to its running server

Hey everyone,

I’m trying to build a nice lab for a course I’m going to lecture on.
What I’m trying to do, is to use binderhub to create jupyterlab servers for the students. Each one of them would use the binderhub shareable URL, and each one would get his lab.

The course is going to take several days, and becasue of that I’m looking for a way for the students to login to their labs. Of course, if they would access the sharable url of binderhub, it would fail because they already have a running lab. Moreover, even if they would save their lab’s url, it would ask them for a token they don’t have.

Any ideas?

Providing the config.yaml for the helm:

config:
  BinderHub:
    use_registry: true
    image_prefix: "<my_registry>/course"
    hub_url: "http://<hub_url>/"
    auth_enabled: true
  DockerRegistry:
    url: "http://<my_registry>/"
jupyterhub:
  custom:
    binderauth_enabled: true
  hub:
    redirectToServer: false
    extraConfig:
      10-binder-custom: |
        import requests
        import json
        class MyCustomBinderSpawner(BinderSpawner):
          def pre_spawn_hook(self, spawner):
            <Some_Stuff_for_init_the_lab>
          def post_stop_hook(self, spawner):
            <Delete_the_stuff>
          def get_env(self):
            <providing_data_they_need>
        c.JupyterHub.spawner_class = MyCustomBinderSpawner
    config:
      Authenticator:
        enable_auth_state: true
        admin_users:
          - user1
          - user2
        allowed_users:
          - user3
      DummyAuthenticator:
        password: HomerSimpsonIsTheBest
      JupyterHub:
        authenticator_class: dummy
      BinderSpawner:
        auth_enabled: false
    services:
      binder:
        oauth_redirect_uri: "http://<binderhub_url>/oauth_callback"
        oauth_client_id: "binder-oauth-client-test"
  singleuser:
    extraEnv:
      JUPYTERHUB_SINGLEUSER_APP: "jupyter_server.serverapp.ServerApp"

Is everyone using the same environment? If so it might be easier to build one environment and use Z2JH without BinderHub.

Hey @manics , Thanks for your response!!

Umm… I want every course to get the same lab(But each user gets its own instance, of course), and I have multiple classes, and each class would get another lab(For example - Basic Python for one class, advanced python for another class, etc).

BTW, when you said Z2JH, you mean Zero To JupyterHub? I am new to all this subject…

A BinderHub is a special kind of JupyterHub that builds software environments on the fly. A JupyterHub is a way to provide access to compute resources to a group of people where JupyterLab or Jupyter Notebook is a good interface, and usually distributes the same environment (though multiple options can be provided). On JupyterHub, each user gets their own instance and their own persistent storage (BinderHubs do not have persistence by default). In our experience, most folk hosting classes go with the JupyterHub option, rather than the BinderHub option.

  • Zero to JupyterHub (z2jh) is a distribution of JupyterHub designed to run on Kubernetes and allows for scaling to the current level of traffic (students logging in) https://z2jh.jupyter.org
  • The Littlest JupyterHub (tljh) is another distribution of JupyterHub designed to run on a single server and can host up to 100 users https://tljh.jupyter.org

So when you say ‘lab’, are you referring to software environment?

1 Like

Hey @sgibson91 , Thanks about your reply!

  1. About using BinderHub - I want a nice interface to build new environments for each class I am going to make. For example - If I’m getting a class about basic python - I want to build a Git repo for the notebooks , and using binder to build for them environment. Similar, If I would get a class for advanced python - building a Git repo for it, and using BinderHub to build them environment. I want to be able to add classes without deploying anything.

  2. About persistent storage - I am creating S3 bucket for each user, and instructing them to use that for persistent storage. For that I am using the pre_start_hook of the spawner.

  3. The lab is just a JupyterLab instance with the notebooks for the students to do.

  4. Is there any way to reproduce BinderHub behaviour when it is spawns a new JupyterLab server? To authenticate against the URL that BinderHub is creating for the environment, and redirect the students to their JupyterLab without providing token?

I’m not sure what you mean by this. Doesn’t an authenticated BinderHub already do this?

Hey @manics ,
Well… It does not doing that for me. If I’m using the BinderHub env URL(What it provides for the Git repo), it fails telling the user already have a running instance.

Maybe named servers needs to be enabled so that the pod names don’t clash when trying to spawn a new pod alongside an already existing pod?

Hey, I’ve tried to enable it using the following configuration:

  hub:
    allowNamedServers: true
    namedServerLimitPerUser: 1

However, when I’m trying to access to the Lab’s URL provided by BinederHub, I’m getting the following error:

Found built image, launching...
Launching server...
Launch attempt 1 failed, retrying...
Launch attempt 2 failed, retrying...
Launch attempt 3 failed, retrying...
User user1 already has the maximum of 1 named servers.  One must be deleted before a new server can be created

Increase the limit per user. The thing that’s going wrong here is that the spawner is trying to create a new pod with the same name, and it can’t do that when one already exists.

This is why I was trying to recommend using a JupyterHub instead. You could still have Binder (technically repo2docker) build the environments for your class using the repo2docker-action GitHub - jupyterhub/repo2docker-action: A GitHub action to build data science environment images with repo2docker and push them to registries. and have the hub pull them in. Then you can use nbgitpuller to pull in your Notebooks GitHub - jupyterhub/nbgitpuller: Jupyter server extension to sync a git repository one-way to a local path Your students each get an individual lab and this issue of needing to authenticate to a running binder instance goes away. Binders are designed to be ephemeral whereas JupyterHub servers are not.

1 Like

Hey @sgibson91 , thanks again about your comment and help! :slight_smile:

  1. About increasing the namedServerLimitPerUser - If I would do that, then the student won’t be able to return to his own lab - he would get a fresh new one, and sometimes I would want them to work on the Lab for some time… That’s why I want them to be able tu return to their own labs.

  2. I would try to use repo2docker and JupyterHub, it would take some time to deploy though… Would update about the results

1 Like

Once you have your JupyterHub deployed, 2i2c has a lot of information about how to create environments using the repo2docker action and distributing content with nbgitpuller User environment and interface — Hub Service Guide

There’s even a template repository for setting up repo2docker-action hub-user-image-template/README.md at main · 2i2c-org/hub-user-image-template · GitHub

Ignore the docs referring to the “configurator”, that’s 2i2c-specific feature. You can instead use singleuser.image Configuration Reference — Zero to JupyterHub with Kubernetes documentation and singleuser.profileList Configuration Reference — Zero to JupyterHub with Kubernetes documentation to let your hub know which images it should use

1 Like