Modern Website over HTTP 2 and SSL with Nginx and Let's Encrypt
Published on:Table of Contents
Banner Generated through trianglify
The free and open certificate authority, Let’s Encrypt has been out in public beta for the last few months and v0.3.0 of their client was recently released, so I decided to give it a try on one of my side projects: eu4stats.com.
Additionally, Nginx, the web server behind eu4stats.com, received an update in September that supports HTTP2 requests. While HTTP2 does hold the promise of increased performance, eu4stats.com most likely won’t see the benefit because most the assets are pulled from CDNs like jsDelivr, but it will be a good future proofing excersise.
Step 0: Testing Along the Way
We’ll be testing our server externally through the use of cURL
. We’ll see the
upgrade, the switch to https, and http 2 represented in the response. The
following command will let us see.
curl -sI "https://eu4stats.com" | egrep -i "Server|HTTP"
cURL, as packaged, is unable to query using HTTP 2, so you’ll have to build it
from source by first building
nghttp2 and then building
cURL by configuring with the
--with-nghttp2
flag and path. After everything is built, you’ll see the
previous command returning HTTP 2 headers.
Step 1: Updating Nginx
We need a recent version of Nginx, but default package managers are likely to
carry only outdated versions, so hop over to the official linux distrubtion
page. The stable
package doesn’t include the HTTP2 module (--with-http_v2_module
), so use the
mainline version.
Below we add the Nginx key to apt
, add their repo, and update.
curl -L "http://nginx.org/keys/nginx_signing.key" | sudo apt-key add -
DEB_CMD="deb http://nginx.org/packages/mainline/ubuntu/ $(lsb_release -c -s) nginx"
sudo bash -c 'echo "${DEB_CMD}" >> /etc/apt/sources.list'
sudo apt-get update
We can test the Nginx server and HTTP version with apt-cache showpkg nginx
.
Newer versions of Nginx should appear. Let’s install the most recent one.
sudo apt-get install nginx
sudo service nginx restart
nginx -v
If the previous snippet does not work, it’s because the nginx maintainer for ubuntu somewhat emulates the apache server configuration, so you may have to go a few more steps.
sudo apt-get remove nginx-common
# Will ask you to overwrite previous configuration, say no or else you'll need
# to change the new nginx configuration to emulate apache
sudo apt-get install nginx
sudo service nginx restart
nginx -v
The latest and greatest Nginx is installed, but because you can’t enable HTTP 2.0 unencrypted (if you can, you shouldn’t because browsers may reject it) we have to get our certificate. Next step!
Step 2: Let’s Encrypt: Retrieving Certificates
Getting and setting up Let’s Encrypt on a machine is somewhat of a controversial topic. As a system administrator, you are putting a lot of trust into this program because:
- Requires root privileges. You’re giving Let’s Encrypt the power to do anything on your machine, including mess it up
- Heavy installation. Installs various dependencies including GCC, which is the not what I want to be installing on what should be a slim server with limited disk space.
- Is a black box. You execute a command and all your certificates including your key are generated. If you’re not careful, it’ll rewrite your Apache configuration as well!
Naturally I tried looking for alternatives that alleviated all mentioned problems:
- gethttpsforfree.com: As a website, doesn’t require installation of anything but also doesn’t support auto-renewel.
- Let’s Encrypt - No Sudo: Had more problems than I could shake a stick at with odd crypto errors.
- simp_le: is another heavy install
After several hours I gave up and went back to the Let’s Encrypt docs and found this golden nugget:
Unless you have a very specific requirements, we kindly ask you to use the letsencrypt-auto method. It’s the fastest, the most thoroughly tested and the most reliable way of getting our software and the free SSL certificates!
They really should have focused on making the client as small and self contained as possible and then build upon that foundation. Not spend time prioritizing an ncurses GUI or auto-magically updating your site’s configuration. All the while, closing sane requests to open up the black box as “too difficult”. Ok, rant done. It’s beta software and getting better every day.
Once you pull down letsencrypt-auto
here are the commands to run to get
handed the cert from already running site:
sudo ./letsencrypt-auto certonly --webroot -w <nginx_website_root> \
--email <email_for_registration> -d <domain_name>
# Chown so that the nginx user can read it!
sudo chown -R www-data.www-data /etc/letsencrypt
You’ll see your Let’s Encrypt certificate along with the chain, full cert, and private key.
Step 3: Installing Certificates
SSL configuration of a server is probably less intuitive than probably one thinks. To help us, Mozilla created an SSL configuration generator and I would recommend starting with the intermediate Nginx configuration. Since we’ll want http 2 and Let’s Encrypt auto renewal, modify the pull request to add http2 and include the following snippets:
listen [::]:443 ssl http2;
# LetsEncrypt.org TLS certificate renewal
location ~ .well-known {
allow all;
}
Step 4: Auto Renewal
The Let’s Encrypt official client will have a renew
command in
0.4.0 , so I won’t spend
too much time on this because this section will be outdated shortly. In the
meantime, I recommend using the
le-renew-script
Comments
If you'd like to leave a comment, please email [email protected]