JupyterHub 2.0 beta

We have just published JupyterHub 2.0.0b1. This is a release with a small number of big features, developed over the last year:

Key features:

  • Roles and Scopes let deployments grant exactly the permissions needed to users and groups, rather than having only ‘regular’ users and admins.
  • API pagination allows better scaling of JupyterHub activities such as the idle culler when there are lots of users, by limiting the number of users returned for each request
  • a new react-based admin page, with nice pagination, group creation, etc.
  • JupyterLab is the default UI for single-user servers if available
  • null authenticator is bundled by default for API-only deployments

Because of the RBAC changes, this is probably our biggest release yet. Servers started before upgrading will not be available after the upgrade, so it’s best to shutdown all servers prior to upgrading. Also, because of the big possibly disruptive database upgrade, I’d ask folks to not test the beta in production just yet. If you have staging/preview deployments, we’d love to hear from you.

In particular, it would be hugely helpful to get feedback on the roles and scopes before we make a final release:

  • Does the documentation have the information you need?
  • Are you able to eliminate ‘admin’ users and services in favor of more specific roles and scopes?

I’d especially like to thank @0mar and @IvanaH8 for tons of work developing the roles and scopes changes.


This seems to be very helpful and I am looking forward to gaining more granular control over permissions.

Something that I am not quite sure about is, will it be possible to use RBAC to restrict access to certain container profiles by these roles? E.g. that a researcher role has access to a container profile with a GPU resource, but a student role does not. If this would be possible, I think it would be very helpful if the use case example page would include an example configuration for this.

1 Like

Yes, in that the profile list on a Spawner instance can be derived from properties of the user (be they scopes, groups, etc.). Profiles aren’t a notion JupyterHub itself has, rather it’s a list produced on a Spawner that can take any information available into account.

I’ll look into adding such an example.

1 Like

Update: 2.0 beta 2 is now out, with more detailed delete: scopes for users and servers (useful in cull-idle services), JupyterLab by default, and the null authenticator is now bundled with JupyterHub instead of sold separately.

Thanks everyone for testing and feedback so far! Keep it coming :heart:

1 Like

Update: 2.0 beta 3 is now out.

The following entry has been added to the changelog.

- Requests to a not-running server (e.g. visiting `/user/someuser/`)
  will return an HTTP 424 error instead of 503,
  making it easier to monitor for real deployment problems.
  JupyterLab in the user environment should be at least version 3.1.16
  to recognize this error code as a stopped server.
  You can temporarily opt-in to the older behavior (e.g. if older JupyterLab is required)
  by setting `c.JupyterHub.use_legacy_stopped_server_status_code = True`.

Thanks everyone for all help testing and providing feedback!!! :heart:


We now have our first release candidate of 2.0. If you’ve already started testing scopes, the 'all' scope has been renamed to 'inherit' based on feedback, because it indicates a token should inherit the permissions of its owner. You can see the latest changes since 2.0.0b3.

Feel free to leave ports of any successful tests here (e.g. some info about Spawner/Authenticator configurations, any use of scopes or roles), and open Issues on GitHub if you encounter problems.


Successful test: jupyterhub 2.0.0rc2 + batchspawner 1.1.0

I was able to spawn a notebook job on a Slurm cluster with batchspawner using JupyterHub 2.0.0rc2.


I’m testing rc3 out with dockerspawner 12.1. The upgrade went smoothly and the new admin panel is nice. At the same time I observe unexpected behavior: the users are redirected to /tree, even though the config has c.DockerSpawner.default_url = "lab" (according to the dockerspawner docs this should make lab the default).

I have confirmed that lab is running and accessible at /lab, and it was the default interface with the same config previously.

Any idea what could be off?

What version of jupyterhub is installed inside your singleuser Docker image?

Ahh! :man_facepalming: that must be it.

Edit: I confirm, this was most definitely it. Upgrading the hub inside the image to 2.0.0rc3 fixed the problem.

1 Like

After some rounds of betas and release candidates, feedback has slowed down and we haven’t seen any major problems. I think that means we are ready to make 2.0 final this week.