Merge branch 'master' into named_servers

This commit is contained in:
Min RK
2017-07-25 16:56:16 +02:00
committed by GitHub
5 changed files with 124 additions and 81 deletions

View File

@@ -99,7 +99,7 @@ more configuration of the system.
## Configuration ## 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. documentation explains the common steps in setting up JupyterHub.
The [**JupyterHub tutorial**](https://github.com/jupyterhub/jupyterhub-tutorial) The [**JupyterHub tutorial**](https://github.com/jupyterhub/jupyterhub-tutorial)

View File

@@ -1,45 +1,72 @@
# Configuration Basics # Configuration Basics
The [getting started document](docs/source/getting-started.md) contains The section contains basic information about configuring settings for a JupyterHub
general information about configuring a JupyterHub deployment and the deployment. The [configuration reference](./configuration-guide.html)
[configuration reference](docs/source/configuration-guide.md) provides more provides additional detail.
comprehensive detail.
## JupyterHub configuration This section will help you learn how to:
Configuration parameters may be set by: - generate a default configuration file, `jupyterhub_config.py`
- a configuration file `jupyterhub_config.py`, or - start with a specific configuration file
- as options from the command line. - 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 On startup, JupyterHub will look by default for a configuration file,
`jupyterhub_config.py` in the current working directory. `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 ```bash
jupyterhub --generate-config jupyterhub --generate-config
``` ```
This default `jupyterhub_config.py` file contains comments and guidance for all 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: To display all command line options that are available for configuration:
```bash
jupyterhub --help-all jupyterhub --help-all
```
Configuration using the command line options is done when launching JupyterHub. 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: would enter:
```bash
jupyterhub --ip 10.0.1.2 --port 443 --ssl-key my_ssl.key --ssl-cert my_ssl.cert 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, All configurable options may technically be set on the command-line,
even if some are really inconvenient to type. Just replace the desired option, though some are inconvenient to type. To set a particular configuration
`c.Class.trait`, with `--Class.trait`. For example, to configure the 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 `c.Spawner.notebook_dir` trait from the command-line, use the
`--Spawner.notebook_dir` option: `--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' jupyterhub --Spawner.notebook_dir='~/assignments'
``` ```
### Load a specific config file ## Configure for various deployment environments
You can load a specific config file with: The default authentication and process spawning mechanisms can be replaced, and
specific [authenticators](./authenticators-users-basics.html) and
```bash [spawners](./spawners-basics.html) can be set in the configuration file.
jupyterhub -f /path/to/jupyterhub_config.py 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:
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:
- Using GitHub OAuth instead of PAM with [OAuthenticator](https://github.com/jupyterhub/oauthenticator) - 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) - Spawning single-user servers with Docker, using the [DockerSpawner](https://github.com/jupyterhub/dockerspawner)

View File

@@ -1,30 +1,30 @@
# Configuration examples # Configuration examples
This section provides configuration files and tips for the following This section provides examples, including configuration files and tips, for the
configurations: following configurations:
- Example with GitHub OAuth - Using GitHub OAuth
- Example with nginx reverse proxy - Using nginx reverse proxy
- JupyterHub deployment on AWS with NGINX
## 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: * Running JupyterHub on a single cloud server
* JupyterHub is running on a single cloud server
* Using SSL on the standard HTTPS port 443 * Using SSL on the standard HTTPS port 443
* You want to use GitHub OAuth (using oauthenticator) for login * Using GitHub OAuth (using oauthenticator) for login
* You need the users to exist locally on the server * Users exist locally on the server
* You want users' notebooks to be served from `~/assignments` to allow users to browse for notebooks within * Users' notebooks to be served from `~/assignments` to allow users to browse
other users home directories 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. * 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`. * 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 ```python
# jupyterhub_config.py # jupyterhub_config.py file
c = get_config() c = get_config()
import os import os
@@ -35,7 +35,6 @@ ssl_dir = pjoin(runtime_dir, 'ssl')
if not os.path.exists(ssl_dir): if not os.path.exists(ssl_dir):
os.makedirs(ssl_dir) os.makedirs(ssl_dir)
# Allows multiple single-server per user # Allows multiple single-server per user
c.JupyterHub.allow_named_servers = True 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' c.JupyterHub.extra_log_file = '/var/log/jupyterhub.log'
# use GitHub OAuthenticator for local users # use GitHub OAuthenticator for local users
c.JupyterHub.authenticator_class = 'oauthenticator.LocalGitHubOAuthenticator' c.JupyterHub.authenticator_class = 'oauthenticator.LocalGitHubOAuthenticator'
c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL'] c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL']
# create system users that don't exist yet # create system users that don't exist yet
c.LocalAuthenticator.create_system_users = True c.LocalAuthenticator.create_system_users = True
@@ -72,34 +71,42 @@ c.Spawner.notebook_dir = '~/assignments'
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb'] c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
``` ```
Using the GitHub Authenticator [requires a few additional env variables][oauth-setup], Using the GitHub Authenticator requires a few additional
which we will need to set when we launch the server: environment variable to be set prior to launching JupyterHub:
```bash ```bash
export GITHUB_CLIENT_ID=github_id export GITHUB_CLIENT_ID=github_id
export GITHUB_CLIENT_SECRET=github_secret export GITHUB_CLIENT_SECRET=github_secret
export OAUTH_CALLBACK_URL=https://example.com/hub/oauth_callback export OAUTH_CALLBACK_URL=https://example.com/hub/oauth_callback
export CONFIGPROXY_AUTH_TOKEN=super-secret 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` * 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` * On the same machine, `NO_HUB.DOMAIN.TLD` strictly serves different content,
* `nginx` is used to manage the web servers / reverse proxy (which means that only nginx will be able to bind two servers to `443`) also on port `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/) * `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 ```python
# Force the proxy to only listen to connections to 127.0.0.1 # Force the proxy to only listen to connections to 127.0.0.1
c.JupyterHub.ip = '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 ```bash
# HTTP server to redirect all 80 traffic to SSL/HTTPS # 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 ```bash
server { 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.

View File

@@ -247,7 +247,19 @@ class Hashed(object):
def token(self, token): def token(self, token):
"""Store the hashed value and prefix for a token""" """Store the hashed value and prefix for a token"""
self.prefix = token[:self.prefix_length] 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): def match(self, token):
"""Is this my token?""" """Is this my token?"""
@@ -394,7 +406,7 @@ class OAuthAccessToken(Hashed, Base):
# from Hashed # from Hashed
hashed = Column(Unicode(64)) hashed = Column(Unicode(64))
prefix = Column(Unicode(16)) prefix = Column(Unicode(16), index=True)
def __repr__(self): def __repr__(self):
return "<{cls}('{prefix}...', user='{user}'>".format( return "<{cls}('{prefix}...', user='{user}'>".format(

View File

@@ -373,7 +373,7 @@ class Spawner(LoggingConfigurable):
This can be set independent of any concrete spawner implementation. This can be set independent of any concrete spawner implementation.
Example: Example::
from subprocess import check_call from subprocess import check_call
def my_hook(spawner): def my_hook(spawner):