nginx &

I’ve started using Let’s Encrypt a lot, for all my domains in fact. Previously, I’ve been using letsencrypt-auto, and stopping my webserver every time I want to renew a certificate. This is probably fine (all the sites and domains I run are low traffic, and can afford to be down for 30s or so when certificates need renewing every few months), except a flaw in my process for renewing certificates meant I took my webserver down for 12 hours or so. Twice.

After reading a post which described various alternatives to letsencrypt-auto, I thought looked fairly good. It’s a bash script which takes a list of domains, and just talks to the Let’s Encrypt ACME server for me, by putting some files somewhere which my webserver could serve.

Installation is simple, if a little jarring1:

git clone

The next step was just ensuring that nginx would serve the ACME responses correctly.

All my sites have a configuration a little like this, to ensure all HTTP requests are redirected to HTTPS:

server {
  listen 80;

  location / {
    return 301$request_uri;

It’s this block – rather than the HTTPS block below, where I set up either WordPress or Django – which I need to modify, since the ACME client is going to talk over HTTP2.

All I needed to do (though figuring this out took me an embarrassingly long time) was add this, somewhere in the same server block:

location ^~ /.well-known/acme-challenge/ {
  default_type "text/plain";
  root /var/www/letsencrypt;

Then, I just needed to create /var/www/letsencrypt/.well-known/acme-challenge3. Once I’d done that, I could create a domains.txt file which just looks like this:

Then, all that’s needed to get my certificates generated is to run:

sudo /etc/ --cron

That’ll stick certificates in /etc/ (this assumes that that’s where you’ve put the bash script, file, and domains.txt, and you’ve broadly stuck with the defaults in the provided

As you’d expect, you can set that up to run regularly with crontab, and you’ll always have fresh SSL certificates for free.

  1.  I’d prefer not to install it with git, but it works
  2. It can’t talk over HTTPS, otherwise we’d have a bootstrapping problem, since we’re presumably using ACME to provision an SSL certificate, when one may or may not exist.
  3. This confused me for a really long time – I’d expect that the location block above would mean that a request to /.well-known/acme-challenge/foobar.html would look for /var/www/letsencrypt/foobar.html, but that turns out to be wrong – it looks for /var/www/letsencrypt/.well-known/acme-challenge/foobar.html.

One Comment

  1. Markus

    Just wanted to mention a few things:
    – the project has been renamed to “dehydrated” in the meantime (due to trademark problems)
    – the configuration file’s name is now ‘config’ (previously was
    – the default locations are /var/www/dehydrated and /etc/dehydrated now

Leave a Reply

Your email address will not be published. Required fields are marked *