Adding SSL (TLS) in 5 steps to your raspberry pi website

Hello, fellow reader!

I want to cover today a topic that I thought I would only cover in the following months. The topic – as the title of this post suggests – is how to add SSL to your website. SSL stands for Secure Sockets Layer and TLS stands for Transport Secure Sockets. The technology that used to be used was SSL, nowadays though TLS is used, but since the term SSL was so popular, it still remains today. I will cover quickly what this is and then later I will explain how to quickly add this security to your website.

Brief explanation

TLS is the protocol where it establishes a secure connection between two points (in our case server and client). A secure connection here is a connection where the message is encrypted by one endpoint and can only be decrypted by the other endpoint. The first encrypting is done by applying a cryptography method known as asymmetric cryptography and later a symmetric cryptography. Because of the asymmetric cryptography, this whole process requires a public and a private key both generated with RSA. A public key as the name suggest is available to the public and the private key is… well, private. 🙂

The public key will be available in the certificate which your website will use, thus everyone will have access to it. The certificate is also known as “digital certificate” (X.509). The certificate contains other kind of information such as your domain name, for example. This certificate is usually signed by a CA (certificate authority). You can sign the certificate yourself, but the user’s browser will probably warn that your website is not secure, because there is no proof that the public key is authentic (not replaced by some one). Anyone can encrypt a message using the public key, but one can only decrypt the message using the corresponded private key.

You can check here the list of CA from mozilla.

Picking the digital certificate

For my website I’m not signing the certificate myself, because I don’t want users to think it’s not secure. If my site was only for my access I think I’d try to use open ssl and generate a certificate for myself. Letsencrypt is CA that makes the process fairly easy and free. All you have to do is to follow the instructions from their website. I will put the instructions I followed here along with other steps I also took. Letsencrypt has a client to generate the certificate which is really easy to use called Certbot.

Step1 – Generate commands

Certbot asks what kind of software and system I’m using on my server in order to provide further instructions. I put NGINX and Debian 9 (Stretch) respectively.

Unfortunately, for Debian 9 an automated way hasn’t been created yet like there has for certain systems, but it’s fairly easy to add the certificate with certbot.

Step 2 – Install certbot

sudo apt-get update
sudo apt-get install certbot

Step 3 – Setting up NGINX to be tested against the ACME challenge

Certbot will add some files inside a path .well-known/acme-challenge/. This way it can assure the DNS you are saying it’s yours really belongs to you. I created the path /etc/letsencrypt and /etc/nginx/letsencrypt. The former path will be the place where the files will be inserted by certbot, while the latter will contain our config file.

sudo mkdir /var/www/letsencrypt
sudo mkdir /etc/nginx/letsencrypt

Then I created the following config file named letsencrypt-acme-challenge.conf under /etc/nginx/snippets:

location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root         /var/www/letsencrypt;

Now I can reference to this snippet inside my website file or any other file I need to use SSL. I just have to include in the config file. Example:

# /etc/nginx/sites-available/blog
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/blog;

    include /etc/nginx/snippets/letsencrypt-acme-challenge.conf;

Reload your config files with sudo nginx -s reload. Now all we have to do is run the test command, answer the question regarding what email they should use to contact us for emergency and agree with their terms.

sudo certbot certonly --webroot -w /var/www/letsencrypt -d -d

Step 4 – Adding the certificate to our website

Now we need to add to our server the ability to listen to port 443 on NGINX and use our certificate. Port 443 is the standard for HTTPS which is HTTP secured by SSL. I used part of this great article from Digital Ocean as a guide to add the certificate to my server. You can check the article here.

To make things easier to manage we can separate the configuration files that contain information about the certificates and include them in the config file of our server. Now in the file named /etc/nginx/snippets/

ssl_certificate /etc/letsencrypt/live/;
ssl_certificate_key /etc/letsencrypt/live/;

Then, you create a file that contains a general config for SSL sites /etc/nginx/snippets/ssl-params.conf

# from
# and

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

# uncomment this if you use step 6
#ssl_dhparam /etc/ssl/certs/dhparam.pem;

Finally, we add the previous two files in our server configuration file.

// redirect income traffic on HTTP to our HTTPS server 
server { 
    listen 80 default_server;
    listen [::]:80 default_server;
    return 301 https://$server_name$request_uri;
// listen to port 443 and uses the certificate there 
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    include snippets/;
    include snippets/ssl-params.conf;

Step 5 – Enable port forwarding/disable firewall

This step depends where and how you are hosting your server. I’m hosting in a little raspberry pi, so all I had to do was enable port forwarding to port 443. You can check this step on my previous post on how to host your own webserver.

You want to enable this time port 443 and port 80 (to allow the redirects). Almost there! Reload your NGINX with the old sudo nginx -s reload and we are done! After that you should be able to see your server with a nice HTTPS symbol near your url! 🙂

Step 6 – Optional

Well, we are ‘done’, but not really… If you want to enhance the security of your encryption you can use dhparam to pre-generate some large prime numbers (this is used in the exchanged key between user/server).

This command can take a while (almost two hours on a raspberry pi 2, 15 min on the model 3)

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

You can change the value 2048 to a lower or higher value. 4096 can take almost a whole day, but it’s more secure. 1024 takes a few minutes, but it’s not recommended.

Make sure you uncomment the last line in the file ssl-params.conf to use this.

That’s it, folks! Hope you were successful!


Leave a Reply

Your email address will not be published. Required fields are marked *