Menu

SSL/TLS enabled websites with LetsEncrypt

Let's face it; in today's world, it's much easier to make a case for setting up SSL/TLS support on your website then to not. And no, Self-Signed certificates don't count. That's fine for your home router or one-man OwnCloud site, but if you care about the data being served up, get yourself some (properly signed) SSL certs!

The problem used to be that if you wanted SSL certs, you had to pay, sometimes a lot. Verisign/Symantec certs can start in the $400 range and go up from there. Conversely Comodo SSL certs start at $79.95. Now, we won't go into the "market topology" of why Verisign is more expensive than Comodo, but to some extent you get what you pay for.

LetsEncrypt aims to change that. They are currently (June2016) offering certificates for free (valid for 90 days). Period. This coalition (most notably backed by Mozilla, Cisco, EFF, and others) are aiming to put an SSL cert into the hands of anybody who wants one.

There will be a TLDRScript™ at the end of this, but keep in mind, the initial setup with certbot requires answering to interactive prompts, so you can't truly script it. Additionally, use that script with caution, it will add custom configs to your apache setup, and that may not be what you want, Caveat emptor.

Setup

Depending on which set of directions you follow from the letsencrypt website, the client (certbot-auto) might be able to obtain and install your certificate in one fell swoop, automatically. Depending on your web server setup and its complexity, that may be completely fine for you. In the setup below, we will have an Apache web server that will be acting both a traditional web server hosting up static content, as well as a reverse proxy for some other applications (maybe even a blog)! As usual, the following assumptions are made:

CentOS 7.latest (7.2.1511 at the time of writing)

Apache 2.4 (latest)

mod_ssl (latest)

Apache installed and running with typical vhost style configuration

SELinux enabled

FirewallD enabled

Getting the warez

First thing we need to do is download certbot-auto from EFF and put it in your path:

Laying down configs

From here, you'll need to lay down your Apache config and create the necessary directories. Take note that all of these commands/configs should be used on your forward most web server (proxy or otherwise), as that is the web server that will be providing the SSL connection to your clients. Let's make some directories:

The Alias statement sends any requests for the .well-known directory to a separate location, the same location we'll specify in the certbot-auto command. This allows you to not touch your web application and still have certbot work. Additionally, if you're trying to do this for a reverse proxied site, add the following to the config (near the proxy line):

ProxyPass /.well-known !

This will prevent apache from sending ACME protocol requests to your proxied site.

The RedirectMatch statements lets everything get redirected to your HTTPS site page except the .well-known directory, which the ACME protocol (used by certbot-auto) uses to put answers to the challenge-response queries. It is important to note, this directory must never get auto-redirected to an HTTPS site, with or without a valid SSL cert; the letsencrypt.org ACME server will barf and your cert creation/renewal will fail.

Note

The SSL portion of that config can be obtained from Mozilla's SSL configuration generator. They'll make best-practice recommendations on which ciphers to allow and which ones to omit. Want to verify your config? Head over to SSLLabs to test your website.

At this point, we should [re]start/enable Apache, and add some firewall exception:

Running certbot-auto

Let't get some certs! Note that the -auto version of the certbot script will automatically install any packages necessary for it to successfully run using your system's package manger (in our case YUM).

certbot-auto certonly --webroot -w /var/www/acme -d zeroent.net

If you want to get multiple domains covered by a single cert (with Subject Name Alternatives), you can use multiple -d arguments like so:

Note that the first specified domain will be the "primary" domain on the cert.

Once you run the certbot-auto command, it will go through requesting the certs, it will prompt you for an e-mail address to register them to so in the event that they need to contact you (certs coming close to expiring, need to be revoked, etc.), they have a means of contacting you. If you are setting this up in a production/enterprise environment, I'd recommend using an alias like [email protected] rather than [email protected]; nothing is more embarrassing than having your production SSL certs expire and not knowing it was going to happen.

Assuming everything goes successfully, you'll see a message like this

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/zeroent.net/fullchain.pem. Your cert
will expire on 2017-03-25. To obtain a new or tweaked version of
this certificate in the future, simply run certbot-auto again. To
non-interactively renew *all* of your certificates, run
"certbot-auto renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

Using the new certificates.

Now that you have the new certs, you need to get Apache to use them. Simply comment out the lines pointing to localhost and point to the new cert files created by certbot:

Certificate Renewal

Any process worth doing is worth automating, and that's just what we're going to do here. Because we're cool and use SystemD (instead of a cronjob), we'll lay down SystemD service and timer units that will check your certificates to determine if they need renewal, and if so, renew them. Note, by default, certbot renews the certs when they are 30 days from expiring. So if something goes wrong with automation, you have some breathing room to get your certs in order.

The service that executes the certbot - /etc/systemd/system/le-renew.service