As promised a couple weeks ago, I’ve created a tutorial for automatically installing Let’s Encrypt certificates on Vesta-hosted sites. As you’ll recall, Let’s Encrypt is a new certificate authority that issues free domain validated (DV) certificates to virtually anyone in an effort to make the web more secure. Let’s Encrypt tries to be fully automated, meaning that you just run a single command on your server and it takes care of all the details of certificate issuance for you: creating the private key and CSR, validating domain ownership, generating the cert, and even configuring the web server for you. Unfortunately, Let’s Encrypt and Vesta use different naming conventions for the certificate files, so the two don’t automatically play nice together. Thanks to Vesta’s command-line tools, however, it is pretty easy to bridge the gap.
TL;DR version: I’ve created a tool, which I’ve posted to GitHub, that automates the Let’s Encrypt certificate request and installation process using the Let’s Encrypt ACME client and Vesta’s command-line tools. You can clone my repository and get to work installing certs on your server.
You should be logged in a root to complete this tutorial.
The Let’s Encrypt client requires Python 2.7, which is not installed on CentOS 6.x by default. Simply upgrading Python will break several system utilities, like yum, so we’ll start by installing Python 2.7 in an alternate location. If you’re using a distro that includes Python 2.7, or you already have it installed, you can skip the next several steps.
First, using yum, install the development tools and libraries we’ll need to build Python from source.
yum groupinstall "Development tools"
yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
Download the latest version of the Python 2.7 branch (2.7.11 as of this writing, but check http://python.org/downloads/ and update the version numbers as appropriate.
Unzip the Python tarball and change into the newly create source directory.
tar xf Python-2.7.11.tar.xz
Run the configure script.
./configure --prefix=/usr/local --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
Build and install the new Python binary. We’re using “make altinstall” to ensure that we don’t interfere the system version of Python (this will name the binary python2.7 instead of just python).
Thanks to Daniel Eriksson and Too Much Data for the How to install Python 2.7 and Python 3.3 on CentOS 6 post, from which my instructions are based. I highly recommend reading that post, as my instructions are only the bare minimum needed to get Let’s Encrypt working.
Installing Let’s Encrypt
Now that we have the right Python version, we can install the Let’s Encrypt ACME client. We’ll also install my installation tool (which isn’t much more than a bash script).
/usr/local is intended for locally installed software (as opposed to system provided software), so it seems like a good place to put these tools.
Clone the official Let’s Encrypt ACME client and my installation tool from GitHub.
git clone https://github.com/letsencrypt/letsencrypt
git clone https://github.com/interbrite/letsencrypt-vesta
Let’s Encrypt’s ACME protocol validates that a requestor is in control of the domain by checking for a the availability of a randomly named file over the web. It can do this with its own web server, or it can write a file to the web root of an existing server running on the domain. Since a Vesta server has many different web roots, we’ll tell let’s Encrypt to write these files to a central location and then configure Apache to look there for incoming validation requests.
First, create the Let’s Encrypt webroot directory.
mkdir -p /etc/letsencrypt/webroot
Then create a symlink to the letsencrypt.conf file in my GitHub repository.
ln -s /usr/local/letsencrypt-vesta/letsencrypt.conf /etc/httpd/conf.d/letsencrypt.conf
Finally, restart Apache so it will pick up the configuration change.
service httpd restart
Everything is installed and ready to go, but to run the tools you’ll need to specify the full path to them, since they aren’t in your PATH environment variable. A quick fix for this is to symlink them inside /usr/local/bin.
ln -s /usr/local/letsencrypt/letsencrypt-auto /usr/local/bin/letsencrypt-auto
ln -s /usr/local/letsencrypt-vesta/letsencrypt-vesta /usr/local/bin/letsencrypt-vesta
Now you’re ready to create your first certificate.
lets encrypt-vesta USERNAME DOMAIN
Substitute a valid Vesta user account for USERNAME and a domain hosted on that account for DOMAIN. The script will look up the account and pull the email address listed with it, using that as the contact email used in the certificate request. It will also look up the list of domain aliases associated with the domain and will include all of them as subject alternate names (SANs) in the certificate request. SANs function as additional domains on the certificate—each one will be recognized as a trusted domain by users’ browsers.
The first time you run the script, the Let’s Encrypt client will do some setup work, so it may take a minute or two. Future runs won’t require this additional work and should complete faster.
The certificates issued by Let’s Encrypt are valid for 90 days. It is recommended that you renew them every 60 days to allow ample time to mitigate issues such as reissue errors and service interruptions that might occur and leave you with an expired cert.
Let’s Encrypt is currently in beta and, while they offer unlimited certificates, they do have some limitations in place, at least for now. As of this writing, they currently only allow ten certificate requests from a single IP address over a three hour period and limit the number of SANs on a single certificate to 100. There are also limits on the number of unverified requests (as in a certificate is requested, but the validation process fails) allowed, though this shouldn’t be ann issue for most admins. These numbers may change over time as the technology platform matures and demand for the service adjusts.