Snippet 0x0D: Let's Encrypt - 5 min guide to set up cronjob based certificate renewal

Contents

Let’s Encrypt was officially released to the open public today. That means the Internet can finally get free, trusted SSL/TLS certificates. This quick guide shows how to set up Let’s Encrypt with auto-renewal through a cronjob – using the simp_le client, an alternative client developed by one of the same authors who develop the official client.

Updates

Feb 2016: The new version of simp_le requires a -f account_key.json argument. I’ve updated the post accordingly.

Feb 2017: Unfortunately, the original simp_le project has been abandoned by the original author. This fork still works fine though. I have changed all the links, and it should just work.

1. Install the simp_le client

On your web server, clone the simp_le client and install it in a sensible directory (e.g. /opt/simp_le). Then run the installation steps as provided in the README.md:

Install client and symlink it

# Clone
$ cd /opt
$ git clone https://github.com/zenhack/simp_le/
$ cd simp_le

# Install
$ ./bootstrap.sh
$ ./venv.sh
$ ln -s $(pwd)/venv/bin/simp_le /usr/local/sbin/simp_le

2. Generate a keypair and retrieve signed certificate

Once the installation is done, everything else is super easy. All you need is a location for your keys and certificates, as well as the publicly available document root for your website. I store my certificates and keys in /srv/cert, with a subfolder for each domain, e.g. /srv/cert/example.com, and my document root is at /srv/www/example.com/html.

Create certificate signed by Let’s Encrypt

$ cd /srv/cert/example.com
$ simp_le \
  -d example.com:/srv/www/example.com/html \
  -f key.pem -f cert.pem -f fullchain.pem -f account_key.json

2015-12-04 01:31:52,131:INFO:simp_le:157: Creating new account key
2015-12-04 01:31:56,529:INFO:requests.packages.urllib3.connectionpool:756: Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
...
2015-12-04 01:31:58,568:INFO:requests.packages.urllib3.connectionpool:207: Starting new HTTP connection (1): example.com
2015-12-04 01:31:58,588:INFO:simp_le:803: example.com was successfully verified by the client
...
2015-12-04 01:32:04,570:INFO:simp_le:409: Saving key.pem
2015-12-04 01:32:04,570:INFO:simp_le:370: Saving fullchain.pem

This command automatically generates a keypair, creates a certificate request and gets that signed by Let’s Encrypt. It also verifies your domain ownership by creating a file in the document root at http://example.com/.well-known/.... So let’s look at the key and certificate:

Certificate and private key file

$ ls
account_key.json  cert.pem  fullchain.pem  key.pem

3. Configure your web server

Now configure the SSL/TLS certificate in your web server. For me, that’s Apache. The configuration for the virtual host looks like this:

Configuring the Apache virtual host

$ cat /etc/apache2/sites-enabled/example.com

<VirtualHost *:443>
        SSLEngine on
        SSLCertificateFile /srv/cert/example.com/cert.pem
        SSLCertificateKeyFile /srv/cert/example.com/key.pem
        SSLCertificateChainFile /srv/cert/example.com/fullchain.pem

        DocumentRoot "/silv/www/example.com/html"
        ServerName example.com

        // ...
</VirtualHost>

And finally, restart Apache with service apache2 restart and you can access your website via HTTPS! Easy, right?

4. Automating certificate renewal via cronjob

The wonderful thing about the simp_le client is that the command for the initial creation and the renewal is the same, so you can run the exact same command as above in a script from a cronjob. I created a script called /srv/bin/cert-renew to do just that:

Script to check/renew the certificates every night

$ cat /srv/bin/cert-renew 
#!/bin/bash

cd /srv/cert/example.com
simp_le -d example.com:/srv/www/example.com/html -f key.pem -f cert.pem -f fullchain.pem -f account_key.json \
	&& service apache2 reload

cd /srv/cert/example.xyz
simp_le -d example.xyz:/srv/www/example.xyz/html -f key.pem -f cert.pem -f fullchain.pem -f account_key.json \
	&& service apache2 reload

This will renew the certificates for two domains (if necessary) and reload Apache if the certificate has been renewed. Note that Apache will not be reloaded if the certificate has not been altered.

The matching cronjob looks like this:

Cronjob to run renewal script every night

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
43 1 * * * /srv/bin/cert-renew || true

That’s it! Now every night at 1:43am, your certificates are checked and renewed if necessary.

A. About this post

I’m trying a new section for my blog. I call it Code Snippets. It’ll be very short, code-focused posts of things I recently discovered or find fascinating or helpful. I hope this helps.