Free and easy SSL with Let's Encrypt

Published 2018-08-12 on Yaroslav's weblog

This text is also available in other languages: Español Русский

We all know that in this day and age security is an important factor when developing sites, and not only. Also let's not forget about that sweet Google SEO which rewards sites which use https instead of the old http (Although I couldn't care less about Google, however some people I might work with do, and I bet most of you reading also care).

You might want to add SSL to your site, but, you might think, those SSL certs cost money, and they ain't exactly cheap. And that's where you are wrong my friend (unless you already knew about Let's Encrypt and are only reading this to learn how to generate a certificate, in that case I apologize for the cringe introduction).

Here I will be detailing the steps to acquire an SSL certificate with Let's Encrypt using Certbot, with nginx. I will be installing Certbot on a Debian Stretch server, so you might need to input a different command depending on the distro or OS you are using.

First we need to install Certbot

# apt-get install certbot

Before we can install the certificates, we need to configure nginx for certficate installation and renewal. We can set the default server configuration on nginx for that. We need to do this so that Let's Encrypt's server can read the challenge generated by Certbot and verify that we indeed own the domain(s) for which we want to make the certificate.

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name _;

        # This is so that Let's Encrypt can look for the challenge
        location /.well-known/acme-challenge/ {
                root /var/www/html/;
                default_type text/plain;
        }

        # The rest of your configuration...
}

Once we have edited the default configuration file, we need to restart nginx.

# sudo systemctl restart nginx

After that we can get started installing the certificate. I wanted to get a certificate for more than subdomain, so I added them using the -d flag to my list of arguments like in the following example

# certbot certonly --webroot -w /var/www/html -d www.example.com -d example.com

It will ask your email for renew notifications, although certbot should renew your certificates automatically before expiration.

That's it, you should already have the new certificate and keys on your server. Now you can go ahead and configure nginx to accept https connections and redirect plain old insecure http requests to https. You should also put the correct path for your certificate and public key under ssl_certificate and ssl_certificate_key respectively.

server {
        listen 80;
        listen [::]:80;
        server_name www.example.com;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl;

        server_name www.example.com;
        ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
        ssl_certificate_key /path/to/key/www.example.com/privkey.pem;
        location /static/ {
                alias /home/webuser/mysite/static/;
        }
        location /media/ {
                alias /home/webuser/mysite/media/;
        }
        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://127.0.0.1:8001;
        }
}

The downside of automatically redirecting http requests to https is that old browsers that don't support https won't be able to open your site. But come on, it's 2018, who cares about 10+ year old software. Even if you are running really old hardware there definitely is some modern free software that runs on that hardware.

For more information on Certbot: https://certbot.eff.org/docs/using.html

Update (2018/11/02): Sometime in 2018 Let's Encrypt added the possibility to generate a wildcard SSL certificate (e.g. *.example.com).

To generate such a certificate we will need to download certbot from the git repository

$ git clone https://github.com/certbot/certbot.git

Then we cd into certbot and run

$ ./certbot-auto certonly --manual \
> --preferred-challenges=dns \
> --email email@example.com \
> --server https://acme-v02.api.letsencrypt.org/directory \
> --agree-tos \
> -d *.example.com

For this you will need to add a TXT record to the DNS settings of your domain, since this only works using the dns challenge. Before pressing enter make sure that your record has been deployed.

Do keep in mind that it's not currently possible to renew this kind of certificate automatically.

© 2018—2024 Yaroslav de la Peña Smirnov.