Secure Your Lab
The following instructions will allow the use fo HTTPS in your lab address.
Navigate to the AWS Console. Go to the Security Groups settings and select your instance. Edit the inbound rules to include HTTP and HTTPS, then save.

sudo -iCreate a DH parameter for OpenSSL:
openssl dhparam -out /etc/jupyterhub/dhparam.pem 2048Change access to the system administrator only:
chmod 600 /etc/jupyterhub/dhparam.pemLink this file to the system folder:
ln -s /etc/jupyterhub/dhparam.pem /etc/ssl/certs/dhparam.pemInstall Certbot:
apt update
apt install software-properties-common
add-apt-repository universe
apt update
apt install certbot python3-certbot-nginxGenerate an SSL Certificate using Certbot:
certbot certonly --nginxYou will be prompted to enter an email and a domain (the newly added custom domain, for example: "YOUR-DOMAIN")
You should see:
Congratulations! Your certificate and chain have been sav /etc/letsencrypt/live/YOUR-DOMAIN/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/YOUR-DOMAIN/privkey.pem
Install nginx to set up a reverse proxy, so you do not have to type ":8000" at the end of the URL:
apt install nginxCreate a configuration file for nginx:
nano /etc/nginx/sites-available/jupyterhub.confCopy and paste the following code, based on Mozilla Configuration Generator, into this file. Be careful to modify the text to include your domain wherever "YOUR-DOMAIN" is present.
# top-level http config for websocket headers
# If Upgrade is defined, Connection = upgrade
# If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP server to redirect all 80 traffic to SSL/HTTPS
server {
listen 80;
listen [::]:80;
server_name YOUR-DOMAIN;
# 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 http2;
listen [::]:443 ssl http2;
server_name YOUR-DOMAIN;
client_max_body_size 0;
ssl_certificate /etc/letsencrypt/live/YOUR-DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUR-DOMAIN/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
#add_header Strict-Transport-Security max-age=1576800;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# Managing literal requests to the JupyterHub front end
location / {
proxy_pass http://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 headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# Managing requests to verify letsencrypt host
location ~ /.well-known {
allow all;
}
}Use CTRL+O then enter to overwrite the document and CTRL+X to exit.
Unlink the existing default file:
unlink /etc/nginx/sites-enabled/defaultLink the new nginx file for JupyterHub:
ln -s /etc/nginx/sites-available/jupyterhub.conf /etc/nginx/sites-enabled/jupyterhub.confStart nginx:
systemctl start nginx.serviceEdit JupyterHub configuration file:
nano /etc/jupyterhub/jupyterhub_config.pyAdd the following to force JupyterHub to only listen to local connections (127.0.0.1):
c.JupyterHub.bind_url = 'http://127.0.0.1:8000'Use CTRL+O then enter to overwrite the document and CTRL+X to exit.
Restart nginx and JupyterHub:
systemctl restart jupyterhub.service
systemctl restart nginx.serviceLast updated