Most if not all readers of my blog are probably aware of the Lets Encrypt project, which officially exited Beta this month.
For those of you not familiar with it, the basic premise is "It's the goddamn 21st century, and there is no reason every website shouldn't be available over HTTPS. We're giving away certificates for free, and giving you an automated tool to acquire and renew them. You have no more excuses!"
Most of you also know I was originally quite skeptical of this project: I'm not a huge fan of trusting third-party programs with my cryptography, and I like to ensure that I'm maintaining control of the impotant bits (like private keys) at all times. The final implementation however appears to be well-designed and reasonably secure, enough so that I have used it for this year's certificate renewal on bsd-box.net.
What follows is a brief description of the Lets Encrypt process on FreeBSD: Its successes, its failures, and some thiings I may be submitting patches for in the near future.
To start, this discussion only considers Lets Encrypt using the FreeBSD Port (available in ports/security/letsencrypt.sh/).
If you are using Lets Encrypt on FreeBSD I assume you are using the port. If you are not using the port I assume you have a really good reason, and that you don't need my opinion/notes as you are smart enough to evaluate the product on your own and sort out any issues you encounter.
While Lets Encrypt is designed to be used for web servers I also run an encrypted mail server (Courier IMAP/SSL & Sendmail SMTP/STARTTLS), so those will be considered as well.
Installation of the Lets Encrypt port is the same as any other port - change to the port directory and run make install ; Installation from packages will be similar (pkg install …).
The port installs example configuration files in /usr/local/etc/letsencrypt.sh ; these can be copied wholesale to their regular (non-.example) locations. The domains.txt file wil need to be modified for your site (each line represents a certificate, and is a whitespace-separated list of domain names to be listed on the certificate. It is not documented, but the format is presumably "MainName AlternativeName AlternativeName ...")
Getting Your Certificate
Lets Encrypt performs domain verification to ensure that you control the domain name you are requesting a certificate for. By default this is done over HTTP: A challenge is generated and placed on your web server, where the Lets Encrypt servers retrieve it to verify domain control.
The FreeBSD Lets Encrypt port places these challenges in /usr/local/etc/letsencrypt.sh/.acme-challenges by default, which is almost certainly not within the webroot directory for whatever HTTP server you are running, therefore you must either make a symbolic link to this directory from your webroot, use a <Location> directive, or add a hook to the letsencrypt.sh configuration to copy the files into place.
Pick your poison, but I recommend either the <Location> directive or the symbolic link.
Once you ensure your web server will correctly serve the challenge responses simply run the letsencrypt.sh script with the -c option and your certificates will be generated and issued.
Certificate data is placed in the /usr/local/etc/letsencrypt.sh/certs/ directory (a subdirectory is created for each main certificate name listed in domains.txt).
You will wind up with a private key, certificate, CSR, and certificate chain:
- cert.csr The Certificate Signing Request that was generated for you
- privkey.pem Your private key
- cert.pem Your signed certificate
- chain.pem The CA key which signed your certificate
- fullchain.pem The full CA chain for your certificate (lincluding your certificate)
These files are symbolic links to the most recently issued certificate, in a timestamped file (e.g. cert.pem will be a symbolic link to cert-1461684379.csr - marked with the epoch time the certificate was requested).
Installing Your Certificate
Most of you don't need to read this section because t's a certiicate, it installs like any other certificate.
Installation for Apache is relatively standard: Locate your Apache configuration file and enter the paths in the appropriate places (SSLCertificateFile is cert.pem, SSLCertificateKeyFile is privkey.pem, and SSLCertificateChainFile is chain.pem).
For those of us who are masochists and using sendmail with SSL/STARTTLS the configuration isn't that bad. As with Apache you can just drop them into your sendmail.mc file, rebuild sendmail.cf, and restart sendmail - it will Just Work.
Sendmail's confCACERT value is chain.pem (you can also use fullchain.pem but I've had issues with sendmail not loading more than one file out of the chain in the past, so I don't do that anymore). confSERVER_KEY and confCLIENT_KEY are both privkey.pem, and confSERVER_CERT / confCLIENT_CERT are cert.pem.
For those of you who have not developed Sendmail-induced Stockholm Syndrome I assume you can figure out which files go where in your mail server configuration files.
Courier IMAP is the only "difficult" configuration, as it expects a single PEM file containing both the certificate and key.
You will need to concatenate cert.pem and privkey.pem into a single file (I used combined.pem), and edit the imapd-ssl configuration file to set TLS_CERTFILE to point at the combined file.
The TLS_TRUSTCERTS parameter should be set to fullchain.pem (or to whatever store of trusted certificates you use, ensuring that it contains the Lets Encrypt chain).
If you have a business need for Extended Validation then Lets Encrypt is not the solution for you (but if you have such a business need you probably also have the budget to pay a commercial CA to issue your certificates).
The most glaring issue I found with the Lets Encrypt port is its lack of documentation: There is no man page.
There is a README file (installed as /usr/local/share/doc/letsencrypt.sh/README.md), but it leaves a bit to be desired. Time permitting I will probably hack together a man page for this utility.
The second major issue is that a combined Certificate+Key PEM file is not produced, and some software (*cough*Courier*cough*) requires it. Managing this manually defeats the purpose of the Lets Encrypt software, and I will be submitting a patch to automatically create a combined .PEM file.
The final issue is that there does not appear to be a way to quiet the output of this script in cron mode. I am one of those sysadmins who DESPISES email, so if there's nothing to report (no certificates issued/renewed) I would like the option to tell the script to shut the hell up and exit silently. Again, I expect I'll be submitting a patch for this in the near future.
I am genrally satisfied with the Lets Encrypt service, and feel confident recommending it for general/personal use, though as with any software I suggest you actually look at the code you're running (letsencrypt.sh is relatively transparent in what it does).
I would still recommend the use of a commercial Extended Validation certificate for some applications (in particular I don't think we'll be using it at my day job: As a medical company it's useful to be able to point users at the green URL bar), but for general-purpose "I want to encrypt my traffic without spending a fortune" use the certificates and level of assurance provided by Lets Encrypt should be more than adequate.