Viewing servers View all News

How-To: Free SSL Certificates From Let’s Encrypt

SSL certificate costs have been steadily declining over the years. A decade ago, you’d have to shell out hundreds of dollars a year for a certificate, but more recently, adequate protection has been available from under $10.

Now, thanks to a non-profit initiative called Let’s Encrypt, SSL prices have truly bottomed out: free.

Let’s Encrypt operates a little different than traditional Certificate Authorities. Where historically certificate purchases have had to be authenticated through the domain’s registrant contact – a process that is all too often confusing for the client – Let’s Encrypt authenticates entirely through server-side software.

Let’s Encrypt is currently in beta, so there are still some kinks to work out, and a bit of elbow grease required for those wishing to give it a try. This article will help guide system admins through the setup process.

Installation

At the time of this posting, official distribution packages are mostly unavailable. So to get the source files, clone from git:

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

Then run the installer:

./letsencrypt/letsencrypt-auto -h

Configuration

You can predefine settings in /etc/letsencrypt/cli.ini:

# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Let's Encrypt with
# "--help" to learn more about the available options.

# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Uncomment and update to register with the specified e-mail address
email = you@domain.com

# Uncomment to use a text interface instead of ncurses
text = True
agree-tos = True
renew-by-default = True

authenticator = webroot

Let’s Encrypt supports different authenticator methods for different server environments (e.g. Apache). We prefer “webroot”, which doesn’t mess with any server configuration files. This tutorial will assume you feel the same way.

Usage

To generate a certificate, run something like:

letsencrypt-auto certonly -w /path/to/webroot -d domain.com -d www.domain.com

This will generate a challenge directory at /path/to/webroot/.well-known. Your server will need to be configured to allow access to this hidden domain or the authentication will fail.

If all went well, you should now have a certificate! Certificates are stored in /etc/letsencrypt/archive/, but you’ll want to use the symlinks they generate in /etc/letsencrypt/live/ to ensure your host file is always pointing to the most recent version. An example nginx configuration looks like this:

server {
	...
	ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
	...
}

After restarting your web server, you should now have luxurious SSL encryption.

Renewal

For security reasons, Let’s Encrypt certificates are only valid for 90 days, so at this stage, you’ll want to get something in place to help automate the renewal process. At the time of this writing, there are no helpers to do this, so we wrote our own. The following script will test certificates found in the /etc/letsencrypt/live/ directory and renew any that are expiring within the next 25 days. If adapting this for your server, be sure and update the letsencrypt-auto binary path.

#!/bin/bash
#
# USAGE:
# -q quiet



#--------------------------------------------------
# Default settings

today=$(date -d "now" +%s)
limit=25
updated=false
use_quiet=false
use_output(){
	#echo if we aren't being quiet
	if [ "$use_quiet" == false ]; then
		echo $1
	fi
}



#--------------------------------------------------
# Parse arguments

while [[ $# > 0 ]]
do
key="$1"

case $key in
	-q)
	use_quiet=true
	;;
	*)
		# unknown option
	;;
esac
shift # past argument or value
done



#--------------------------------------------------
# Renewal

for d in `find /etc/letsencrypt/live/ -mindepth 1 -type d`; do

	domain=`basename $d`
	use_output "------------------------------"
	use_output "DOMAIN: ${domain}"
	use_output "------------------------------"

	cert="${d}/cert.pem"
	exp=$(date -d "`openssl x509 -in $cert -text -noout|grep "Not After"|cut -c 25-`" +%s)
	days_expire=$(echo \( $exp - $today \) / 86400 | bc)
	use_output "	Expiring in ${days_expire} days."
	status="ignored"

	#under the limit, let's renew!
	if [ "$days_expire" -lt "$limit" ]; then
		cert_file="/etc/letsencrypt/renewal/$domain.conf"

		use_output "	Starting renewal..."

		domains=$(grep --only-matching --perl-regex "(?<=domains \= ).*" "${cert_file}")
		# Determine last character
		last_char=$(use_output "${domains}" | awk '{print substr($0,length,1)}')
		# If last character is comma, then delete it from $domains
		if [ "${last_char}" = "," ]; then
			domains=$(use_output "${domains}" |awk '{print substr($0, 1, length-1)}')
		fi

		webroot=$(grep --only-matching --perl-regex "(?<=webroot_path \= ).*" "${cert_file}")
		# Determine last character
		last_char=$(use_output "${webroot}" | awk '{print substr($0,length,1)}')
		# If last character is comma, then delete it from $webroot
		if [ "${last_char}" = "," ]; then
			webroot=$(use_output "${webroot}" |awk '{print substr($0, 1, length-1)}')
		fi

		if ! /path/to/letsencrypt-auto certonly --renew-by-default --config /etc/letsencrypt/cli.ini -w "${webroot}" -d "${domains}" > /var/log/letsencrypt/renew.log 2>&1 ; then
			use_output "	Renewal failed."
			status="failed"
		else
			updated=true
			use_output "	Renewal succeeded."
			status="renewed"
		fi
	fi

	use_output ""

	#log it
	echo `date +"%F:%T"`" ${domain} ${days_expire} ${status}" >> /var/log/letsencrypt-renew.log

done;



#--------------------------------------------------
# Restart server?

if [ "$updated" == true ]; then
	service nginx restart >/dev/null 2>&1
	use_output "NGINX restarted"
fi

With the renewal process automated like this, we can simplify maintenance and make these free SSL certificates practical on production environments.

Be sure to check out our tips on How to Achieve an A+ SSL Configuration on Nginx to see how to maximize your encryption potential.

View all BBG Technology posts here.

Posted By
Josh Stoik

HHVM: The Gift That Keeps On Giving

Over the past 20 years, PHP has become the de facto server-side programming language of the web.

From leading open-source software like WordPress to some of the Internet’s most heavily-trafficked sites (Facebook, Twitter, and Wikipedia to name a few), you’ll find it everywhere.

But its developer-friendly syntax comes at a cost.

Before any Web Magic™ can happen, the human-readable PHP source code must be run through an interpreter. This process is expensive (particularly in terms of memory usage) and time-consuming. Ultimately, this sets an upper-bound on the number of simultaneous page requests a given server can handle. As a site nears this ceiling, it becomes necessary to either make the site more efficient, or upgrade the hardware.

For some sites, the answer is to sidestep PHP altogether and implement static page caching. But for others, where dynamic processing is unavoidable, the solution might lie in the interpreter itself.

As system administrators know, there is no shortage of PHP interpreters on the market.

Each has its own quirks, configurations, and compatibility issues, so there is no one-size-fits-all solution. But with a little experimentation and a lot of testing, performance gains can be substantial.

One of the most promising interpreters available today is the Hip-Hop Virtual Machine (HHVM). Developed in-house by Facebook, the name of the game for HHVM is speed. For one thing, HHVM meets the machine halfway, converting PHP source code into an intermediate bytecode (this bytecode, then, is what’s left to dynamically interpret at runtime).

This is similar to what PHP extensions like Xcache bring to the table. Another trick up its sleeves: HHVM uses a single multi-threaded process to handle requests (unlike, for example, PHP-FPM, which spawns multiple processes). This leads to much more stable CPU and memory usage for servers operating under heavy loads.

A couple months ago, one of the more resource-heavy sites managed by Bright Bright Great was suffering from a substantial increase in traffic. While publicity is one of the better problems to have, it did pose difficulties for the server, which simply wasn’t configured for that level of interest.

After some (read: lots of) compatibility testing, we successfully transitioned from PHP-FPM to HHVM. The results were astounding.

The average DOM-Ready time dropped by 46%. Simultaneous page serves increased by 112%. And CPU usage under load, once maxed out, remained stable at a healthy 55%.

In fact, the PHP gains were so successful the bottleneck was shifted to MySQL. After some code rewrites to help the site take advantage of object caching (via HHVM’s implementation of APC), the simultaneous page serving capacity was nearly doubled again.

But wait, there’s more!

As part of HHVM’s regular development cycle, its engineers are locked in a room with a surfeit of junk food and coffee (I imagine) and tasked to further optimize the code already in place. By focusing on improvements that directly benefit widely-used software, the real-world impact of any gains made is maximized. With the recent release of version 3.8, HHVM was able to serve 9.7% more pages per second for WordPress, 4.8% for MediaWiki, and 13.9% for Drupal8 (uncached).

We ran quick before and after tests ourselves (against the site previously mentioned) using the command line program siege. Sure enough, the upgrade was able to serve 4.3% more pages per second.

HHVM is indeed the gift that keeps on giving!

Posted By
Josh Stoik