mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-15 22:13:00 +00:00
Merge branch 'master' into named_servers
This commit is contained in:
@@ -99,7 +99,7 @@ more configuration of the system.
|
||||
|
||||
## Configuration
|
||||
|
||||
The [Getting Started](docs/source/getting-started.md) section of the
|
||||
The [Getting Started](http://jupyterhub.readthedocs.io/en/latest/getting-started.html) section of the
|
||||
documentation explains the common steps in setting up JupyterHub.
|
||||
|
||||
The [**JupyterHub tutorial**](https://github.com/jupyterhub/jupyterhub-tutorial)
|
||||
|
@@ -1,45 +1,72 @@
|
||||
# Configuration Basics
|
||||
|
||||
The [getting started document](docs/source/getting-started.md) contains
|
||||
general information about configuring a JupyterHub deployment and the
|
||||
[configuration reference](docs/source/configuration-guide.md) provides more
|
||||
comprehensive detail.
|
||||
The section contains basic information about configuring settings for a JupyterHub
|
||||
deployment. The [configuration reference](./configuration-guide.html)
|
||||
provides additional detail.
|
||||
|
||||
## JupyterHub configuration
|
||||
This section will help you learn how to:
|
||||
|
||||
Configuration parameters may be set by:
|
||||
- a configuration file `jupyterhub_config.py`, or
|
||||
- as options from the command line.
|
||||
- generate a default configuration file, `jupyterhub_config.py`
|
||||
- start with a specific configuration file
|
||||
- configure JupyterHub using command line options
|
||||
- find information and examples for some common deployments
|
||||
|
||||
### Generate a default config file
|
||||
## Generate a default config file
|
||||
|
||||
On startup, JupyterHub will look by default for a configuration file named
|
||||
`jupyterhub_config.py` in the current working directory.
|
||||
On startup, JupyterHub will look by default for a configuration file,
|
||||
`jupyterhub_config.py`, in the current working directory.
|
||||
|
||||
To generate a default config file `jupyterhub_config.py`:
|
||||
To generate a default config file, `jupyterhub_config.py`:
|
||||
|
||||
```bash
|
||||
jupyterhub --generate-config
|
||||
```
|
||||
|
||||
This default `jupyterhub_config.py` file contains comments and guidance for all
|
||||
configuration variables and their default values.
|
||||
configuration variables and their default values. We recommend storing
|
||||
configuration files in the standard UNIX filesystem location, i.e.
|
||||
`/etc/jupyterhub`.
|
||||
|
||||
### Configure using command line options
|
||||
## Start with a specific config file
|
||||
|
||||
You can load a specific config file and start JupyterHub using:
|
||||
|
||||
```bash
|
||||
jupyterhub -f /path/to/jupyterhub_config.py
|
||||
```
|
||||
|
||||
If you have stored your configuration file in the recommended UNIX filesystem
|
||||
location, `/etc/jupyterhub`, the following command will start JupyterHub using
|
||||
the configuration file:
|
||||
|
||||
```bash
|
||||
jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
|
||||
```
|
||||
|
||||
The IPython documentation provides additional information on the
|
||||
[config system](http://ipython.readthedocs.io/en/stable/development/config.html)
|
||||
that Jupyter uses.
|
||||
|
||||
## Configure using command line options
|
||||
|
||||
To display all command line options that are available for configuration:
|
||||
|
||||
```bash
|
||||
jupyterhub --help-all
|
||||
```
|
||||
|
||||
Configuration using the command line options is done when launching JupyterHub.
|
||||
For example, to start JupyterHub on ``10.0.1.2:443`` with **https**, you
|
||||
For example, to start JupyterHub on ``10.0.1.2:443`` with https, you
|
||||
would enter:
|
||||
|
||||
```bash
|
||||
jupyterhub --ip 10.0.1.2 --port 443 --ssl-key my_ssl.key --ssl-cert my_ssl.cert
|
||||
```
|
||||
|
||||
All configurable options are technically configurable on the command-line,
|
||||
even if some are really inconvenient to type. Just replace the desired option,
|
||||
`c.Class.trait`, with `--Class.trait`. For example, to configure the
|
||||
All configurable options may technically be set on the command-line,
|
||||
though some are inconvenient to type. To set a particular configuration
|
||||
parameter, `c.Class.trait`, you would use the command line option,
|
||||
`--Class.trait`, when starting JupyterHub. For example, to configure the
|
||||
`c.Spawner.notebook_dir` trait from the command-line, use the
|
||||
`--Spawner.notebook_dir` option:
|
||||
|
||||
@@ -47,23 +74,14 @@ even if some are really inconvenient to type. Just replace the desired option,
|
||||
jupyterhub --Spawner.notebook_dir='~/assignments'
|
||||
```
|
||||
|
||||
### Load a specific config file
|
||||
## Configure for various deployment environments
|
||||
|
||||
You can load a specific config file with:
|
||||
|
||||
```bash
|
||||
jupyterhub -f /path/to/jupyterhub_config.py
|
||||
```
|
||||
|
||||
See also: [general docs](http://ipython.org/ipython-doc/dev/development/config.html)
|
||||
on the config system Jupyter uses.
|
||||
|
||||
### Configuration for different deployment environments
|
||||
|
||||
The default authentication and process spawning mechanisms can be replaced,
|
||||
which allows plugging into a variety of authentication methods or process
|
||||
control and deployment environments. Some examples, meant as illustration and
|
||||
testing of this concept, are:
|
||||
The default authentication and process spawning mechanisms can be replaced, and
|
||||
specific [authenticators](./authenticators-users-basics.html) and
|
||||
[spawners](./spawners-basics.html) 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](./config-examples.html),
|
||||
meant as illustration, 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)
|
||||
|
@@ -1,30 +1,30 @@
|
||||
# Configuration examples
|
||||
|
||||
This section provides configuration files and tips for the following
|
||||
configurations:
|
||||
This section provides examples, including configuration files and tips, for the
|
||||
following configurations:
|
||||
|
||||
- Example with GitHub OAuth
|
||||
- Example with nginx reverse proxy
|
||||
- JupyterHub deployment on AWS with NGINX
|
||||
- Using GitHub OAuth
|
||||
- Using nginx reverse proxy
|
||||
|
||||
## Using GitHub OAuth
|
||||
|
||||
## Example with GitHub OAuth
|
||||
In this example, we show a configuration file for a fairly standard JupyterHub
|
||||
deployment with the following assumptions:
|
||||
|
||||
In the following example, we show a configuration files for a fairly standard JupyterHub deployment with the following assumptions:
|
||||
|
||||
* JupyterHub is running on a single cloud server
|
||||
* Running JupyterHub on a single cloud server
|
||||
* Using SSL on the standard HTTPS port 443
|
||||
* You want to use GitHub OAuth (using oauthenticator) for login
|
||||
* You need the users to exist locally on the server
|
||||
* You want users' notebooks to be served from `~/assignments` to allow users to browse for notebooks within
|
||||
other users home directories
|
||||
* You want the landing page for each user to be a Welcome.ipynb notebook in their assignments directory.
|
||||
* Using GitHub OAuth (using oauthenticator) for login
|
||||
* Users exist locally on the server
|
||||
* Users' notebooks to be served from `~/assignments` to allow users to browse
|
||||
for notebooks within other users' home directories
|
||||
* You want the landing page for each user to be a `Welcome.ipynb` notebook in
|
||||
their assignments directory.
|
||||
* All runtime files are put into `/srv/jupyterhub` and log files in `/var/log`.
|
||||
|
||||
Let's start out with `jupyterhub_config.py`:
|
||||
The `jupyterhub_config.py` file would have these settings:
|
||||
|
||||
```python
|
||||
# jupyterhub_config.py
|
||||
# jupyterhub_config.py file
|
||||
c = get_config()
|
||||
|
||||
import os
|
||||
@@ -35,7 +35,6 @@ ssl_dir = pjoin(runtime_dir, 'ssl')
|
||||
if not os.path.exists(ssl_dir):
|
||||
os.makedirs(ssl_dir)
|
||||
|
||||
|
||||
# Allows multiple single-server per user
|
||||
c.JupyterHub.allow_named_servers = True
|
||||
|
||||
@@ -54,9 +53,9 @@ c.JupyterHub.db_url = pjoin(runtime_dir, 'jupyterhub.sqlite')
|
||||
c.JupyterHub.extra_log_file = '/var/log/jupyterhub.log'
|
||||
|
||||
# use GitHub OAuthenticator for local users
|
||||
|
||||
c.JupyterHub.authenticator_class = 'oauthenticator.LocalGitHubOAuthenticator'
|
||||
c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL']
|
||||
|
||||
# create system users that don't exist yet
|
||||
c.LocalAuthenticator.create_system_users = True
|
||||
|
||||
@@ -72,34 +71,42 @@ c.Spawner.notebook_dir = '~/assignments'
|
||||
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
|
||||
```
|
||||
|
||||
Using the GitHub Authenticator [requires a few additional env variables][oauth-setup],
|
||||
which we will need to set when we launch the server:
|
||||
Using the GitHub Authenticator requires a few additional
|
||||
environment variable to be set prior to launching JupyterHub:
|
||||
|
||||
```bash
|
||||
export GITHUB_CLIENT_ID=github_id
|
||||
export GITHUB_CLIENT_SECRET=github_secret
|
||||
export OAUTH_CALLBACK_URL=https://example.com/hub/oauth_callback
|
||||
export CONFIGPROXY_AUTH_TOKEN=super-secret
|
||||
jupyterhub -f /path/to/aboveconfig.py
|
||||
jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
|
||||
```
|
||||
|
||||
## Example with nginx reverse proxy
|
||||
## Using nginx reverse proxy
|
||||
|
||||
In the following example, we show configuration files for a JupyterHub server running locally on port `8000` but accessible from the outside on the standard SSL port `443`. This could be useful if the JupyterHub server machine is also hosting other domains or content on `443`. The goal here is to have the following be true:
|
||||
In the following example, we show configuration files for a JupyterHub server
|
||||
running locally on port `8000` but accessible from the outside on the standard
|
||||
SSL port `443`. This could be useful if the JupyterHub server machine is also
|
||||
hosting other domains or content on `443`. The goal in this example is to
|
||||
satisfy the following:
|
||||
|
||||
* JupyterHub is running on a server, accessed *only* via `HUB.DOMAIN.TLD:443`
|
||||
* On the same machine, `NO_HUB.DOMAIN.TLD` strictly serves different content, also on port `443`
|
||||
* `nginx` is used to manage the web servers / reverse proxy (which means that only nginx will be able to bind two servers to `443`)
|
||||
* After testing, the server in question should be able to score an A+ on the Qualys SSL Labs [SSL Server Test](https://www.ssllabs.com/ssltest/)
|
||||
* On the same machine, `NO_HUB.DOMAIN.TLD` strictly serves different content,
|
||||
also on port `443`
|
||||
* `nginx` is used to manage the web servers / reverse proxy (which means that
|
||||
only nginx will be able to bind two servers to `443`)
|
||||
* After testing, the server in question should be able to score an A+ on the
|
||||
Qualys SSL Labs [SSL Server Test](https://www.ssllabs.com/ssltest/)
|
||||
|
||||
Let's start out with `jupyterhub_config.py`:
|
||||
Let's start out with needed JupyterHub configuration in `jupyterhub_config.py`:
|
||||
|
||||
```python
|
||||
# Force the proxy to only listen to connections to 127.0.0.1
|
||||
c.JupyterHub.ip = '127.0.0.1'
|
||||
```
|
||||
|
||||
The `nginx` server config files are fairly standard fare except for the two `location` blocks within the `HUB.DOMAIN.TLD` config file:
|
||||
The **`nginx` server config file** is fairly standard fare except for the two
|
||||
`location` blocks within the `HUB.DOMAIN.TLD` config file:
|
||||
|
||||
```bash
|
||||
# HTTP server to redirect all 80 traffic to SSL/HTTPS
|
||||
@@ -162,7 +169,11 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
`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 of the site as well as the applicable location call:
|
||||
`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
|
||||
of the site as well as the applicable location call:
|
||||
|
||||
```bash
|
||||
server {
|
||||
@@ -195,4 +206,6 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
Now just restart `nginx`, restart the JupyterHub, and enjoy accessing https://HUB.DOMAIN.TLD while serving other content securely on https://NO_HUB.DOMAIN.TLD.
|
||||
Now just restart `nginx`, restart the JupyterHub, and enjoy accessing
|
||||
https://HUB.DOMAIN.TLD while serving other content securely on
|
||||
https://NO_HUB.DOMAIN.TLD.
|
||||
|
@@ -247,7 +247,19 @@ class Hashed(object):
|
||||
def token(self, token):
|
||||
"""Store the hashed value and prefix for a token"""
|
||||
self.prefix = token[:self.prefix_length]
|
||||
self.hashed = hash_token(token, rounds=self.rounds, salt=self.salt_bytes, algorithm=self.algorithm)
|
||||
if len(token) >= 32:
|
||||
# Tokens are generally UUIDs, which have sufficient entropy on their own
|
||||
# and don't need salt & hash rounds.
|
||||
# ref: https://security.stackexchange.com/a/151262/155114
|
||||
rounds = 1
|
||||
salt_bytes = b''
|
||||
else:
|
||||
# users can still specify API tokens in a few ways,
|
||||
# so trigger salt & hash rounds if they provide a short token
|
||||
app_log.warning("Applying salt & hash rounds to %sB token" % len(token))
|
||||
rounds = self.rounds
|
||||
salt_bytes = self.salt_bytes
|
||||
self.hashed = hash_token(token, rounds=rounds, salt=salt_bytes, algorithm=self.algorithm)
|
||||
|
||||
def match(self, token):
|
||||
"""Is this my token?"""
|
||||
@@ -394,7 +406,7 @@ class OAuthAccessToken(Hashed, Base):
|
||||
|
||||
# from Hashed
|
||||
hashed = Column(Unicode(64))
|
||||
prefix = Column(Unicode(16))
|
||||
prefix = Column(Unicode(16), index=True)
|
||||
|
||||
def __repr__(self):
|
||||
return "<{cls}('{prefix}...', user='{user}'>".format(
|
||||
|
@@ -146,7 +146,7 @@ class Spawner(LoggingConfigurable):
|
||||
The surrounding `<form>` element and the submit button are already provided.
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
.. code:: html
|
||||
|
||||
Set your key:
|
||||
@@ -370,18 +370,18 @@ class Spawner(LoggingConfigurable):
|
||||
help="""
|
||||
An optional hook function that you can implement to do some bootstrapping work before
|
||||
the spawner starts. For example, create a directory for your user or load initial content.
|
||||
|
||||
This can be set independent of any concrete spawner implementation.
|
||||
|
||||
Example:
|
||||
|
||||
from subprocess import check_call
|
||||
def my_hook(spawner):
|
||||
username = spawner.user.name
|
||||
check_call(['./examples/bootstrap-script/bootstrap.sh', username])
|
||||
|
||||
c.Spawner.pre_spawn_hook = my_hook
|
||||
|
||||
This can be set independent of any concrete spawner implementation.
|
||||
|
||||
Example::
|
||||
|
||||
from subprocess import check_call
|
||||
def my_hook(spawner):
|
||||
username = spawner.user.name
|
||||
check_call(['./examples/bootstrap-script/bootstrap.sh', username])
|
||||
|
||||
c.Spawner.pre_spawn_hook = my_hook
|
||||
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
@@ -464,7 +464,7 @@ class Spawner(LoggingConfigurable):
|
||||
env['JUPYTERHUB_HOST'] = self.hub.public_host
|
||||
env['JUPYTERHUB_OAUTH_CALLBACK_URL'] = \
|
||||
url_path_join(self.user.url, self.name, 'oauth_callback')
|
||||
|
||||
|
||||
# Info previously passed on args
|
||||
env['JUPYTERHUB_USER'] = self.user.name
|
||||
env['JUPYTERHUB_API_URL'] = self.hub.api_url
|
||||
@@ -884,7 +884,7 @@ class LocalProcessSpawner(Spawner):
|
||||
cmd = self.shell_cmd + [' '.join(pipes.quote(s) for s in cmd)]
|
||||
|
||||
self.log.info("Spawning %s", ' '.join(pipes.quote(s) for s in cmd))
|
||||
|
||||
|
||||
popen_kwargs = dict(
|
||||
preexec_fn=self.make_preexec_fn(self.user.name),
|
||||
start_new_session=True, # don't forward signals
|
||||
|
Reference in New Issue
Block a user