Snippet 0x0D: Let’s Encrypt – 5 min guide to set up cronjob based certificate renewal
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.
Content
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:
1 2 3 4 5 6 7 8 9 |
# 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ 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:
1 2 |
$ 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ 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:
1 2 3 4 5 6 7 8 9 10 |
$ 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:
1 2 |
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.
Hi Phillip,
I just wanted to say a quick thank you for producing this guide.
Really well written and super helpful for those, like me, who are experimenting with Lets Encrypt but don’t want to turn over full control of NGINX and/or Apache.
Just being able to fetch the certs and have them auto-renew is awesome.
Thanks again and Happy New Year!
Dave J
The link to the readme is broken (README.md instead of README.rst)
You may wish to check on your cronjob. This site is using an expired LE certificate… :-)
I love that this happened to me. Wasn’t actually the fault of my cronjob; I had moved to a new server and had forgotten to add the cronjob.