As you may be aware, I’m hosting this blog on my raspberry pi3 at home. It’s got a dynamic dns thanks to duckdns.org, and now I would like to set it up with an SSL certificate so I can serve it via https.

I’m running debian jessie and I’m using nginx as my web server. I suggest you do too if you want to follow this blog post.

We will need to set up the dns management for the domain name. I’m using namecheap to provide my domain.

I’ve set up two cname records, for my domain, in my last post, so now we can continue.

Before we can setup an SSL certificate, we need to allow access to our web server for the authorisation test:

ssh pi@<your-pis-ip-address>
sudo vi /etc/nginx/sites-available/<your-blogs-config>

and the following under the port 80 server:

location ~ /.well-known {
        allow all;
}

Mine now looks like this:

server {
    listen   80;
    server_name tinklr.net www.tinklr.net;
    root /usr/share/nginx/html;

    location / {
            return 301 https://$host$request_uri;
    }
    location ~ /.well-known {
            allow all;
    }
}

This will allow lets encrypt to put a set of test files into your webroot, and then confirm that it can access them.

N.B. I’m running debian jessie, if you’re running something else (i.e. wheezy), you will need to follow different instructions. See https://certbot.eff.org for more information.

02

Connect to your pi vi SSH and then add deb http://ftp.debian.org/debian jessie-backports main to the bottom of the file /etc/apt/sources.list.d/raspi.list

My file now looks like this:

deb http://archive.raspberrypi.org/debian/ jessie main ui
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://archive.raspberrypi.org/debian/ jessie main ui
deb http://ftp.debian.org/debian jessie-backports main

Once this line is added continue with the following:

sudo apt-get update
sudo apt-get install certbot -t jessie-backports

After this completes, we should have everything we need.

sudo certbot certonly

This may take some time if it’s the first time you’ve run it.

When asked, select “enter webroot” to perform the check. then enter your webroot. In my case it’s:

/usr/share/nginx/html

You will be asked to confirm by typing the number at the side of the webroot. After this you will hopefully complete without failures and you should see the location of your new certificate printed in the terminal. it should end with “fullchain.pem”. Copy the whole path so we can add it to our nginx config we created earlier. Mine now looks like this:

server {
    listen   80;
    server_name tinklr.net www.tinklr.net;
    root /usr/share/nginx/html;

    location / {
            return 301 https://$host$request_uri;
    }
    location ~ /.well-known {
            allow all;
    }
}

server {
        listen 443 ssl;
        server_name tinklr.net www.tinklr.net;
        root /usr/share/nginx/html/_site;
        ssl_certificate /etc/letsencrypt/live/tinklr.net/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/tinklr.net/privkey.pem;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        index index.html index.htm;

        location / {
                try_files $uri $uri/ /index.html;
        }
}

I have set the http requests to be forwarded to https and I have also added the fullchain.pem and the privkey.pem to the setup. In addition, I have changed the root of the https handler to point at the root location of the hosted blog. I have left the port 80 root pointing at the main nginx location. This will allow the renewal for the cert to run.

Now we can write quit this config and restart nginx.

sudo service nginx restart

Now I can test the domain and see that tinklr.net forwards to the https fully secured certificate version from nginx.

03

These certificates last for 90 days. You can set up a cron job to update them by adding the following line to your crontab but firstly you’ll want to check your renewal process:

sudo certbot-auto renew --dry-run

You may see some errors from this that you’ll have to fix. Essentially you need to allow letsencrypt read from your nginx root under the directory “.well-known/”. The additional line that we put in at the start should allow this, but you may have a different setup that stops this from happening.

Once this is completed, we can add the following line to our crontab:

17 0 * * 3  ./home/pi/certbot-auto renew --quiet --no-self-upgrade --post-hook "sudo service nginx restart"

This command will quietly check to see if a new certificate is required (i.e. any running out soon) at 17 minutes past midnight every Wednesday. If there is a certificate to renew it will do so and then restart nginx.

I usually do this by using vi but I believe crontab defaults to gedit. You can change this (temporarily I might add) to vi by using the following command:

export EDITOR=vi

04

So, that’s a free ssl certificate that will update itself, with a blog hosted on a pi3. As always, this is ok whilst there’s not much traffic. If it picks up significantly, I would have to move the site. For now, I see that as a nice problem to have as I currently have ads on the site.

Tutorial video: