mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-08 10:34:10 +00:00
147 lines
5.6 KiB
Markdown
147 lines
5.6 KiB
Markdown
# Security
|
|
|
|
**IMPORTANT: You should not run JupyterHub without SSL encryption on a public network.**
|
|
|
|
---
|
|
|
|
**Deprecation note:** Removed `--no-ssl` in version 0.7.
|
|
|
|
JupyterHub versions 0.5 and 0.6 require extra confirmation via `--no-ssl` to
|
|
allow running without SSL using the command `jupyterhub --no-ssl`. The
|
|
`--no-ssl` command line option is not needed anymore in version 0.7.
|
|
|
|
---
|
|
|
|
Security is the most important aspect of configuring Jupyter. There are four main aspects of the
|
|
security configuration:
|
|
|
|
1. SSL encryption (to enable HTTPS)
|
|
2. Cookie secret (a key for encrypting browser cookies)
|
|
3. Proxy authentication token (used for the Hub and other services to authenticate to the Proxy)
|
|
4. Periodic security audits
|
|
|
|
*Note* that the **Hub** hashes all secrets (e.g., auth tokens) before storing them in its
|
|
database. A loss of control over read-access to the database should have no security impact
|
|
on your deployment.
|
|
|
|
## SSL encryption
|
|
|
|
Since JupyterHub includes authentication and allows arbitrary code execution, you should not run
|
|
it without SSL (HTTPS). This will require you to obtain an official, trusted SSL certificate or
|
|
create a self-signed certificate. Once you have obtained and installed a key and certificate you
|
|
need to specify their locations in the configuration file as follows:
|
|
|
|
```python
|
|
c.JupyterHub.ssl_key = '/path/to/my.key'
|
|
c.JupyterHub.ssl_cert = '/path/to/my.cert'
|
|
```
|
|
|
|
It is also possible to use letsencrypt (https://letsencrypt.org/) to obtain
|
|
a free, trusted SSL certificate. If you run letsencrypt using the default
|
|
options, the needed configuration is (replace `mydomain.tld` by your fully
|
|
qualified domain name):
|
|
|
|
```python
|
|
c.JupyterHub.ssl_key = '/etc/letsencrypt/live/{mydomain.tld}/privkey.pem'
|
|
c.JupyterHub.ssl_cert = '/etc/letsencrypt/live/{mydomain.tld}/fullchain.pem'
|
|
```
|
|
|
|
If the fully qualified domain name (FQDN) is `example.com`, the following
|
|
would be the needed configuration:
|
|
|
|
```python
|
|
c.JupyterHub.ssl_key = '/etc/letsencrypt/live/example.com/privkey.pem'
|
|
c.JupyterHub.ssl_cert = '/etc/letsencrypt/live/example.com/fullchain.pem'
|
|
```
|
|
|
|
Some cert files also contain the key, in which case only the cert is needed. It is important that
|
|
these files be put in a secure location on your server, where they are not readable by regular
|
|
users.
|
|
|
|
Note on **chain certificates**: If you are using a chain certificate, see also
|
|
[chained certificate for SSL](troubleshooting.md#chained-certificates-for-ssl) in the JupyterHub troubleshooting FAQ).
|
|
|
|
Note: In certain cases, e.g. **behind SSL termination in nginx**, allowing no SSL
|
|
running on the hub may be desired.
|
|
|
|
## Cookie secret
|
|
|
|
The cookie secret is an encryption key, used to encrypt the browser cookies used for
|
|
authentication. If this value changes for the Hub, all single-user servers must also be restarted.
|
|
Normally, this value is stored in a file, the location of which can be specified in a config file
|
|
as follows:
|
|
|
|
```python
|
|
c.JupyterHub.cookie_secret_file = '/srv/jupyterhub/cookie_secret'
|
|
```
|
|
|
|
The content of this file should be 32 random bytes, encoded as hex.
|
|
An example would be to generate this file with:
|
|
|
|
```bash
|
|
openssl rand -hex 32 > /srv/jupyterhub/cookie_secret
|
|
```
|
|
|
|
In most deployments of JupyterHub, you should point this to a secure location on the file
|
|
system, such as `/srv/jupyterhub/cookie_secret`. If the cookie secret file doesn't exist when
|
|
the Hub starts, a new cookie secret is generated and stored in the file. The
|
|
file must not be readable by group or other or the server won't start.
|
|
The recommended permissions for the cookie secret file are 600 (owner-only rw).
|
|
|
|
|
|
If you would like to avoid the need for files, the value can be loaded in the Hub process from
|
|
the `JPY_COOKIE_SECRET` environment variable, which is a hex-encoded string. You
|
|
can set it this way:
|
|
|
|
```bash
|
|
export JPY_COOKIE_SECRET=`openssl rand -hex 32`
|
|
```
|
|
|
|
For security reasons, this environment variable should only be visible to the Hub.
|
|
If you set it dynamically as above, all users will be logged out each time the
|
|
Hub starts.
|
|
|
|
You can also set the cookie secret in the configuration file itself,`jupyterhub_config.py`,
|
|
as a binary string:
|
|
|
|
```python
|
|
c.JupyterHub.cookie_secret = bytes.fromhex('64 CHAR HEX STRING')
|
|
```
|
|
|
|
## Proxy authentication token
|
|
|
|
The Hub authenticates its requests to the Proxy using a secret token that
|
|
the Hub and Proxy agree upon. The value of this string should be a random
|
|
string (for example, generated by `openssl rand -hex 32`). You can pass
|
|
this value to the Hub and Proxy using either the `CONFIGPROXY_AUTH_TOKEN`
|
|
environment variable:
|
|
|
|
```bash
|
|
export CONFIGPROXY_AUTH_TOKEN=`openssl rand -hex 32`
|
|
```
|
|
|
|
This environment variable needs to be visible to the Hub and Proxy.
|
|
|
|
Or you can set the value in the configuration file, `jupyterhub_config.py`:
|
|
|
|
```python
|
|
c.JupyterHub.proxy_auth_token = '0bc02bede919e99a26de1e2a7a5aadfaf6228de836ec39a05a6c6942831d8fe5'
|
|
```
|
|
|
|
If you don't set the Proxy authentication token, the Hub will generate a random key itself, which
|
|
means that any time you restart the Hub you **must also restart the Proxy**. If the proxy is a
|
|
subprocess of the Hub, this should happen automatically (this is the default configuration).
|
|
|
|
Another time you must set the Proxy authentication token yourself is if
|
|
you want other services, such as [nbgrader](https://github.com/jupyter/nbgrader)
|
|
to also be able to connect to the Proxy.
|
|
|
|
## Security audits
|
|
|
|
We recommend that you do periodic reviews of your deployment's security. It's
|
|
good practice to keep JupyterHub, configurable-http-proxy, and nodejs
|
|
versions up to date.
|
|
|
|
A handy website for testing your deployment is
|
|
[Qualsys' SSL analyzer tool](https://www.ssllabs.com/ssltest/analyze.html).
|