Setup a New Self-Signed SSL Certificate on OctoPrint (“Enable HTTPS”)

Overview

In this tutorial, I will show you how to:

  • Create a new self-signed SSL certificate on your OctoPrint instance
  • Teach you how to forward any HTTP request to HTTPS (“forcing all connections to use HTTPS”)
  • How to have your PC/Mac/iOS device trust the certificate

Though this isn’t the right term, “Enabling HTTPS” can be a way of describing what we are doing here. OctoPrint comes with HTTPS enabled already and a default SSL certificate. We are just making updates to what already exists.

Apologies in advance, I'm a new user here and can't post screen shots in this post :slight_smile:

Disclaimer

I am NOT a security expert or security professional. This tutorial is not intended to setup a secure way to access your OctoPrint instance outside of your network. This is intended to only be used to secure in-network traffic to your OctoPrint instance. If you procced with this tutorial, you understand the risks and take full responsibility for any security risks/incidents that might occur.

Pre-Requisites

Before we get started this is what you will need

  • An instance of OctoPrint with SSH enabled or a way to access the command line

    • In my example I will be using OctoPi. I’m using a “dummy” OctoPi, so all usernames/passwords will be the default. I suggest setting up more secure passwords for better security
  • Luckily the tools we need, OpenSSL & HAProxy, come with OctoPi by default. This is how to check to make sure they are installed (run the following in the terminal). If these are not installed, a quick Google will show you how-to install them

openssl version
haproxy -v
  • Please make sure your OctoPi is updated. This is a simple command I run to ensure it’s up to date
sudo apt update && sudo apt dist-upgrade && sudo apt-get autoremove && sudo apt clean && sudo reboot now
  • Assign your OctoPi a static IP and note what that IP is (we need it later)

One Last Note Before We Start

  • Anywhere below I reference "octopi.local", you should use the local DNS entry your OctoPi uses (such as printer.customdomain).
    • Just using the IP and not a custom domain? No worries, though it may vary depending on your network, octopi.local is a common default

Lets get started already!

Create a Self-Signed SSL Certificate

  1. Connect to the terminal, and CD into the following folder
cd /etc/ssl

This folder is where the default .pem (snakeoil.pem) file OctoPi comes with is located. We will be storing all the SSL related items in here

  1. Generate a RSA private key
sudo openssl genrsa -out octopi.local.key 2048

This is needed to generate the certificate requests in the next steps

  1. Generate the certificate file (.cer)

MAKE SURE YOU ADD IN YOUR STATIC in place of "STATIC_IP"

sudo openssl req -new -x509 -sha256 -key octopi.local.key -out octopi.local.cer -days 365 -subj /CN=octopi.local -addext "subjectAltName = DNS.1:octopi.local, IP.1:STATIC_IP"

This creates the .cer file needed. It's important the DNS.1 & IP.1 values are correct for your environment. If these are off, your browser will see the difference and not trust the certificate.

  1. We need to concatenate the .key/.cer files and replace the contents of snakeoil.pem

Optional: You can go with a different name other than snakeoil.pem. I have found changing the name of this file can cause issues later, so I wouldn't recommend it.

For this step, we need to be running as the root account. Not sure why, but I get permision issues even if I run as sudo

sudo -i

Need to go back to the SSL folder

cd /etc/ssl

Concatenate the .cer/.key files

cat octopi.local.cer octopi.local.key > snakeoil.pem

Stop being the root account

exit

Yay! we have all the SSL files setup on the OctoPi. Next, lets modify HAProxy to force HTTP to be redirected to HTTPS

HAProxy - Forward all HTTP requests to HTTPS

  1. Open the haproxy.cfg file
sudo nano /etc/haproxy/haproxy.cfg
  1. Navigate to the row that says
option forwardfor except 127.0.0.1
  1. Under the line mention above add
redirect scheme https if !{ hdr(Host) -i 127.0.0.1 } !{ ssl_fc }

The final result should look like this

...

frontend public
        bind :::80 v4v6
        bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem
        option forwardfor except 127.0.0.1
        redirect scheme https if !{ hdr(Host) -i 127.0.0.1 } !{ ssl_fc }
        use_backend webcam if { path_beg /webcam/ }
        default_backend octoprint
...

The redirect sends any HTTP request to HTTPS, unless it is the localhost (127.0.0.1) connecting. This allows OctoDash or other local UI's to connect (they usually don't support HTTPS connections).

Optional: If you changed snakeoil.pem to a different name, make sure to change the reference above. Again I would avoid changing the name because that kept causing issues for me.

  1. Save (CTRL + O) & Exit (CTRL + X)

Just a few more steps before we are done with OctoPi

  1. Copy the octopi.local.cer file to a flash drive/shared folder/etc (personally I use scp).
    We need to use this file later to establish the trust between your other devices and OctoPi.

  2. Reboot your OctoPi

sudo reboot now

This is the command just to restart HAProxy if you need it. Any time you modify haproxy.cfg, you need to restart HAProxy or you OctoPi.

sudo systemctl restart haproxy

We are now done with OctoPi! Time to setup your devices to trust this self-signed SSL

Trust Self-Signed Certificate on Windows

  1. Have the octopi.local.cer file somewhere you can access it

  2. Open "Manage user certificates"

  3. Expand "Trusted Root Certification Authorities" > Right click on "Certificates" > "All Tasks" > "Import..."

  4. Click next on the first screen

  5. Select the .cer file > Next

  6. Next (leave defaults)

  7. Click "Finish "on the last screen

  8. Click "Yes" if you get a security warning

If you look at the certificate list, you should see a record called "octopi.local"

  1. Open a browser and test the following
Type in http://IP and/or DNS. Make sure it forwards to HTTPS
Type in https://IP and or DNS. Make sure the connection works

Your browser should show the connection is secured!

Trust Self-Signed Certificate on iOS

  1. Have the octopi.local.cer file somewhere you can access it

  2. Click on the file > Select the device you want to install it on (iPhone/iPad)

  3. Open Settings > Click on the "Profile Downloaded" Option

  4. Click on the Profile > Install

  5. Click Install (accept any security warnings that popup)

  6. Go to Setting > General > About > Certificate Trust Settings (all the way at the bottom)

  7. Turn on the octopi.local option (accept any security warnings)

  8. Open a browser and test the following

Type in http://IP and/or DNS. Make sure it forwards to HTTPS
Type in https://IP and or DNS. Make sure the connection works

Your browser should show the connection is secured!

Trust Self-Signed Certificate on MacOS

  1. Have the octopi.local.cer file somewhere you can access it

  2. Follow this guide Getting OS X to trust self-signed SSL certificates

  3. Open a browser and test the following

Type in http://IP and/or DNS. Make sure it forwards to HTTPS
Type in https://IP and or DNS. Make sure the connection works

Your results should show that accessing the site is Secure!

Trust Self-Signed Certificate on Android

I do not own an Android, but a quick Google search can get you there!

Trust Self-Signed Certificate on Linux

Quick Google search can get you there!

You have reached the end!
@jneilliii has a very cool tutorial on how to setup client certificates. Go check it out! I owe them credit too, their tutorial helped me figure out a few things :smiley:

Please comment any feedback or questions you might have

9 Likes

Nice post. You can take it a step further and use client certificates to further restrict access.

2 Likes

Thank you! I've come across your tutorial before, and owe you credit! Helped me figure out a few things making this one

1 Like

Updated the HAProxy setup to allow localhost (127.0.0.1) to connect via HTTP. Most local UIs (like OctoDash) don't support HTTPS.

I will admit, I'm slightly confused... OctoPi already ships with a self signed certificate and https enabled in haproxy.

1 Like

Yes! Thank you! I updated some wording to reflect that :smiley:

Still a useful tutorial for someone who might want to rotate their keys out.

True. I was just worried that the fact that this is already there was somehow overlooked :slight_smile:

Any way to revert to the default certs?

Not unless you backed up the files, if you overwrote the original files you won't be able to to. But this is the script that is run on initial boot to complete the process.

This may be a completely stupid question on my part, but why do you go through all the trouble and not just use the standard self signed certificates that comes with the OctoPi image?

There is a necessary section of haproxy.cfg missing from this guide. How did you configure the backend? what goes after backend octoprint.
...
backend octoprint
????

There are no changes required to the backend sections, SSL is all done on the front end.

Hi, I know this is probably old news, but I amended my haproxy.cfg line to remove support for the insecure TLS v1.0 (mainly to stop my network monitoring system alarming :-))

Just change this line in the frontend public section to add the no-tlsv10 at the end.

    bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem no-tlsv10

Hope it helps.

2 Likes

This was super helpful, thank you!

In case this helps others...

To copy the cert from the pi to your local computer:

scp pi@octopi.local:/etc/ssl/octopi.local.cer /etc/ssl/octopi.local.cer

To trust the cert on your Mac from the command line:

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /etc/ssl/octopi.local.cer
1 Like

Hey hey, so i know this guide's a little old, but im pretty sure it's still valid, anyway!

I have followed the steps in this guide but am getting an "ERR_SSL_PROTOCOL_ERROR"
Any ideas on what i'd be doing wrong?

One thing i wanted to double check
In the sudo openssl req -new -x509 -sha256 -key......
the "IP.1:...."
is that your devices static local IP address?
regardless i tried once with local IP and then public IP...
both still giving me the same error in the browser
image

Is there a way of getting a cert from another place like cloudflare or something similar?

Yes, it is possible to get a certificate from one of the authorities but an SSL certificate cannot be issued for Reserved IP addresses (RFC 1918 and RFC 4193 range)/ private IP addresses (IPv4, IPv6), Intranet for Internal Server Name, local server name with a non-public domain name suffix.

So if you had one of these certificates then your OctoPrint instance would be publicly accessible which is a bad idea.

It is possible to get around the public facing non-secure aspect of that by using your own internal DNS server. I do that now with with my pihole server and point the name to the internal private IP.

What certificate authority are you using?