mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-17 15:03:02 +00:00
Merge branch 'main' into Improve-on-documentation-websecurity.md
This commit is contained in:
@@ -7,18 +7,18 @@ document describes how to do these upgrades.
|
||||
|
||||
If you are using :ref:`a JupyterHub distribution <index/distributions>`, you
|
||||
should consult the distribution's documentation on how to upgrade. This
|
||||
document is if you have set up your own JupyterHub without using a
|
||||
document is useful if you have set up your own JupyterHub without using a
|
||||
distribution.
|
||||
|
||||
It is long because is pretty detailed! Most likely, upgrading
|
||||
JupyterHub is painless, quick and with minimal user interruption.
|
||||
The steps are discussed in detail, so if you get stuck at any step you can always refer to this guide. Most likely,
|
||||
upgrading JupyterHub is painless, quick and with minimal user interruption.
|
||||
|
||||
Read the Changelog
|
||||
==================
|
||||
|
||||
The `changelog <../changelog.html>`_ contains information on what has
|
||||
changed with the new JupyterHub release, and any deprecation warnings.
|
||||
Read these notes to familiarize yourself with the coming changes. There
|
||||
The `changelog <../changelog.md>`_ contains information on what has
|
||||
changed with the new JupyterHub release and any deprecation warnings.
|
||||
Read these notes to familiarize yourself with the upcoming changes. There
|
||||
might be new releases of authenticators & spawners you are using, so
|
||||
read the changelogs for those too!
|
||||
|
||||
@@ -30,10 +30,10 @@ is managed by JupyterHub, your users will see service disruption during
|
||||
the upgrade process. You should notify them, and pick a time to do the
|
||||
upgrade where they will be least disrupted.
|
||||
|
||||
If you are using a different proxy, or running ``configurable-http-proxy``
|
||||
If you are using a different proxy or running ``configurable-http-proxy``
|
||||
independent of JupyterHub, your users will be able to continue using notebook
|
||||
servers they had already launched, but will not be able to launch new servers
|
||||
nor sign in.
|
||||
or sign in.
|
||||
|
||||
|
||||
Backup database & config
|
||||
@@ -41,37 +41,36 @@ Backup database & config
|
||||
|
||||
Before doing an upgrade, it is critical to back up:
|
||||
|
||||
#. Your JupyterHub database (sqlite by default, or MySQL / Postgres
|
||||
if you used those). If you are using sqlite (the default), you
|
||||
should backup the ``jupyterhub.sqlite`` file.
|
||||
#. Your JupyterHub database (SQLite by default, or MySQL / Postgres
|
||||
if you used those). If you are using SQLite (the default), you
|
||||
should back up the ``jupyterhub.sqlite`` file.
|
||||
#. Your ``jupyterhub_config.py`` file.
|
||||
#. Your user's home directories. This is unlikely to be affected directly by
|
||||
a JupyterHub upgrade, but we recommend a backup since user data is very
|
||||
critical.
|
||||
#. Your users' home directories. This is unlikely to be affected directly by
|
||||
a JupyterHub upgrade, but we recommend a backup since user data is critical.
|
||||
|
||||
|
||||
Shutdown JupyterHub
|
||||
===================
|
||||
Shut down JupyterHub
|
||||
====================
|
||||
|
||||
Shutdown the JupyterHub process. This would vary depending on how you
|
||||
Shut down the JupyterHub process. This would vary depending on how you
|
||||
have set up JupyterHub to run. Most likely, it is using a process
|
||||
supervisor of some sort (``systemd`` or ``supervisord`` or even ``docker``).
|
||||
Use the supervisor specific command to stop the JupyterHub process.
|
||||
Use the supervisor-specific command to stop the JupyterHub process.
|
||||
|
||||
Upgrade JupyterHub packages
|
||||
===========================
|
||||
|
||||
There are two environments where the ``jupyterhub`` package is installed:
|
||||
|
||||
#. The *hub environment*, which is where the JupyterHub server process
|
||||
#. The *hub environment*: where the JupyterHub server process
|
||||
runs. This is started with the ``jupyterhub`` command, and is what
|
||||
people generally think of as JupyterHub.
|
||||
|
||||
#. The *notebook user environments*. This is where the user notebook
|
||||
#. The *notebook user environments*: where the user notebook
|
||||
servers are launched from, and is probably custom to your own
|
||||
installation. This could be just one environment (different from the
|
||||
hub environment) that is shared by all users, one environment
|
||||
per user, or same environment as the hub environment. The hub
|
||||
per user, or the same environment as the hub environment. The hub
|
||||
launched the ``jupyterhub-singleuser`` command in this environment,
|
||||
which in turn starts the notebook server.
|
||||
|
||||
@@ -92,10 +91,8 @@ with:
|
||||
|
||||
conda install -c conda-forge jupyterhub==<version>
|
||||
|
||||
Where ``<version>`` is the version of JupyterHub you are upgrading to.
|
||||
|
||||
You should also check for new releases of the authenticator & spawner you
|
||||
are using. You might wish to upgrade those packages too along with JupyterHub,
|
||||
are using. You might wish to upgrade those packages, too, along with JupyterHub
|
||||
or upgrade them separately.
|
||||
|
||||
Upgrade JupyterHub database
|
||||
@@ -109,7 +106,7 @@ database. From the hub environment, in the same directory as your
|
||||
|
||||
jupyterhub upgrade-db
|
||||
|
||||
This should find the location of your database, and run necessary upgrades
|
||||
This should find the location of your database, and run the necessary upgrades
|
||||
for it.
|
||||
|
||||
SQLite database disadvantages
|
||||
@@ -118,11 +115,11 @@ SQLite database disadvantages
|
||||
SQLite has some disadvantages when it comes to upgrading JupyterHub. These
|
||||
are:
|
||||
|
||||
- ``upgrade-db`` may not work, and you may need delete your database
|
||||
- ``upgrade-db`` may not work, and you may need to delete your database
|
||||
and start with a fresh one.
|
||||
- ``downgrade-db`` **will not** work if you want to rollback to an
|
||||
earlier version, so backup the ``jupyterhub.sqlite`` file before
|
||||
upgrading
|
||||
upgrading.
|
||||
|
||||
What happens if I delete my database?
|
||||
-------------------------------------
|
||||
@@ -137,10 +134,10 @@ resides only in the Hub database includes:
|
||||
If the following conditions are true, you should be fine clearing the
|
||||
Hub database and starting over:
|
||||
|
||||
- users specified in config file, or login using an external
|
||||
- users specified in the config file, or login using an external
|
||||
authentication provider (Google, GitHub, LDAP, etc)
|
||||
- user servers are stopped during upgrade
|
||||
- don't mind causing users to login again after upgrade
|
||||
- user servers are stopped during the upgrade
|
||||
- don't mind causing users to log in again after the upgrade
|
||||
|
||||
Start JupyterHub
|
||||
================
|
||||
@@ -148,7 +145,7 @@ Start JupyterHub
|
||||
Once the database upgrade is completed, start the ``jupyterhub``
|
||||
process again.
|
||||
|
||||
#. Log-in and start the server to make sure things work as
|
||||
#. Log in and start the server to make sure things work as
|
||||
expected.
|
||||
#. Check the logs for any errors or deprecation warnings. You
|
||||
might have to update your ``jupyterhub_config.py`` file to
|
||||
|
@@ -1,5 +1,5 @@
|
||||
Eventlogging and Telemetry
|
||||
==========================
|
||||
Event logging and Telemetry
|
||||
===========================
|
||||
|
||||
JupyterHub can be configured to record structured events from a running server using Jupyter's `Telemetry System`_. The types of events that JupyterHub emits are defined by `JSON schemas`_ listed at the bottom of this page_.
|
||||
|
||||
@@ -15,8 +15,8 @@ Event logging is handled by its ``Eventlog`` object. This leverages Python's sta
|
||||
|
||||
To begin recording events, you'll need to set two configurations:
|
||||
|
||||
1. ``handlers``: tells the EventLog *where* to route your events. This trait is a list of Python logging handlers that route events to
|
||||
2. ``allows_schemas``: tells the EventLog *which* events should be recorded. No events are emitted by default; all recorded events must be listed here.
|
||||
1. ``handlers``: tells the EventLog *where* to route your events; this trait is a list of Python logging handlers that route events to the destination
|
||||
2. ``allows_schemas``: tells the EventLog *which* events should be recorded; no events are emitted by default; all recorded events must be listed here
|
||||
|
||||
Here's a basic example:
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Configuration Basics
|
||||
|
||||
The section contains basic information about configuring settings for a JupyterHub
|
||||
This section contains basic information about configuring settings for a JupyterHub
|
||||
deployment. The [Technical Reference](../reference/index)
|
||||
documentation provides additional details.
|
||||
|
||||
@@ -49,7 +49,7 @@ that Jupyter uses.
|
||||
|
||||
## Configure using command line options
|
||||
|
||||
To display all command line options that are available for configuration:
|
||||
To display all command line options that are available for configuration run the following command:
|
||||
|
||||
```bash
|
||||
jupyterhub --help-all
|
||||
@@ -81,7 +81,7 @@ specific [authenticators](./authenticators-users-basics) and
|
||||
[spawners](./spawners-basics) can be set in the configuration file.
|
||||
This enables JupyterHub to be used with a variety of authentication methods or
|
||||
process control and deployment environments. [Some examples](../reference/config-examples),
|
||||
meant as illustration, are:
|
||||
meant as illustrations, are:
|
||||
|
||||
- Using GitHub OAuth instead of PAM with [OAuthenticator](https://github.com/jupyterhub/oauthenticator)
|
||||
- Spawning single-user servers with Docker, using the [DockerSpawner](https://github.com/jupyterhub/dockerspawner)
|
||||
|
@@ -24,7 +24,7 @@ Hub via the REST API.
|
||||
|
||||
## API Token basics
|
||||
|
||||
### Create an API token
|
||||
### Step 1: Generate an API token
|
||||
|
||||
To run such an external service, an API token must be created and
|
||||
provided to the service.
|
||||
@@ -43,12 +43,12 @@ generating an API token is available from the JupyterHub user interface:
|
||||
|
||||

|
||||
|
||||
### Pass environment variable with token to the Hub
|
||||
### Step 2: Pass environment variable with token to the Hub
|
||||
|
||||
In the case of `cull_idle_servers`, it is passed as the environment
|
||||
variable called `JUPYTERHUB_API_TOKEN`.
|
||||
|
||||
### Use API tokens for services and tasks that require external access
|
||||
### Step 3: Use API tokens for services and tasks that require external access
|
||||
|
||||
While API tokens are often associated with a specific user, API tokens
|
||||
can be used by services that require external access for activities
|
||||
@@ -62,7 +62,7 @@ c.JupyterHub.services = [
|
||||
]
|
||||
```
|
||||
|
||||
### Restart JupyterHub
|
||||
### Step 4: Restart JupyterHub
|
||||
|
||||
Upon restarting JupyterHub, you should see a message like below in the
|
||||
logs:
|
||||
@@ -78,16 +78,15 @@ single-user servers, and only cookies can be used for authentication.
|
||||
0.8 supports using JupyterHub API tokens to authenticate to single-user
|
||||
servers.
|
||||
|
||||
## Configure the idle culler to run as a Hub-Managed Service
|
||||
## How to configure the idle culler to run as a Hub-Managed Service
|
||||
|
||||
Install the idle culler:
|
||||
### Step 1: Install the idle culler:
|
||||
|
||||
```
|
||||
pip install jupyterhub-idle-culler
|
||||
```
|
||||
|
||||
In `jupyterhub_config.py`, add the following dictionary for the
|
||||
`idle-culler` Service to the `c.JupyterHub.services` list:
|
||||
### Step 2: In `jupyterhub_config.py`, add the following dictionary for the `idle-culler` Service to the `c.JupyterHub.services` list:
|
||||
|
||||
```python
|
||||
c.JupyterHub.services = [
|
||||
@@ -127,7 +126,7 @@ It now needs the scopes:
|
||||
- `admin:servers` to start/stop servers
|
||||
```
|
||||
|
||||
## Run `cull-idle` manually as a standalone script
|
||||
## How to run `cull-idle` manually as a standalone script
|
||||
|
||||
Now you can run your script by providing it
|
||||
the API token and it will authenticate through the REST API to
|
||||
|
@@ -1,12 +1,12 @@
|
||||
# Spawners and single-user notebook servers
|
||||
|
||||
Since the single-user server is an instance of `jupyter notebook`, an entire separate
|
||||
multi-process application, there are many aspects of that server that can be configured, and a lot
|
||||
A Spawner starts each single-user notebook server. Since the single-user server is an instance of `jupyter notebook`, an entire separate
|
||||
multi-process application, many aspects of that server can be configured and there are a lot
|
||||
of ways to express that configuration.
|
||||
|
||||
At the JupyterHub level, you can set some values on the Spawner. The simplest of these is
|
||||
`Spawner.notebook_dir`, which lets you set the root directory for a user's server. This root
|
||||
notebook directory is the highest level directory users will be able to access in the notebook
|
||||
notebook directory is the highest-level directory users will be able to access in the notebook
|
||||
dashboard. In this example, the root notebook directory is set to `~/notebooks`, where `~` is
|
||||
expanded to the user's home directory.
|
||||
|
||||
@@ -20,7 +20,7 @@ You can also specify extra command line arguments to the notebook server with:
|
||||
c.Spawner.args = ['--debug', '--profile=PHYS131']
|
||||
```
|
||||
|
||||
This could be used to set the users default page for the single user server:
|
||||
This could be used to set the user's default page for the single-user server:
|
||||
|
||||
```python
|
||||
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
|
||||
|
@@ -14,7 +14,7 @@ satisfy the following:
|
||||
- After testing, the server in question should be able to score at least an A on the
|
||||
Qualys SSL Labs [SSL Server Test](https://www.ssllabs.com/ssltest/)
|
||||
|
||||
Let's start out with needed JupyterHub configuration in `jupyterhub_config.py`:
|
||||
Let's start out with the needed JupyterHub configuration in `jupyterhub_config.py`:
|
||||
|
||||
```python
|
||||
# Force the proxy to only listen to connections to 127.0.0.1 (on port 8000)
|
||||
@@ -30,15 +30,15 @@ This can take a few minutes:
|
||||
openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
|
||||
```
|
||||
|
||||
## nginx
|
||||
## Nginx
|
||||
|
||||
This **`nginx` config file** is fairly standard fare except for the two
|
||||
`location` blocks within the main section for HUB.DOMAIN.tld.
|
||||
To create a new site for jupyterhub in your nginx config, make a new file
|
||||
To create a new site for jupyterhub in your Nginx config, make a new file
|
||||
in `sites.enabled`, e.g. `/etc/nginx/sites.enabled/jupyterhub.conf`:
|
||||
|
||||
```bash
|
||||
# top-level http config for websocket headers
|
||||
# Top-level HTTP config for WebSocket headers
|
||||
# If Upgrade is defined, Connection = upgrade
|
||||
# If Upgrade is empty, Connection = close
|
||||
map $http_upgrade $connection_upgrade {
|
||||
@@ -51,7 +51,7 @@ server {
|
||||
listen 80;
|
||||
server_name HUB.DOMAIN.TLD;
|
||||
|
||||
# Tell all requests to port 80 to be 302 redirected to HTTPS
|
||||
# Redirect the request to HTTPS
|
||||
return 302 https://$host$request_uri;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ server {
|
||||
ssl_stapling_verify on;
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
|
||||
# Managing literal requests to the JupyterHub front end
|
||||
# Managing literal requests to the JupyterHub frontend
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
@@ -101,10 +101,10 @@ server {
|
||||
If `nginx` is not running on port 443, substitute `$http_host` for `$host` on
|
||||
the lines setting the `Host` header.
|
||||
|
||||
`nginx` will now be the front facing element of JupyterHub on `443` which means
|
||||
`nginx` will now be the front-facing element of JupyterHub on `443` which means
|
||||
it is also free to bind other servers, like `NO_HUB.DOMAIN.TLD` to the same port
|
||||
on the same machine and network interface. In fact, one can simply use the same
|
||||
server blocks as above for `NO_HUB` and simply add line for the root directory
|
||||
server blocks as above for `NO_HUB` and simply add a line for the root directory
|
||||
of the site as well as the applicable location call:
|
||||
|
||||
```bash
|
||||
@@ -112,7 +112,7 @@ server {
|
||||
listen 80;
|
||||
server_name NO_HUB.DOMAIN.TLD;
|
||||
|
||||
# Tell all requests to port 80 to be 302 redirected to HTTPS
|
||||
# Redirect the request to HTTPS
|
||||
return 302 https://$host$request_uri;
|
||||
}
|
||||
|
||||
@@ -143,12 +143,12 @@ Now restart `nginx`, restart the JupyterHub, and enjoy accessing
|
||||
`https://HUB.DOMAIN.TLD` while serving other content securely on
|
||||
`https://NO_HUB.DOMAIN.TLD`.
|
||||
|
||||
### SELinux permissions for nginx
|
||||
### SELinux permissions for Nginx
|
||||
|
||||
On distributions with SELinux enabled (e.g. Fedora), one may encounter permission errors
|
||||
when the nginx service is started.
|
||||
when the Nginx service is started.
|
||||
|
||||
We need to allow nginx to perform network relay and connect to the jupyterhub port. The
|
||||
We need to allow Nginx to perform network relay and connect to the JupyterHub port. The
|
||||
following commands do that:
|
||||
|
||||
```bash
|
||||
@@ -157,26 +157,26 @@ setsebool -P httpd_can_network_relay 1
|
||||
setsebool -P httpd_can_network_connect 1
|
||||
```
|
||||
|
||||
Replace 8000 with the port the jupyterhub server is running from.
|
||||
Replace 8000 with the port the JupyterHub server is running from.
|
||||
|
||||
## Apache
|
||||
|
||||
As with nginx above, you can use [Apache](https://httpd.apache.org) as the reverse proxy.
|
||||
First, we will need to enable the apache modules that we are going to need:
|
||||
As with Nginx above, you can use [Apache](https://httpd.apache.org) as the reverse proxy.
|
||||
First, we will need to enable the Apache modules that we are going to need:
|
||||
|
||||
```bash
|
||||
a2enmod ssl rewrite proxy headers proxy_http proxy_wstunnel
|
||||
```
|
||||
|
||||
Our Apache configuration is equivalent to the nginx configuration above:
|
||||
Our Apache configuration is equivalent to the Nginx configuration above:
|
||||
|
||||
- Redirect HTTP to HTTPS
|
||||
- Good SSL Configuration
|
||||
- Support for websockets on any proxied URL
|
||||
- Support for WebSocket on any proxied URL
|
||||
- JupyterHub is running locally at http://127.0.0.1:8000
|
||||
|
||||
```bash
|
||||
# redirect HTTP to HTTPS
|
||||
# Redirect HTTP to HTTPS
|
||||
Listen 80
|
||||
<VirtualHost HUB.DOMAIN.TLD:80>
|
||||
ServerName HUB.DOMAIN.TLD
|
||||
@@ -188,26 +188,26 @@ Listen 443
|
||||
|
||||
ServerName HUB.DOMAIN.TLD
|
||||
|
||||
# enable HTTP/2, if available
|
||||
# Enable HTTP/2, if available
|
||||
Protocols h2 http/1.1
|
||||
|
||||
# HTTP Strict Transport Security (mod_headers is required) (63072000 seconds)
|
||||
Header always set Strict-Transport-Security "max-age=63072000"
|
||||
|
||||
# configure SSL
|
||||
# Configure SSL
|
||||
SSLEngine on
|
||||
SSLCertificateFile /etc/letsencrypt/live/HUB.DOMAIN.TLD/fullchain.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/HUB.DOMAIN.TLD/privkey.pem
|
||||
SSLOpenSSLConfCmd DHParameters /etc/ssl/certs/dhparam.pem
|
||||
|
||||
# intermediate configuration from ssl-config.mozilla.org (2022-03-03)
|
||||
# Please note, that this configuration might be out-dated - please update it accordingly using https://ssl-config.mozilla.org/
|
||||
# Intermediate configuration from SSL-config.mozilla.org (2022-03-03)
|
||||
# Please note, that this configuration might be outdated - please update it accordingly using https://ssl-config.mozilla.org/
|
||||
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
|
||||
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
SSLHonorCipherOrder off
|
||||
SSLSessionTickets off
|
||||
|
||||
# Use RewriteEngine to handle websocket connection upgrades
|
||||
# Use RewriteEngine to handle WebSocket connection upgrades
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTP:Connection} Upgrade [NC]
|
||||
RewriteCond %{HTTP:Upgrade} websocket [NC]
|
||||
@@ -224,7 +224,7 @@ Listen 443
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
In case of the need to run the jupyterhub under /jhub/ or other location please use the below configurations:
|
||||
In case of the need to run JupyterHub under /jhub/ or another location please use the below configurations:
|
||||
|
||||
- JupyterHub running locally at http://127.0.0.1:8000/jhub/ or other location
|
||||
|
||||
@@ -241,7 +241,7 @@ httpd.conf amendments:
|
||||
jupyterhub_config.py amendments:
|
||||
|
||||
```bash
|
||||
--The public facing URL of the whole JupyterHub application.
|
||||
--This is the address on which the proxy will bind. Sets protocol, ip, base_url
|
||||
--The public-facing URL of the whole JupyterHub application.
|
||||
--This is the address on which the proxy will bind. Sets protocol, IP, base_url
|
||||
c.JupyterHub.bind_url = 'http://127.0.0.1:8000/jhub/'
|
||||
```
|
||||
|
@@ -1,8 +1,8 @@
|
||||
# Configuring user environments
|
||||
|
||||
Deploying JupyterHub means you are providing Jupyter notebook environments for
|
||||
To deploy JupyterHub means you are providing Jupyter notebook environments for
|
||||
multiple users. Often, this includes a desire to configure the user
|
||||
environment in some way.
|
||||
environment in a custom way.
|
||||
|
||||
Since the `jupyterhub-singleuser` server extends the standard Jupyter notebook
|
||||
server, most configuration and documentation that applies to Jupyter Notebook
|
||||
@@ -10,12 +10,9 @@ applies to the single-user environments. Configuration of user environments
|
||||
typically does not occur through JupyterHub itself, but rather through the system-wide
|
||||
configuration of Jupyter, which is inherited by `jupyterhub-singleuser`.
|
||||
|
||||
**Tip:** When searching for configuration tips for JupyterHub user
|
||||
environments, try removing JupyterHub from your search because there are a lot
|
||||
more people out there configuring Jupyter than JupyterHub and the
|
||||
configuration is the same.
|
||||
**Tip:** When searching for configuration tips for JupyterHub user environments, you might want to remove JupyterHub from your search because there are a lot more people out there configuring Jupyter than JupyterHub and the configuration is the same.
|
||||
|
||||
This section will focus on user environments, including:
|
||||
This section will focus on user environments, which includes the following:
|
||||
|
||||
- [Installing packages](#installing-packages)
|
||||
- [Configuring Jupyter and IPython](#configuring-jupyter-and-ipython)
|
||||
@@ -24,26 +21,23 @@ This section will focus on user environments, including:
|
||||
|
||||
## Installing packages
|
||||
|
||||
To make packages available to users, you generally will install packages
|
||||
system-wide or in a shared environment.
|
||||
To make packages available to users, you will typically install packages system-wide or in a shared environment.
|
||||
|
||||
This installation location should always be in the same environment that
|
||||
This installation location should always be in the same environment where
|
||||
`jupyterhub-singleuser` itself is installed in, and must be _readable and
|
||||
executable_ by your users. If you want users to be able to install additional
|
||||
executable_ by your users. If you want your users to be able to install additional
|
||||
packages, the installation location must also be _writable_ by your users.
|
||||
|
||||
If you are using a standard system Python install, you would use:
|
||||
If you are using a standard Python installation on your system, use the following command:
|
||||
|
||||
```bash
|
||||
sudo python3 -m pip install numpy
|
||||
```
|
||||
|
||||
to install the numpy package in the default system Python 3 environment
|
||||
to install the numpy package in the default Python 3 environment on your system
|
||||
(typically `/usr/local`).
|
||||
|
||||
You may also use conda to install packages. If you do, you should make sure
|
||||
that the conda environment has appropriate permissions for users to be able to
|
||||
run Python code in the env.
|
||||
Alternatively, You may also use conda to install packages. To do this, ensure that the conda environment has appropriate users permissions needed to run Python code in the environment.
|
||||
|
||||
## Configuring Jupyter and IPython
|
||||
|
||||
@@ -51,15 +45,9 @@ run Python code in the env.
|
||||
and [IPython](https://ipython.readthedocs.io/en/stable/development/config.html)
|
||||
have their own configuration systems.
|
||||
|
||||
As a JupyterHub administrator, you will typically want to install and configure
|
||||
environments for all JupyterHub users. For example, you wish for each student in
|
||||
a class to have the same user environment configuration.
|
||||
|
||||
Jupyter and IPython support **"system-wide"** locations for configuration, which
|
||||
is the logical place to put global configuration that you want to affect all
|
||||
users. It's generally more efficient to configure user environments "system-wide",
|
||||
and it's a good idea to avoid creating files in users' home directories.
|
||||
As a JupyterHub administrator, you will typically want to install and configure environments for all JupyterHub users. For example, let's say you wish for each student in a class to have the same user environment configuration.
|
||||
|
||||
Jupyter and IPython support **"system-wide"** locations for configuration, which is the logical place to put global configuration that you want to affect all users. It's generally more efficient to configure user environments "system-wide", and it's a good practice to avoid creating files in the users' home directories.
|
||||
The typical locations for these config files are:
|
||||
|
||||
- **system-wide** in `/etc/{jupyter|ipython}`
|
||||
@@ -67,8 +55,7 @@ The typical locations for these config files are:
|
||||
|
||||
### Example: Enable an extension system-wide
|
||||
|
||||
For example, to enable the `cython` IPython extension for all of your users,
|
||||
create the file `/etc/ipython/ipython_config.py`:
|
||||
For example, to enable the `cython` IPython extension for all of your users, create the file `/etc/ipython/ipython_config.py`:
|
||||
|
||||
```python
|
||||
c.InteractiveShellApp.extensions.append("cython")
|
||||
@@ -77,21 +64,18 @@ c.InteractiveShellApp.extensions.append("cython")
|
||||
### Example: Enable a Jupyter notebook configuration setting for all users
|
||||
|
||||
:::{note}
|
||||
These examples configure the Jupyter ServerApp,
|
||||
which is used by JupyterLab, the default in JupyterHub 2.0.
|
||||
These examples configure the Jupyter ServerApp, which is used by JupyterLab, the default in JupyterHub 2.0.
|
||||
|
||||
If you are using the classing Jupyter Notebook server,
|
||||
the same things should work,
|
||||
with the following substitutions:
|
||||
|
||||
- Where you see `jupyter_server_config`, use `jupyter_notebook_config`
|
||||
- Where you see `NotebookApp`, use `ServerApp`
|
||||
- Search for `jupyter_server_config`, and replace with `jupyter_notebook_config`
|
||||
- Search for `NotebookApp`, and replace with `ServerApp`
|
||||
|
||||
:::
|
||||
|
||||
To enable Jupyter notebook's internal idle-shutdown behavior (requires
|
||||
notebook ≥ 5.4), set the following in the `/etc/jupyter/jupyter_server_config.py`
|
||||
file:
|
||||
To enable Jupyter notebook's internal idle-shutdown behavior (requires notebook ≥ 5.4), set the following in the `/etc/jupyter/jupyter_server_config.py` file:
|
||||
|
||||
```python
|
||||
# shutdown the server after no activity for an hour
|
||||
@@ -104,16 +88,14 @@ c.MappingKernelManager.cull_interval = 2 * 60
|
||||
|
||||
## Installing kernelspecs
|
||||
|
||||
You may have multiple Jupyter kernels installed and want to make sure that
|
||||
they are available to all of your users. This means installing kernelspecs
|
||||
either system-wide (e.g. in /usr/local/) or in the `sys.prefix` of JupyterHub
|
||||
You may have multiple Jupyter kernels installed and want to make sure that they are available to all of your users. This means installing kernelspecs either system-wide (e.g. in /usr/local/) or in the `sys.prefix` of JupyterHub
|
||||
itself.
|
||||
|
||||
Jupyter kernelspec installation is system-wide by default, but some kernels
|
||||
may default to installing kernelspecs in your home directory. These will need
|
||||
to be moved system-wide to ensure that they are accessible.
|
||||
|
||||
You can see where your kernelspecs are with:
|
||||
To see where your kernelspecs are, you can use the following command:
|
||||
|
||||
```bash
|
||||
jupyter kernelspec list
|
||||
@@ -121,8 +103,7 @@ jupyter kernelspec list
|
||||
|
||||
### Example: Installing kernels system-wide
|
||||
|
||||
Assuming I have a Python 2 and Python 3 environment that I want to make
|
||||
sure are available, I can install their specs system-wide (in /usr/local) with:
|
||||
Let's assume that I have a Python 2 and Python 3 environment that I want to make sure are available, I can install their specs **system-wide** (in /usr/local) using the following command:
|
||||
|
||||
```bash
|
||||
/path/to/python3 -m ipykernel install --prefix=/usr/local
|
||||
@@ -141,31 +122,25 @@ How you configure user environments for each category can differ a bit
|
||||
depending on what Spawner you are using.
|
||||
|
||||
The first category is a **shared system (multi-user host)** where
|
||||
each user has a JupyterHub account and a home directory as well as being
|
||||
each user has a JupyterHub account, a home directory as well as being
|
||||
a real system user. In this example, shared configuration and installation
|
||||
must be in a 'system-wide' location, such as `/etc/`, or `/usr/local`
|
||||
or a custom prefix such as `/opt/conda`.
|
||||
|
||||
When JupyterHub uses **container-based** Spawners (e.g. KubeSpawner or
|
||||
DockerSpawner), the 'system-wide' environment is really the container image
|
||||
that you are using for users.
|
||||
DockerSpawner), the 'system-wide' environment is really the container image used for users.
|
||||
|
||||
In both cases, you want to _avoid putting configuration in user home
|
||||
directories_ because users can change those configuration settings. Also,
|
||||
home directories typically persist once they are created, so they are
|
||||
difficult for admins to update later.
|
||||
directories_ because users can change those configuration settings. Also, home directories typically persist once they are created, thereby making it difficult for admins to update later.
|
||||
|
||||
## Named servers
|
||||
|
||||
By default, in a JupyterHub deployment, each user has exactly one server.
|
||||
By default, in a JupyterHub deployment, each user has one server only.
|
||||
|
||||
JupyterHub can, however, have multiple servers per user.
|
||||
This is most useful in deployments where users can configure the environment
|
||||
in which their server will start (e.g. resource requests on an HPC cluster),
|
||||
so that a given user can have multiple configurations running at the same time,
|
||||
without having to stop and restart their one server.
|
||||
This is mostly useful in deployments where users can configure the environment in which their server will start (e.g. resource requests on an HPC cluster), so that a given user can have multiple configurations running at the same time, without having to stop and restart their own server.
|
||||
|
||||
To allow named servers:
|
||||
To allow named servers, include this code snippet in your config file:
|
||||
|
||||
```python
|
||||
c.JupyterHub.allow_named_servers = True
|
||||
@@ -183,13 +158,13 @@ as well as the admin page:
|
||||
Named servers can be accessed, created, started, stopped, and deleted
|
||||
from these pages. Activity tracking is now per server as well.
|
||||
|
||||
The number of named servers per user can be limited by setting a constant value:
|
||||
To limit the number of **named server** per user by setting a constant value, include this code snippet in your config file:
|
||||
|
||||
```python
|
||||
c.JupyterHub.named_server_limit_per_user = 5
|
||||
```
|
||||
|
||||
or a callable/awaitable based on the handler object:
|
||||
Alternatively, to use a callable/awaitable based on the handler object, include this code snippet in your config file:
|
||||
|
||||
```python
|
||||
def named_server_limit_per_user_fn(handler):
|
||||
@@ -211,8 +186,9 @@ If `named_server_limit_per_user` is set to `0`, no limit is enforced.
|
||||
|
||||
By default, the single-user server launches JupyterLab,
|
||||
which is based on [Jupyter Server][].
|
||||
|
||||
This is the default server when running JupyterHub ≥ 2.0.
|
||||
You can switch to using the legacy Jupyter Notebook server by setting the `JUPYTERHUB_SINGLEUSER_APP` environment variable
|
||||
To switch to using the legacy Jupyter Notebook server, you can set the `JUPYTERHUB_SINGLEUSER_APP` environment variable
|
||||
(in the single-user environment) to:
|
||||
|
||||
```bash
|
||||
@@ -223,19 +199,20 @@ export JUPYTERHUB_SINGLEUSER_APP='notebook.notebookapp.NotebookApp'
|
||||
[jupyter notebook]: https://jupyter-notebook.readthedocs.io
|
||||
|
||||
:::{versionchanged} 2.0
|
||||
|
||||
JupyterLab is now the default single-user UI, if available,
|
||||
which is based on the [Jupyter Server][],
|
||||
no longer the legacy [Jupyter Notebook][] server.
|
||||
JupyterHub prior to 2.0 launched the legacy notebook server (`jupyter notebook`),
|
||||
and the Jupyter server could be selected by specifying
|
||||
and the Jupyter server could be selected by specifying the following:
|
||||
|
||||
```python
|
||||
# jupyterhub_config.py
|
||||
c.Spawner.cmd = ["jupyter-labhub"]
|
||||
```
|
||||
|
||||
or for an otherwise customized Jupyter Server app,
|
||||
set the environment variable:
|
||||
Alternatively, for an otherwise customized Jupyter Server app,
|
||||
set the environment variable using the following command:
|
||||
|
||||
```bash
|
||||
export JUPYTERHUB_SINGLEUSER_APP='jupyter_server.serverapp.ServerApp'
|
||||
|
@@ -30,19 +30,19 @@ Some relevant points:
|
||||
Here are some key definitions to keep in mind when we are talking about OAuth.
|
||||
You can also read more detail [here](https://www.oauth.com/oauth2-servers/definitions/).
|
||||
|
||||
- **provider** the entity responsible for managing identity and authorization,
|
||||
- **provider**: The entity responsible for managing identity and authorization,
|
||||
always a web server.
|
||||
JupyterHub is _always_ an oauth provider for JupyterHub's components.
|
||||
When OAuthenticator is used, an external service, such as GitHub or KeyCloak, is also an oauth provider.
|
||||
- **client** An entity that requests OAuth **tokens** on a user's behalf,
|
||||
- **client**: An entity that requests OAuth **tokens** on a user's behalf,
|
||||
generally a web server of some kind.
|
||||
OAuth **clients** are services that _delegate_ authentication and/or authorization
|
||||
to an OAuth **provider**.
|
||||
JupyterHub _services_ or single-user _servers_ are OAuth **clients** of the JupyterHub **provider**.
|
||||
When OAuthenticator is used, JupyterHub is itself _also_ an OAuth **client** for the external oauth **provider**, e.g. GitHub.
|
||||
- **browser** A user's web browser, which makes requests and stores things like cookies
|
||||
- **token** The secret value used to represent a user's authorization. This is the final product of the OAuth process.
|
||||
- **code** A short-lived temporary secret that the **client** exchanges
|
||||
- **browser**: A user's web browser, which makes requests and stores things like cookies.
|
||||
- **token**: The secret value used to represent a user's authorization. This is the final product of the OAuth process.
|
||||
- **code**: A short-lived temporary secret that the **client** exchanges
|
||||
for a **token** at the conclusion of oauth,
|
||||
in what's generally called the "oauth callback handler."
|
||||
|
||||
@@ -56,8 +56,8 @@ A single oauth flow generally goes like this:
|
||||
|
||||
1. A **browser** makes an HTTP request to an oauth **client**.
|
||||
2. There are no credentials, so the client _redirects_ the browser to an "authorize" page on the oauth **provider** with some extra information:
|
||||
- the oauth **client id** of the client itself
|
||||
- the **redirect uri** to be redirected back to after completion
|
||||
- the oauth **client id** of the client itself.
|
||||
- the **redirect uri** to be redirected back to after completion.
|
||||
- the **scopes** requested, which the user should be presented with to confirm.
|
||||
This is the "X would like to be able to Y on your behalf. Allow this?" page you see on all the "Login with ..." pages around the Internet.
|
||||
3. During this authorize step,
|
||||
@@ -77,8 +77,8 @@ That's the end of the requests made between the **browser** and the **provider**
|
||||
|
||||
At this point:
|
||||
|
||||
- The browser is authenticated with the _provider_
|
||||
- The user's authorized permissions are recorded in an _oauth code_
|
||||
- The browser is authenticated with the _provider_.
|
||||
- The user's authorized permissions are recorded in an _oauth code_.
|
||||
- The _provider_ knows that the given oauth client's requested permissions have been granted, but the client doesn't know this yet.
|
||||
- All requests so far have been made directly by the browser.
|
||||
No requests have originated at the client or provider.
|
||||
@@ -86,8 +86,8 @@ At this point:
|
||||
### OAuth Client Handles Callback Request
|
||||
|
||||
Now we get to finish the OAuth process.
|
||||
Let's dig into what the oauth client does when it handles
|
||||
the oauth callback request with the
|
||||
Let's dig into what the OAuth client does when it handles
|
||||
the OAuth callback request.
|
||||
|
||||
- The OAuth client receives the _code_ and makes an API request to the _provider_ to exchange the code for a real _token_.
|
||||
This is the first direct request between the OAuth _client_ and the _provider_.
|
||||
@@ -113,24 +113,24 @@ So that's _one_ OAuth process.
|
||||
|
||||
## Full sequence of OAuth in JupyterHub
|
||||
|
||||
Let's go through the above oauth process in JupyterHub,
|
||||
Let's go through the above OAuth process in JupyterHub,
|
||||
with specific examples of each HTTP request and what information is contained.
|
||||
For bonus points, we are using the double-oauth example of JupyterHub configured with GitHubOAuthenticator.
|
||||
For bonus points, we are using the double-OAuth example of JupyterHub configured with GitHubOAuthenticator.
|
||||
|
||||
To disambiguate, we will call the OAuth process where JupyterHub is the **provider** "internal oauth,"
|
||||
and the one with JupyterHub as a **client** "external oauth."
|
||||
To disambiguate, we will call the OAuth process where JupyterHub is the **provider** "internal OAuth,"
|
||||
and the one with JupyterHub as a **client** "external OAuth."
|
||||
|
||||
Our starting point:
|
||||
|
||||
- a user's single-user server is running. Let's call them `danez`
|
||||
- jupyterhub is running with GitHub as an oauth provider (this means two full instances of oauth),
|
||||
- Danez has a fresh browser session with no cookies yet
|
||||
- Jupyterhub is running with GitHub as an OAuth provider (this means two full instances of OAuth),
|
||||
- Danez has a fresh browser session with no cookies yet.
|
||||
|
||||
First request:
|
||||
|
||||
- browser->single-user server running JupyterLab or Jupyter Classic
|
||||
- `GET /user/danez/notebooks/mynotebook.ipynb`
|
||||
- no credentials, so single-user server (as an oauth **client**) starts internal oauth process with JupyterHub (the **provider**)
|
||||
- no credentials, so single-user server (as an OAuth **client**) starts internal OAuth process with JupyterHub (the **provider**)
|
||||
- response: 302 redirect -> `/hub/api/oauth2/authorize`
|
||||
with:
|
||||
- client-id=`jupyterhub-user-danez`
|
||||
@@ -138,9 +138,9 @@ First request:
|
||||
|
||||
Second request, following redirect:
|
||||
|
||||
- browser->jupyterhub
|
||||
- browser->JupyterHub
|
||||
- `GET /hub/api/oauth2/authorize`
|
||||
- no credentials, so jupyterhub starts external oauth process _with GitHub_
|
||||
- no credentials, so JupyterHub starts external OAuth process _with GitHub_
|
||||
- response: 302 redirect -> `https://github.com/login/oauth/authorize`
|
||||
with:
|
||||
- client-id=`jupyterhub-client-uuid`
|
||||
@@ -154,8 +154,8 @@ c.JupyterHub.authenticator_class = 'github'
|
||||
```
|
||||
|
||||
That means authenticating a request to the Hub itself starts
|
||||
a _second_, external oauth process with GitHub as a provider.
|
||||
This external oauth process is optional, though.
|
||||
a _second_, external OAuth process with GitHub as a provider.
|
||||
This external OAuth process is optional, though.
|
||||
If you were using the default username+password PAMAuthenticator,
|
||||
this redirect would have been to `/hub/login` instead, to present the user
|
||||
with a login form.
|
||||
@@ -171,7 +171,7 @@ Here, GitHub prompts for login and asks for confirmation of authorization
|
||||
After successful authorization
|
||||
(either by looking up a pre-existing authorization,
|
||||
or recording it via form submission)
|
||||
GitHub issues an **oauth code** and redirects to `/hub/oauth_callback?code=github-code`
|
||||
GitHub issues an **OAuth code** and redirects to `/hub/oauth_callback?code=github-code`
|
||||
|
||||
Next request:
|
||||
|
||||
@@ -194,9 +194,9 @@ The second:
|
||||
- request made with access **token** in the `Authorization` header
|
||||
- response is the user model, including username, email, etc.
|
||||
|
||||
Now the external oauth callback request completes with:
|
||||
Now the external OAuth callback request completes with:
|
||||
|
||||
- set cookie on `/hub/` path, recording jupyterhub authentication so we don't need to do external oauth with GitHub again for a while
|
||||
- set cookie on `/hub/` path, recording jupyterhub authentication so we don't need to do external OAuth with GitHub again for a while
|
||||
- redirect -> `/hub/api/oauth2/authorize`
|
||||
|
||||
🎉 At this point, we have completed our first OAuth flow! 🎉
|
||||
@@ -211,14 +211,14 @@ Now, we get our first repeated request:
|
||||
2. automatically accepts authorization (shortcut taken when a user is visiting their own server)
|
||||
- redirect -> `/user/danez/oauth_callback?code=jupyterhub-code`
|
||||
|
||||
Here, we start the same oauth callback process as before, but at Danez's single-user server for the _internal_ oauth
|
||||
Here, we start the same OAuth callback process as before, but at Danez's single-user server for the _internal_ OAuth.
|
||||
|
||||
- browser->single-user server
|
||||
- `GET /user/danez/oauth_callback`
|
||||
|
||||
(in handler)
|
||||
|
||||
Inside the internal oauth callback handler,
|
||||
Inside the internal OAuth callback handler,
|
||||
Danez's server makes two API requests to JupyterHub:
|
||||
|
||||
The first:
|
||||
|
@@ -84,5 +84,5 @@ template (for example, `login.html`) with:
|
||||
```
|
||||
|
||||
Extending `page.html` puts the message on all pages, but note that
|
||||
extending `page.html` take precedence over an extension of a specific
|
||||
extending `page.html` takes precedence over an extension of a specific
|
||||
page (unlike the variable-based approach above).
|
||||
|
@@ -2,13 +2,13 @@
|
||||
|
||||
This document describes how JupyterHub routes requests.
|
||||
|
||||
This does not include the [REST API](./rest.md) urls.
|
||||
This does not include the [REST API](./rest.md) URLs.
|
||||
|
||||
In general, all URLs can be prefixed with `c.JupyterHub.base_url` to
|
||||
run the whole JupyterHub application on a prefix.
|
||||
|
||||
All authenticated handlers redirect to `/hub/login` to login users
|
||||
prior to being redirected back to the originating page.
|
||||
All authenticated handlers redirect to `/hub/login` to log-in users
|
||||
before being redirected back to the originating page.
|
||||
The returned request should preserve all query parameters.
|
||||
|
||||
## `/`
|
||||
@@ -25,12 +25,12 @@ This is an authenticated URL.
|
||||
|
||||
This handler redirects users to the default URL of the application,
|
||||
which defaults to the user's default server.
|
||||
That is, it redirects to `/hub/spawn` if the user's server is not running,
|
||||
or the server itself (`/user/:name`) if the server is running.
|
||||
That is, the handler redirects to `/hub/spawn` if the user's server is not running,
|
||||
or to the server itself (`/user/:name`) if the server is running.
|
||||
|
||||
This default url behavior can be customized in two ways:
|
||||
This default URL behavior can be customized in two ways:
|
||||
|
||||
To redirect users to the JupyterHub home page (`/hub/home`)
|
||||
First, to redirect users to the JupyterHub home page (`/hub/home`)
|
||||
instead of spawning their server,
|
||||
set `redirect_to_server` to False:
|
||||
|
||||
@@ -40,7 +40,7 @@ c.JupyterHub.redirect_to_server = False
|
||||
|
||||
This might be useful if you have a Hub where you expect
|
||||
users to be managing multiple server configurations
|
||||
and automatic spawning is not desirable.
|
||||
but automatic spawning is not desirable.
|
||||
|
||||
Second, you can customise the landing page to any page you like,
|
||||
such as a custom service you have deployed e.g. with course information:
|
||||
@@ -57,7 +57,7 @@ By default, the Hub home page has just one or two buttons
|
||||
for starting and stopping the user's server.
|
||||
|
||||
If named servers are enabled, there will be some additional
|
||||
tools for management of named servers.
|
||||
tools for management of the named servers.
|
||||
|
||||
_Version added: 1.0_ named server UI is new in 1.0.
|
||||
|
||||
@@ -65,34 +65,34 @@ _Version added: 1.0_ named server UI is new in 1.0.
|
||||
|
||||
This is the JupyterHub login page.
|
||||
If you have a form-based username+password login,
|
||||
such as the default PAMAuthenticator,
|
||||
such as the default [PAMAuthenticator](https://en.wikipedia.org/wiki/Pluggable_authentication_module),
|
||||
this page will render the login form.
|
||||
|
||||

|
||||
|
||||
If login is handled by an external service,
|
||||
e.g. with OAuth, this page will have a button,
|
||||
declaring "Login with ..." which users can click
|
||||
to login with the chosen service.
|
||||
declaring "Log in with ..." which users can click
|
||||
to log in with the chosen service.
|
||||
|
||||

|
||||
|
||||
If you want to skip the user-interaction to initiate logging in
|
||||
via the button, you can set
|
||||
If you want to skip the user interaction and initiate login
|
||||
via the button, you can set:
|
||||
|
||||
```python
|
||||
c.Authenticator.auto_login = True
|
||||
```
|
||||
|
||||
This can be useful when the user is "already logged in" via some mechanism,
|
||||
but a handshake via redirects is necessary to complete the authentication with JupyterHub.
|
||||
This can be useful when the user is "already logged in" via some mechanism.
|
||||
However, a handshake via `redirects` is necessary to complete the authentication with JupyterHub.
|
||||
|
||||
## `/hub/logout`
|
||||
|
||||
Visiting `/hub/logout` clears cookies from the current browser.
|
||||
Visiting `/hub/logout` clears [cookies](https://en.wikipedia.org/wiki/HTTP_cookie) from the current browser.
|
||||
Note that **logging out does not stop a user's server(s)** by default.
|
||||
|
||||
If you would like to shutdown user servers on logout,
|
||||
If you would like to shut down user servers on logout,
|
||||
you can enable this behavior with:
|
||||
|
||||
```python
|
||||
@@ -105,8 +105,8 @@ does not mean the user is no longer actively using their server from another mac
|
||||
## `/user/:username[/:servername]`
|
||||
|
||||
If a user's server is running, this URL is handled by the user's given server,
|
||||
not the Hub.
|
||||
The username is the first part and, if using named servers,
|
||||
not by the Hub.
|
||||
The username is the first part, and if using named servers,
|
||||
the server name is the second part.
|
||||
|
||||
If the user's server is _not_ running, this will be redirected to `/hub/user/:username/...`
|
||||
@@ -120,11 +120,11 @@ if the specified server were running).
|
||||
Handling this URL is the most complicated condition in JupyterHub,
|
||||
because there can be many states:
|
||||
|
||||
1. server is not active
|
||||
1. the server is not active
|
||||
a. user matches
|
||||
b. user doesn't match
|
||||
2. server is ready
|
||||
3. server is pending, but not ready
|
||||
2. the server is ready
|
||||
3. the server is pending, but not ready
|
||||
|
||||
If the server is pending spawn,
|
||||
the browser will be redirected to `/hub/spawn-pending/:username/:servername`
|
||||
@@ -140,39 +140,37 @@ Some checks are performed and a delay is added before redirecting back to `/user
|
||||
If something is really wrong, this can result in a redirect loop.
|
||||
|
||||
Visiting this page will never result in triggering the spawn of servers
|
||||
without additional user action (i.e. clicking the link on the page)
|
||||
without additional user action (i.e. clicking the link on the page).
|
||||
|
||||

|
||||
|
||||
_Version changed: 1.0_
|
||||
|
||||
Prior to 1.0, this URL itself was responsible for spawning servers,
|
||||
and served the progress page if it was pending,
|
||||
redirected to running servers, and
|
||||
This was useful because it made sure that requested servers were restarted after they stopped,
|
||||
but could also be harmful because unused servers would continuously be restarted if e.g.
|
||||
an idle JupyterLab frontend were open pointed at it,
|
||||
which constantly makes polling requests.
|
||||
Prior to 1.0, this URL itself was responsible for spawning servers.
|
||||
If the progress page was pending, the URL redirected it to running servers.
|
||||
This was useful because it made sure that the requested servers were restarted after they stopped.
|
||||
However, it could also be harmful because unused servers would continuously be restarted if e.g.
|
||||
an idle JupyterLab frontend that constantly makes polling requests was openly pointed at it.
|
||||
|
||||
### Special handling of API requests
|
||||
|
||||
Requests to `/user/:username[/:servername]/api/...` are assumed to be
|
||||
from applications connected to stopped servers.
|
||||
These are failed with 503 and an informative JSON error message
|
||||
indicating how to spawn the server.
|
||||
This is meant to help applications such as JupyterLab
|
||||
These requests fail with a `503` status code and an informative JSON error message
|
||||
that indicates how to spawn the server.
|
||||
This is meant to help applications such as JupyterLab,
|
||||
that are connected to a server that has stopped.
|
||||
|
||||
_Version changed: 1.0_
|
||||
|
||||
JupyterHub 0.9 failed these API requests with status 404,
|
||||
but 1.0 uses 503.
|
||||
JupyterHub version 0.9 failed these API requests with status `404`,
|
||||
but version 1.0 uses 503.
|
||||
|
||||
## `/user-redirect/...`
|
||||
|
||||
This URL is for sharing a URL that will redirect a user
|
||||
The `/user-redirect/...` URL is for sharing a URL that will redirect a user
|
||||
to a path on their own default server.
|
||||
This is useful when users have the same file at the same URL on their servers,
|
||||
This is useful when different users have the same file at the same URL on their servers,
|
||||
and you want a single link to give to any user that will open that file on their server.
|
||||
|
||||
e.g. a link to `/user-redirect/notebooks/Index.ipynb`
|
||||
@@ -194,7 +192,7 @@ that is intended to make it possible.
|
||||
### `/hub/spawn[/:username[/:servername]]`
|
||||
|
||||
Requesting `/hub/spawn` will spawn the default server for the current user.
|
||||
If `username` and optionally `servername` are specified,
|
||||
If the `username` and optionally `servername` are specified,
|
||||
then the specified server for the specified user will be spawned.
|
||||
Once spawn has been requested,
|
||||
the browser is redirected to `/hub/spawn-pending/...`.
|
||||
@@ -207,7 +205,7 @@ and a POST request will trigger the actual spawn and redirect.
|
||||
|
||||
_Version added: 1.0_
|
||||
|
||||
1.0 adds the ability to specify username and servername.
|
||||
1.0 adds the ability to specify `username` and `servername`.
|
||||
Prior to 1.0, only `/hub/spawn` was recognized for the default server.
|
||||
|
||||
_Version changed: 1.0_
|
||||
@@ -247,7 +245,7 @@ against the [JupyterHub REST API](./rest.md).
|
||||
|
||||
Administrators can take various administrative actions from this page:
|
||||
|
||||
1. add/remove users
|
||||
2. grant admin privileges
|
||||
3. start/stop user servers
|
||||
4. shutdown JupyterHub itself
|
||||
- add/remove users
|
||||
- grant admin privileges
|
||||
- start/stop user servers
|
||||
- shutdown JupyterHub itself
|
||||
|
@@ -56,7 +56,7 @@ If any additional services are run on the same domain as the Hub, the services
|
||||
|
||||
## Mitigate security issues
|
||||
|
||||
Several approaches to mitigating these issues with configuration
|
||||
The several approaches to mitigating security issues with configuration
|
||||
options provided by JupyterHub include:
|
||||
|
||||
### Enable subdomains
|
||||
@@ -74,10 +74,10 @@ resolves the cross-site issues.
|
||||
|
||||
### Disable user config
|
||||
|
||||
If subdomains are not available or not desirable, JupyterHub provides the
|
||||
If subdomains are unavailable or undesirable, JupyterHub provides a
|
||||
configuration option `Spawner.disable_user_config`, which can be set to prevent
|
||||
the user-owned configuration files from being loaded. After implementing this
|
||||
option, PATHs and package installation and PATHs are the other things that the
|
||||
option, `PATH`s and package installation are the other things that the
|
||||
admin must enforce.
|
||||
|
||||
### Prevent spawners from evaluating shell configuration files
|
||||
@@ -115,9 +115,9 @@ extend to securing the `tcp` sockets as well.
|
||||
|
||||
## Security audits
|
||||
|
||||
We recommend that you do periodic reviews of your deployment's security. It is
|
||||
good practice to keep JupyterHub, configurable-http-proxy, and nodejs
|
||||
versions up to date.
|
||||
We recommend that you do periodic reviews of your deployment's security. It's
|
||||
good practice to keep [JupyterHub](https://readthedocs.org/projects/jupyterhub/), [configurable-http-proxy][], and [nodejs
|
||||
versions](https://github.com/nodejs/Release) up to date.
|
||||
|
||||
A handy website for testing your deployment is
|
||||
[Qualsys' SSL analyzer tool](https://www.ssllabs.com/ssltest/analyze.html).
|
||||
|
@@ -15,8 +15,8 @@ If you have tried to start the JupyterHub proxy and it fails to start:
|
||||
- Try starting with `jupyterhub --ip=0.0.0.0`
|
||||
|
||||
**Note**: If this occurs on Ubuntu/Debian, check that you are using a
|
||||
recent version of [Node](https://nodejs.org). Some versions of Ubuntu/Debian come with a version
|
||||
of Node that is very old, and it is necessary to update Node.
|
||||
recent version of [Node](https://nodejs.org). Some versions of Ubuntu/Debian come with a very old version
|
||||
of Node and it is necessary to update Node.
|
||||
|
||||
### sudospawner fails to run
|
||||
|
||||
@@ -41,7 +41,7 @@ this to a particular set of users, and admin_users lets you specify who
|
||||
among them may use the admin interface (not necessary, unless you need to do
|
||||
things like inspect other users' servers or modify the user list at runtime).
|
||||
|
||||
### JupyterHub Docker container not accessible at localhost
|
||||
### JupyterHub Docker container is not accessible at localhost
|
||||
|
||||
Even though the command to start your Docker container exposes port 8000
|
||||
(`docker run -p 8000:8000 -d --name jupyterhub jupyterhub/jupyterhub jupyterhub`),
|
||||
@@ -71,7 +71,7 @@ After successfully logging in to JupyterHub with a compatible authenticator, I g
|
||||
This issue occurs when the authenticator requires a local system user to exist. In these cases, you need to use a spawner
|
||||
that does not require an existing system user account, such as `DockerSpawner` or `KubeSpawner`.
|
||||
|
||||
### How can I run JupyterHub with sudo but use my current env vars and virtualenv location?
|
||||
### How can I run JupyterHub with sudo but use my current environment variables and virtualenv location?
|
||||
|
||||
When launching JupyterHub with `sudo jupyterhub` I get import errors and my environment variables don't work.
|
||||
|
||||
@@ -87,7 +87,7 @@ sudo MY_ENV=abc123 \
|
||||
|
||||
### Error 500 after spawning my single-user server
|
||||
|
||||
You receive a 500 error when accessing the URL `/user/<your_name>/...`.
|
||||
You receive a 500 error while accessing the URL `/user/<your_name>/...`.
|
||||
This is often seen when your single-user server cannot verify your user cookie
|
||||
with the Hub.
|
||||
|
||||
@@ -268,7 +268,7 @@ similar to this one:
|
||||
provides additional information. The [pySpark configuration documentation](https://spark.apache.org/docs/0.9.0/configuration.html)
|
||||
is also helpful for programmatic configuration examples.
|
||||
|
||||
### How do I use JupyterLab's prerelease version with JupyterHub?
|
||||
### How do I use JupyterLab's pre-release version with JupyterHub?
|
||||
|
||||
While JupyterLab is still under active development, we have had users
|
||||
ask about how to try out JupyterLab with JupyterHub.
|
||||
@@ -294,7 +294,7 @@ notebook servers to default to JupyterLab:
|
||||
### How do I set up JupyterHub for a workshop (when users are not known ahead of time)?
|
||||
|
||||
1. Set up JupyterHub using OAuthenticator for GitHub authentication
|
||||
2. Configure the admin list to have workshop leaders be listed with administrator privileges.
|
||||
2. Configure the admin list to have workshop leaders listed with administrator privileges.
|
||||
|
||||
Users will need a GitHub account to log in and be authenticated by the Hub.
|
||||
|
||||
|
Reference in New Issue
Block a user