mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-09 19:13:03 +00:00
177 lines
6.0 KiB
ReStructuredText
177 lines
6.0 KiB
ReStructuredText
Security basics
|
|
===============
|
|
|
|
.. important::
|
|
|
|
You should not run JupyterHub without SSL encryption on a public network.
|
|
|
|
Security is the most important aspect of configuring Jupyter. Three
|
|
configuration settings and one best practice are the main aspects of security
|
|
configuration:
|
|
|
|
1. :ref:`SSL encryption <ssl-encryption>` (to enable HTTPS)
|
|
2. :ref:`Cookie secret <cookie-secret>` (a key for encrypting browser cookies)
|
|
3. Proxy :ref:`authentication token <authentication-token>` (used for the Hub and
|
|
other services to authenticate to the Proxy)
|
|
4. Periodic :ref:`security audits <security-audits>`
|
|
|
|
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:
|
|
|
|
Enabling SSL encryption
|
|
-----------------------
|
|
|
|
Since JupyterHub includes authentication and allows arbitrary code execution,
|
|
you should not run it without SSL (HTTPS).
|
|
|
|
Using an SSL certificate
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
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:
|
|
|
|
.. code-block:: python
|
|
|
|
c.JupyterHub.ssl_key = '/path/to/my.key'
|
|
c.JupyterHub.ssl_cert = '/path/to/my.cert'
|
|
|
|
|
|
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.
|
|
|
|
If you are using a **chain certificate**, see also chained certificate for SSL
|
|
in the JupyterHub `troubleshooting FAQ <troubleshooting>`_.
|
|
|
|
Using letsencrypt
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
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):
|
|
|
|
.. code-block:: 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:
|
|
|
|
.. code-block:: python
|
|
|
|
c.JupyterHub.ssl_key = '/etc/letsencrypt/live/example.com/privkey.pem'
|
|
c.JupyterHub.ssl_cert = '/etc/letsencrypt/live/example.com/fullchain.pem'
|
|
|
|
|
|
If SSL termination happens outside of the Hub
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In certain cases, e.g. behind `SSL termination in NGINX <https://www.nginx.com/resources/admin-guide/nginx-ssl-termination/>`_,
|
|
allowing no SSL running on the hub may be the desired configuration option.
|
|
|
|
.. _cookie-secret:
|
|
|
|
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:
|
|
|
|
.. code-block:: 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:
|
|
|
|
.. code-block:: 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:
|
|
|
|
.. code-block:: 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:
|
|
|
|
.. code-block:: python
|
|
|
|
c.JupyterHub.cookie_secret = bytes.fromhex('64 CHAR HEX STRING')
|
|
|
|
|
|
.. _authentication-token:
|
|
|
|
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:
|
|
|
|
.. code-block:: 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``:
|
|
|
|
.. code-block:: 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:
|
|
|
|
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>`_.
|