Note: Self-Signed SSL Certificate for (local) JupyterHub


In this note I'll go through creating self-signed SSL certificates and adding them to a JupyterHub configuration. This will allow encrypted access to the server using https in a browser.

I've been working with JupyterHub for serving JupyterLab notebooks from a remote system. This recent post "Note: JupyterHub with JupyterLab Install using Conda" describes the JupyterHub install and configuration that I have been using. That multi-user configuration is working well and I have even gotten "docker" containers working with it along with the "single user notebook servers". The configuration is intended to be served on a LAN or over a VPN and was using un-encrypted http for access. That is OK with trusted users on a trusted network. However, it is preferable to encrypt all network traffic to a web browser.

For a system that is not using a registered public domain-name and ip address, adding SSL certificates to provide encryption can be accomplished using "self-signed" certificates. This is essentially being your own "Certificate Authority". These are perfectly good certificates and really no different than those issued by public CA's. But, web browsers do complain about them …

Web Browser software providers set their own requirements for certificates, CA/Browser Forums. Certificates that are not signed by a public CA (certificate authority) are flagged with warnings even when they are served on non-public networks (including localhost). This is an annoyance and requires you to click on something like "Advanced", "Accept the risk", etc.. However, after you have accepted the certificate into your browsers "trust store" you should not have to take any special action in the future.

SSL setup can be complicated. This post is not intended to be a complete guide! There is a good discussion at this Stack Overflow post.

This is a tricky problem! I would love to use a cert from Let's Encrypt for example, but, their documentation here suggests that what I've presented in this post may be the best solution for encrypting traffic to the server (on the users local network!).

I'm assuming;

1) JupyterHub server is on a reserved ip LAN (like, 192.168.x.x or 10.x.x.x) and accessed over LAN or VPN, (or possibly on the end users own machine i.e. localhost).

2) There is no FQDN for the server. Probably no DNS name resolution for the server at all.

I'm doing;

1) Generate and install new cert and key during install configuration of JupyterHub

2) First time users, connecting to the JupyterHub server will add/accept the cert into the "trust store" for the browser they use.

The directory paths and configuration files are as described in the post ["Note: JupyterHub with JupyterLab Install using Conda" .

Create SSL cert and key for using https to access JupyterHub

For what follows you need a version of openssl with version greater than or equal 1.1.1.

[You need to be root to make the following changes. You can get a root shell with "sudo -s"]


mkdir -p ${JHUB_HOME}/etc/jupyterhub/ssl-certs

cd ${JHUB_HOME}/etc/jupyterhub/ssl-certs

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes 
  -keyout jhubssl.key -out jhubssl.crt 
  -subj "/C=US/ST=Washington/L=Auburn/O=Puget Systems/OU=Labs/CN=Puget Systems Labs Self-Signed" 
  -addext "subjectAltName=DNS:localhost,DNS:localhost,IP:"

That generates the certificate and key. It is a x509 certificate valid for 10 years using 4096 bit encryption.

Edit the JupyterHub file to use the certificate and key

Search for,

#c.JupyterHub.ssl_cert = ''

#c.JupyterHub.ssl_key = ''



Un-comment and change those lines to point to the SSL cert and key.

c.JupyterHub.ssl_cert = '/opt/conda/envs/jupyterhub/etc/jupyterhub/ssl-certs/jhubssl.crt'

c.JupyterHub.ssl_key = '/opt/conda/envs/jupyterhub/etc/jupyterhub/ssl-certs/jhubssl.key'

Restart JupyterHub,

systemctl restart jupyterhub

You can now access JupyterHub at https://(address-for-jhub):8000 Traffic between your browser and the server will be encrypted.


SSL is complicated!

The most cryptic line in the openssl command I used, is

-subj "/C=US/ST=Washington/L=Auburn/O=Puget Systems/OU=Labs/CN=Puget Systems Labs Self-Signed"

These are answers to questions that openssl would ask in interactive mode (with "/" seperator). I used Puget System info here. You can use any info or even leave it out.

  • C = Country name. The two-letter ISO abbreviation.
  • ST= State or Province name.
  • L = Locality Name. The name of the city where you are located.
  • O = The full name of your organization.
  • OU= Organizational Unit.
  • CN= "Common Name".

In older versions CN would have been a fully qualified domaine name (FQDN). That is now added in the SAN (subjectAltName) field.


I just used localhost here since there is no FQDN for the system. You could also enter the LAN ip address for the server here if you like but it is not necessary.

Remember, when you first access the server using https your browser will complain. After you have the certificate in your browsers key-store that should stop.

Screen shots of browsers complaining;

(The certificate is valid but browsers don't like self-signed certs because they could be created by someone doing a "man in the middle" attack on a public network.)


Chrome SSL

click "Advanced",

click "Proceed to … (unsafe)"


click "Advanced"

"Accept the Risk and Continue"


click "Details"

"Go on to the webpage"

With my current configuration that takes you to something like, (yes I changed the JupyterHub login page CSS styles — why not!)

Note: There does appear to be built-in configuration options for JupyterHub that will have it generate it's own certificates and keys. I was able to get those to generate correctly but unable to access the server after doing so.

Happy computing! –dbk @dbkinghorn — Best wishes and stay safe!

CTA Image
Looking for a GPU Accelerated Workstation?

Puget Systems offers a range of powerful and reliable systems that are tailor-made for your unique workflow.

Configure a System!
CTA Image
Labs Consultation Service

Our Labs team is available to provide in-depth hardware recommendations based on your workflow.

Find Out More!

Why Choose Puget Systems?

gears icon

Built Specifically for You

Rather than getting a generic workstation, our systems are designed around your unique workflow and are optimized for the work you do every day.

people icon

We’re Here, Give Us a Call!

We make sure our representatives are as accessible as possible, by phone and email. At Puget Systems, you can actually talk to a real person!

delivery icon

Fast Build Times

By keeping inventory of our most popular parts, and maintaining a short supply line to parts we need, we are able to offer an industry-leading ship time.

repair icon

Lifetime Labor & Tech Support

Even when your parts warranty expires, we continue to answer your questions and even fix your computer with no labor costs.
Click here for even more reasons!