mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-17 15:03:02 +00:00
added example config with nginx reverse proxy
This commit is contained in:
@@ -128,6 +128,8 @@ Configuring only the main IP and port of JupyterHub should be sufficient for mos
|
|||||||
However, more customized scenarios may need additional networking details to
|
However, more customized scenarios may need additional networking details to
|
||||||
be configured.
|
be configured.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Configuring the Proxy's REST API communication IP address and port (optional)
|
### Configuring the Proxy's REST API communication IP address and port (optional)
|
||||||
The Hub service talks to the proxy via a REST API on a secondary port,
|
The Hub service talks to the proxy via a REST API on a secondary port,
|
||||||
whose network interface and port can be configured separately.
|
whose network interface and port can be configured separately.
|
||||||
@@ -390,7 +392,7 @@ It is recommended to put all of the files used by JupyterHub into standard UNIX
|
|||||||
* `/etc/jupyterhub` for all configuration files
|
* `/etc/jupyterhub` for all configuration files
|
||||||
* `/var/log` for log files
|
* `/var/log` for log files
|
||||||
|
|
||||||
## Example
|
## Example with GitHub OAuth
|
||||||
|
|
||||||
In the following example, we show a configuration files 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:
|
||||||
|
|
||||||
@@ -462,6 +464,120 @@ export CONFIGPROXY_AUTH_TOKEN=super-secret
|
|||||||
jupyterhub -f /path/to/aboveconfig.py
|
jupyterhub -f /path/to/aboveconfig.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Example with 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:
|
||||||
|
|
||||||
|
* 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/)
|
||||||
|
|
||||||
|
Let's start out with `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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# HTTP server to redirect all 80 traffic to SSL/HTTPS
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name HUB.DOMAIN.TLD;
|
||||||
|
|
||||||
|
# Tell all requests to port 80 to be 302 redirected to HTTPS
|
||||||
|
return 302 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTPS server to handle JupyterHub
|
||||||
|
server {
|
||||||
|
listen 443;
|
||||||
|
ssl on;
|
||||||
|
|
||||||
|
server_name HUB.DOMAIN.TLD;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/HUB.DOMAIN.TLD/fullchain.pem
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/HUB.DOMAIN.TLD/privkey.pem
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_dhparam /etc/ssl/certs/dhparam.pem;
|
||||||
|
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
|
||||||
|
ssl_session_timeout 1d;
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
add_header Strict-Transport-Security max-age=15768000;
|
||||||
|
|
||||||
|
# Managing literal requests to the JupyterHub front end
|
||||||
|
location / {
|
||||||
|
proxy_pass https://127.0.0.1:8000;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Managing WebHook/Socket requests between hub user servers and external proxy
|
||||||
|
location ~* /(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/? {
|
||||||
|
proxy_pass https://127.0.0.1:8000;
|
||||||
|
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
# WebSocket support
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Managing requests to verify letsencrypt host
|
||||||
|
location ~ /.well-known {
|
||||||
|
allow all;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`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 {
|
||||||
|
listen 80;
|
||||||
|
server_name NO_HUB.DOMAIN.TLD;
|
||||||
|
|
||||||
|
# Tell all requests to port 80 to be 302 redirected to HTTPS
|
||||||
|
return 302 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443;
|
||||||
|
ssl on;
|
||||||
|
|
||||||
|
# INSERT OTHER SSL PARAMETERS HERE AS ABOVE
|
||||||
|
|
||||||
|
# Set the appropriate root directory
|
||||||
|
root /var/www/html
|
||||||
|
|
||||||
|
# Set URI handling
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Managing requests to verify letsencrypt host
|
||||||
|
location ~ /.well-known {
|
||||||
|
allow all;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
# Further reading
|
# Further reading
|
||||||
|
|
||||||
- [Custom Authenticators](./authenticators.html)
|
- [Custom Authenticators](./authenticators.html)
|
||||||
|
Reference in New Issue
Block a user