negative zero

Getting a TLS Certificate with Certbot

2019 August 10

[security] [tech] [tls] [tutorial]


Certbot is the EFF's tool for getting free (gratis) TLS certificates signed by the Let's Encrypt certificate authority, so you can secure the connection between your server and clients that connect to it. Certbot is free to use, and its components are licensed under either Apache 2.0 or MIT Expat free software licenses.

This guide assumes the following:

  1. You are planning to generate the certificate(s) on the same server where they will be used.
  2. You do not need a wildcard certificate.[1]
  3. It is possible to bind to your server at your domain(s) on port 80.

If any of these conditions cannot be satisfied, you must use a DNS challenge instead.

This guide will also assume you're using a SystemD-based server operating system.

This guide uses the Apache webserver on Fedora (where it's called httpd), but you can use whatever webserver you want. Just replace httpd in the systemctl commands with your webserver.)

In this guide, we will be generating a cert for example.com, as well as a few subdomains: sd1.example.com, and sd2.example.com. Replace example.com with your own domain.


1. Setup

Certbot needs to be able to bind to our server on port 80. This means we need to have port forwarding set up. Different routers will have different procedures for this, but basically you need to set your router to send incoming connections on port 80 to the local IP address of your server.

It also means you need DNS records for all the domains you will be generating certificates for, pointing to your server. (CNAME records are fine for subdomains.)

It also means we can't be running a conflicting server on that port. In my case, this means stopping Apache from running:

sudo systemctl stop httpd

You need Let's Encrypt's Certbot tool. You may be able to install it from your operating system's package manager.

For Fedora:

sudo dnf install certbot

For Debian:

sudo apt-get install certbot

See the Certbot instructions for other operating systems or download it from GitHub if it is unavailable from your package manager.


2. Generating the Certificates

There are a few methods that can be used to generate certificates with Certbot, but I like to use the following:

sudo certbot certonly --standalone --rsa-key-size 4096 -d example.com

We need to run this command with sudo. The certificate will be accessible only as root.

Certbot has a few options for how to generate the certificates, which can be used to automatically apply the certificate for a webserver like Apache or Nginx. In this case, we're using the certonly option to just generate a certificate, not apply it. You may prefer to take advantage of this feature.

We'll use the --standalone option, which will bind to your server on port 80.

Default RSA key length is 2048. We're specifying --rsa-key-size 4096 because why not make it stronger?

Next, we use -d example.com to specify which domain(s) this certificate should be used for. You can optionally generate a certificate that covers multiple by just adding more -d options. For example, if we want to make a single certificate for example.com, sd1.example.com, and sd2.example.com, we can do this with:

sudo certbot certonly --standalone --rsa-key-size 4096 -d example.com, -d sd1.example.com -d sd2.example.com

Note, however, that you cannot generate a wildcard certificate this way. This only works for a finite number of explicit domains.

Your certificate will be stored in /etc/letsencrypt/live/example.com/. (Notably, if you generate a single certificate that covers multiple domains, "example.com" will be the first domain you specify.)


3. Renewing the Certificates

After generating the certificates the first time, you can renew them by running:

sudo certbot renew

This will check all your certificates to see if they need to be renewed, and if they do, it will attempt to do so. In order for the --standalone method to be used, you must be able to bind on port 80, so be sure to stop a webserver or other servers blocking that port.

This process can be automated with systemd. We need to use appropriate hooks so it can run properly. For me (using an Apache server), this means stopping the server before running Certbot, and restarting the server afterwards. I also have some additional commands to copy the new certificates, and so on.

Put things in /etc/letsencrypt/renewal-hooks/pre/ that should be done before renewing the certificates:

sudo nano /etc/letsencrypt/renewal-hooks/pre/pre

#!/bin/sh
systemctl stop httpd
# other commands go here

and put things in /etc/letsencrypt/renewal-hooks/post/ that should be done afterwards:

sudo nano /etc/letsencrypt/renewal-hooks/post/post

#!/bin/sh
systemctl restart httpd
# other commands go here

Make sure these files are executable.

sudo chmod 750 /etc/letsencrypt/renewal-hooks/pre/pre

sudo chmod 750 /etc/letsencrypt/renewal-hooks/post/post

Here, we're stopping Apache before renewing the certs, and restarting if after. You might also need to copy the certificate for a domain or subdomain to another place so it can be used by some other process. For example, I have Prosody import my TLS certs by including the line

prosodyctl --root cert import /etc/letsencrypt/live

in my /etc/letsencrypt/renewal-hooks/post/post file.

Now, we need a timer to run this service periodically.

To enable the timer on Fedora:

sudo systemctl enable certbot-renew.timer

To enable the timer on Debian:

sudo systemctl enable certbot.timer

Other distros may use different names for the systemd timer.

Now, the timer will run automatically when the device starts up. You probably also want to start it running now.

To run the timer this time on Fedora:

sudo systemctl start certbot-renew.timer

To run the timer this time on Debian:

sudo systemctl start certbot.timer

Again, go with your distro's name for the systemd timer.