/ Let's Encrypt from Start to Finish

Let's Encrypt From Start to Finish: First Steps

This is the second in a series of several posts on how to do way more than you really need to with Let's Encrypt, certbot, and a good server. I use all of these things regularly but I've never taken the time to take them apart, look at how they work, and spend hours in Google trying in vain to figure out how to put them back together. It was inspired by a disturbing trend of ISP privacy violations and the shocking regulatory capture of the US Federal Communications Commission.

This post is a catch-all for items that aren't closely related to the other major tasks. It begins with a list of very useful resources that provided a foundation for my research, followed by a general dependency list. Using certbot's docs, it presents two methods to get certbot up and running. It concludes with my approach to reusing Let's Encrypt and certbot config.

The Series so Far

  1. Overview
  2. First Steps
  3. Tuning with OpenSSL
  4. Useful Headers
  5. Generating and Testing a Cert
  6. Automating Renewals

Things that are still planned but probably not soon:

  • Updating OpenSSL
  • CSP Playground
  • Vagrant Examples (don't hold your breath)


You can view the code related to this post under the post-02-first-steps tag. If you're curious, you can also check out my first draft.


I'm testing out some new tooling. This will be wotw-highlighter's shakedown run. Let me know what you think about the syntax highlighting! I'm pretty excited because (no whammies) it should work well in AMP and normally.

Prototypical Resources

I've been shuffling around copypasta Let's Encrypt config since, I think, the middle of last year (the company's only 19 months old, so it couldn't have been much longer than that). I don't have VCS versions of any of that, so unfortunately I can't point to a single article or book that shaped this. This list deserves highlighting if for no other reason than I had the link saved and totally forgot where I was going to use it.

  • This Gist is a great resource to snag a stable config you can put almost anywhere.
  • This Gist is another great resouce. I believe I've had portions of it in production at some point.
  • Qualys SSL Labs is the SSL gold standard. If you don't have a good Qualys rating, you don't have a good config.
  • Mozilla provides a great generator that's probably responsible for a fair chunk of the articles out there now.


  • OpenSSL: This entire series is written around openssl usage. As far as I know, it's necessary for any of the common webservers. If you can't get OpenSSL, there's a really good chance you shouldn't be serving from your machine.
  • A web server:
    • Nginx: I'd recommend at least v1.12 if possible. I can't point to specific sources, but I remember reading something about that at some point during my research this weekend. It is almost a year old by now.
    • Apache: To follow a majority of the instructions I was able to find easily, you'll need at least v2.4 to access mod_socache_shmcb. The alternatives I remember were somehow even more opaque than shmcb, so I avoided them.
    • You're on your own with something else. You can most likely figure out what you need to know with these examples, your server's docs, and Google.


You can follow distro-specific instructions via the official docs for almost everything. The generic wget method usually provides the most current version; however, it's usually a better idea to wait for an official package.

$ wget https://dl.eff.org/certbot-auto
$ wget -N https://dl.eff.org/certbot-auto.asc
$ gpg2 --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2
$ gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc certbot-auto
$ chmod a+x ./certbot-auto
$ sudo mv ./certbot-auto /usr/bin/certbot-auto

Common Let's Encrypt Elements

Let's Encrypt works by creating challenges on the server and verifying them through an external request. To simplify things, it's a good idea to create a centralized location for everything. With one or two sites, it's not a huge deal; it's very nice the more sites your server supports.

Group and Directory Creation

I prefer the /srv directory over the /var directory, YMMV. Also exa isn't vanilla.

$ sudo groupadd letsencrypt
$ sudo mkdir -p /srv/www/letsencrypt/.well-known/acme-challenge
$ sudo chown -R :letsencrypt /srv/www/letsencrypt
$ sudo chmod -R g+rwx /srv/www/letsencrypt
$ exa --all --long --header --group-directories-first --group --time-style long-iso --tree /srv
Permissions Size User Group Date Modified Name
drwxr-xr-x@ - root root 2017-12-24 01:06 /srv
drwxr-xr-x - root root 2017-12-24 00:57 └── www
drwxrwxr-x - root letsencrypt 2017-12-24 01:41 └── letsencrypt
drwxrwxr-x - root letsencrypt 2017-12-24 01:37 └── .well-known
drwxrwxr-x - root letsencrypt 2017-12-24 00:57 └── acme-challenge

Share and Test Access

You can then add your server's service account to the letsencrypt group.

$ sudo usermod -G letsencrypt nginx
$ sudo usermod -G letsencrypt apache
$ sudo usermod -G letsencrypt safer_single_purpose_named_service_account

To make sure permissions work as intended, touch one of the new directories as the service account. You'll most likely need to specify a shell, as service accounts typically don't have login shells to limit outside access. If yours does expose a shell, you might think about changing that.

$ getent passwd nginx | cut -d ':' -f 7
$ sudo su -s /bin/bash -c "touch /srv/www/letsencrypt/.well-known" good_service_account || echo "whoops"
$ sudo su -s /bin/bash -c "touch /srv/www/letsencrypt/.well-known" bad_service_account || echo "whoops"
touch: setting times of '/srv/www/letsencrypt/.well-known/': Permission denied

Reuse Location

We'll also want to save a snippet exposing this structure.

I use /etc/<server>/common/ for my shared config, YMMV.


This is just a simple location block.

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

I've got at least three servers running a variant of this right now.


From the Let's Encrypt forums,

Alias /.well-known/acme-challenge/ /srv/www/letsencrypt/.well-known/acme-challenge/
<Directory "/srv/www/letsencrypt/.well-known/acme-challenge/">
Options None
AllowOverride None
ForceType text/plain
RedirectMatch 404 "^(?!/\.well-known/acme-challenge/[\w-]{43}$)"

I have not tested this.

Before You Go

Let's Encrypt is a fantastic service. If you like what they do, i.e. appreciate how accessible they've made secure web traffic, please donate. EFF's certbot is what powers my site (and basically anything I work on these days); consider buying them a beer (it's really just a donate link but you catch my drift).

Legal Stuff

I'm still pretty new to the whole CYA legal thing. I really like everything I've covered here, and I've done my best to respect individual legal policies. If I screwed something up, please send me an email ASAP so I can fix it.

  • The Electronic Frontier Foundation and certbot are covered by EFF's generous copyright. As far as I know, it's all under CC BY 3.0 US. I made a few minor tweaks to build the banner image but tried to respect the trademark. I don't know who the certbot logo artist is but I really wish I did because it's a fantastic piece of art.
  • Let's Encrypt is trademarked. Its logo uses CC BY-NC 4.0. I made a few minor tweaks to build the banner image but tried to respect the trademark.
  • I didn't find anything definitive (other than EULAs) covering Nginx, which doesn't mean it doesn't exist. Assets were taken from its press page.
  • Apache content was sourced from its press page. It provides a full trademark policy.

CJ Harries

I did a thing once. Change "blog." to "cj@" and you've got my email. All these opinions are mine and might not be shared by clients or employers.

Read More