diff --git a/docs/source/changelog.md b/docs/source/changelog.md index 797cf08e..8c397bd7 100644 --- a/docs/source/changelog.md +++ b/docs/source/changelog.md @@ -2,6 +2,12 @@ See `git log` for a more detailed summary. +## 0.5 + +- Single-user server must be run with Jupyter Notebook ≥ 4.0 +- Require `--no-ssl` confirmation to allow the Hub to be run without SSL (e.g. behind SSL termination in nginx) + + ## 0.4 ### 0.4.1 diff --git a/jupyterhub/app.py b/jupyterhub/app.py index bcecdae0..7bc1687e 100644 --- a/jupyterhub/app.py +++ b/jupyterhub/app.py @@ -87,6 +87,9 @@ flags = { 'no-db': ({'JupyterHub': {'db_url': 'sqlite:///:memory:'}}, "disable persisting state database to disk" ), + 'no-ssl': ({'JupyterHub': {'confirm_no_ssl': True}}, + "Allow JupyterHub to run without SSL (SSL termination should be happening elsewhere)." + ), } SECRET_BYTES = 2048 # the number of bytes to use when generating new secrets @@ -208,7 +211,12 @@ class JupyterHub(Application): def _template_paths_default(self): return [os.path.join(self.data_files_path, 'templates')] - + + confirm_no_ssl = Bool(False, config=True, + help="""Confirm that JupyterHub should be run without SSL. + This is **NOT RECOMMENDED** unless SSL termination is being handled by another layer. + """ + ) ssl_key = Unicode('', config=True, help="""Path to SSL key file for the public facing interface of the proxy @@ -800,6 +808,18 @@ class JupyterHub(Application): cmd.extend(['--ssl-key', self.ssl_key]) if self.ssl_cert: cmd.extend(['--ssl-cert', self.ssl_cert]) + # Require SSL to be used or `--no-ssl` to confirm no SSL on + if ' --ssl' not in ' '.join(cmd): + if self.confirm_no_ssl: + self.log.warning("Running JupyterHub without SSL." + " There better be SSL termination happening somewhere else...") + else: + self.log.error( + "Refusing to run JuptyterHub without SSL." + " If you are terminating SSL in another layer," + " pass --no-ssl to tell JupyterHub to allow the proxy to listen on HTTP." + ) + self.exit(1) self.log.info("Starting proxy @ %s", self.proxy.public_server.bind_url) self.log.debug("Proxy cmd: %s", cmd) try: diff --git a/jupyterhub/tests/mocking.py b/jupyterhub/tests/mocking.py index d2d5e8bb..0b77fc73 100644 --- a/jupyterhub/tests/mocking.py +++ b/jupyterhub/tests/mocking.py @@ -108,6 +108,7 @@ class MockHub(JupyterHub): """Hub with various mock bits""" db_file = None + confirm_no_ssl = True def _ip_default(self): return '127.0.0.1'