Installing LetsEncrypt SSL Certificates on Apache

Two days before Christmas, having wrapped up most of my tasks for the year, I decided to finally install an SSL certificate that I had purchased back in June for the princely sum of $38.97.

At the time I had been hanging for Lets Encrypt to go live, but alas, June 30 crept around and I was forced to make the decision of whether or not to buy the certificate before the tax year ended. I bought it, but then never got round to installing it.

So today I went to install it. And then promptly figured out that I had only created it for myserver.com. It did not contain www.myserver.com, which meant connection requests to www.myserver.com, which should seamlessly redirect to myserver.com, were raising an SSL error in the browser. Not cool!

I explored options for reconfiguring my certificate but none existed. It could be "re-issued", but it would still have the same SANs, so it looked like I was going to have to regenerate the certificate.

I knew Lets Encrypt had gone live, because there was much chatter about it on Twitter and, in particular, in the Laravel world, largely because Taylor Otwell had incorporated Lets Encrypt into Laravel Forge. This allows Forge users to easily enable SSL on their Forge-based servers. Very cool indeed!

I spent a few minutes reading the Lets Encrypt documentation overview and decided that I should “do the right thing” and test the process on a local VM first. Part way through the process I realised that you can’t really do this, because when you run the letsencrypt client, it actually talks to their servers and starts enrolling you and generating live certificates.

So I did what everybody says not to do and installed it straight onto my production server. And it worked perfectly! The only small challenge was that there was a point in the process where I needed to stop Apache. My solution was to go to my app’s activity page, see how many people were logged on (not many) and watch what they were doing (not a lot), get my commands ready to go in two separate terminal windows and then wait. As soon as I spotted what felt like a good opportunity, I ran through the process, which only involved stopping Apache for about 10 seconds.

The entire process that I went through on my production server, which runs Debian 8.1, was as follows:

git clone https://github.com/letsencrypt/letsencrypt

cd letsencrypt

./letsencrypt-auto --help

sudo /etc/init.d/apache2 stop

# Note that the following command will prompt you for an admin email address
# There are command-line options to pass this information, which allows the
# entire process to be automated.
./letsencrypt-auto certonly --standalone -d myserver.com -d www.myserver.com

sudo /etc/init.d/apache2 start

These steps result in SSL certificates and supporting files being saved in /etc/letsencrypt/live/myserver.com.

The final step was to configure the site’s configuration file and tell Apache to reload it. Here is the SSL part of the site’s configuration file:

# /etc/apache/sites-enabled/myserver.conf

<VirtualHost *:443>
  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/live/myserver.com/cert.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/myserver.com/privkey.pem
  SSLCACertificateFile /etc/letsencrypt/live/myserver.com/fullchain.pem
  ServerName myserver.com
  DocumentRoot /var/www/prod/public
  DirectoryIndex index.php
  CustomLog /var/log/apache2/prod.log combined
</VirtualHost>

<VirtualHost *:443>
  ServerName www.myserver.com
  Redirect permanent / https://myserver.com/
</VirtualHost>

Once those changes were made, only one more step was required to have the app start serving via HTTPS:

/etc/init.d/apache reload

The entire installation process, once you know what steps to take, should only take a few minutes. Although Lets Encrypt is still in beta, I feel quite comfortable running these steps on a production server, because the really critical part is the Apache configuration, which you can do manually, and even if you get that wrong, you’re probably still not going to screw up non-SSL traffic on port 80. I guess to be ultra-sure you should back up your site’s configuration file first.

Please note that although Lets Encrypt certificates only have a three month expiry date, renewing is as easy as running the lets-encrypt-auto command that was used in the first place.

I hope Lets Encrypt receives tons of support from the business community as well as the developer community, because they have done a truly stellar job on this product.

And what an awesome way to finish 2015!

Yet Another Programming Blog

Where James Gordon rambles about PHP and web development in general.

Find me on Twitter Find me on Stack Exchange Find me on Github Subscribe