Supercharging , Part 1

As fast as the Internet moves, even 's latest release seems dated. Let's fix that.


Superceded by Part 2

Google Chrome is the embodiment of agile development. Now that they're the majority browser on the Internet, they're the ones calling the shots as far as Web standards and features are concerned. It's enough to make even recent releases of Web software, cryptographic libraries, compression algorithms, and even entire Linux distributions seem outdated out of the gate. When I installed not too long ago, even it was several versions behind.

I was able to find an Ubuntu PPA with a newer version linked against a newer version of OpenSSL, but even that was lacking compared to, for example, what CloudFlare is advertising. So, I took it upon myself to grab all of the patches and roll my own.

First, a warning. I'll be downloading bleeding-edge development versions of software, pulling patches from GitHub, reading draft RFC's, and throwing all this onto the public Internet for the world to have at. Bugs will be found, patches will be released, standards may change, browsers will change, and best case, your Web site may break horribly. This is not a "set it and forget it" tutorial; in fact, you should bookmark this.

I am installing all this on a server running Ubuntu Linux 16.04.2 LTS. If you use another Linux or a BSD, that's great, but make sure you know how to install software (apt, emerge, ports, etc.).

Make an empty folder and change into it --‍ I used /opt/nginx-build.

You should also uninstall any packages you've installed through your package manager.

Compiling OpenSSL

There's no reason to not use for your Web site. Reduced performance is an issue of the past, between TLS 1.3 speeding things up, and HTTP/2 over cleartext being dead on arrival. Thanks to Let's Encrypt, certificates that once cost hundreds of dollars are now free. It's enough to make Google demote sites that don't use TLS.

Now, we can use the built-in OpenSSL 1.0.2 and get almost everything we need. But if it were that easy, I wouldn't be writing this. To get the latest and greatest performance and security, with things such as the Curve25519 elliptic curve, SCT support, and those new AES-CCM ciphers, we need to use the 1.1 branch of OpenSSL. So, let's download that. I'll also be mixing in Cloudflare's ChaCha20-Poly1305 reordering patch, to ensure newer processors that can perform AES-GCM in hardware will continue to do so, while the more efficient ChaCha20 algorithm will be preferred by older clients with Google or Mozilla software --‍ like my ancient laptop.

# Download and verify OpenSSL
gpg --‍recv-keys 0xD9C4D26D0E604491
gpg --‍verify openssl-1.1.0f.tar.gz.asc

# Apply CloudFlare's ChaCha20 patch.
cd openssl-1.1.0f
curl​cloudflare/​sslconfig/​master/​patches/​openssl__1.1.0_chacha20_poly1305.patch | patch -‍p1
cd ..

We're not going to build it just yet.

Compressing Resources with Brotli

There are two modules that I'll be adding in. The first is the Brotli compression module, which is far more efficient than GZip, which will save some bandwidth for you and your users. Another Google invention, Brotli is in three of the four major browsers (all four once Safari 11 launches), so there's no reason to not use it.

This will require a couple libraries to be installed; fortunately, Scott Helme's blog proved to be an invaluable resource in getting this set up.

You will be needing the Git client and some Python libraries for the rest of this tutorial, so let's install those, too. Then, we'll fetch the Brotli libraries and module.

cd ..
apt-get install git python2.7 python-dev
git clone​google/​brotli.git
cd brotli
sudo python setup‍.‍py install
cd tests
cd ..

git clone​bagder/​libbrotli
cd libbrotli
sudo make install
cd ..

git clone​google/​ngx_brotli.git

Supporting Certificate Transparency with SCT's

Google got sick of random certificate authorities giving other people valid certificates for Can you really blame them? Several technologies were created as a result of incidents like that, Certificate Transparency being one of them. It should be mandatory by next year, so let's be the first one on the boat.

We'll need the module right now, but we're also going to build a command-line tool that we'll need to use whenever we get a new certificate.

# This fetches the current development build of the module.
git clone

# This grabs the ct-submit tool.
# It's written in Go, so we need support for that, too.

apt-get install golang-go
go build ./ct-submit.go
rm ./ct-submit.go
sudo mv ct‍-‍submit /usr/local/bin

Finally, Let's Build .

Now that we have all those pieces, we can finally get around to building OpenSSL and . Of note are three more patches developed by Cloudflare. The first one implements a static version of to compress HTTP/2 headers, the next allows both HTTP/2 and its predecessor /3.1 to be supported (because we all know legacy technology dies slowly), and the last one adjusts TLS record sizes on the fly for better performance.

# Download, verify, and extract.
gpg --‍recv-keys 0x520A9993A1C052F8
gpg --‍verify nginx-1.13.2.tar.gz.asc
tar xvf nginx-1.13.2
cd nginx-1.13.2

# We're going to grab some performance enhancers from Cloudflare.
curl​cloudflare/​sslconfig/​master/​patches/​nginx_1.13.1_http2_hpack.patch | patch -p1
curl​cloudflare/​sslconfig/​master/​patches/​nginx__1.13.0_http2_spdy.patch | patch -p1
curl​cloudflare/​sslconfig/​master/​patches/​nginx__1.11.5_dynamic_tls_records.patch | patch -p1

# Make sure you pay attention to the bold parts.
# You can add and remove any other modules that you wish.

./configure --‍prefix=/usr/local --‍conf‍-‍path=/etc/nginx/nginx.conf --‍http-log-path=/var/log/nginx/access.log --‍error-log-path=/var/log/nginx/error.log --‍lock-path=/var/lock/nginx.lock --‍pid-path=/run/ --‍http-client-body-temp-path=/var/lib/nginx/body --‍http-fastcgi-temp-path=/var/lib/nginx/fastcgi --‍http-proxy-temp-path=/var/lib/nginx/proxy --‍http-scgi-temp-path=/var/lib/nginx/scgi --‍http-uwsgi-temp-path=/var/lib/nginx/uwsgi --‍with-pcre-jit --‍with-http_ssl_module --‍with-http_stub_status_module --‍with-http_realip_module --‍with-http_auth_request_module --‍with-http_addition_module --‍with-http_dav_module --‍with-http_geoip_module --‍with-http_gzip_static_module --‍with-http_image_filter_module --‍with-http_mp4_module --‍with-http_sub_module --‍with-http_xslt_module --‍with-http_v2_module --‍with-http_v2_hpack_enc --‍with-http_spdy_module --‍with-google_perftools_module --‍with-http_secure_link_module --‍with-openssl=../openssl-1.1.0f --‍with-openssl-opt="enable-ec_nistp_64_gcc_128" --‍add-module=../nginx-ct-1.3.2 --‍add-module=../ngx_brotli
sudo make install

# I was getting link errors afterwards when trying to run OpenSSL.
# These two lines fixed everything. Your mileage may vary.

echo "/usr/local/lib64" > /etc/​openssl.conf

Congratulations! You now have a bleeding-edge version of waiting for you under /usr/local/sbin. If you're using systemd, you can run systemctl enable nginx && systemctl start nginx. Of course, without content, there won't be much to see. Part two, which is coming soon, will show you how to actually enable these features.

If there are any typos or if I can clarify anything better, feel free to complain at me on Twitter.

Metadata and license information
Property Value
Author Me, wearing a purple shirt, tie, and a jacket. Colin Cogle

This blog post is licensed under Creative Commons License 4.0 CC-BYCreative Commons Attribution 4.0 International License.

Content Rating None
Encoding text/html; charset=UTF-8
Search keywords , HTTP, , , TLS
Summary As fast as the Internet moves, even NGINX's latest seems dated. Find out how to support modern tech such as Brotli, SCT's, and ChaCha20. In part one, we build it and its dependencies from source.
Word count 776 words, not counting code snippets

Creative Commons License 4.0 CC-BY This blog post is licensed under a Creative Commons Attribution 4.0 International License. The full text of the license is available online at


This article:
"HTTPS as a Ranking Signal" by Google:
Cloudflare's TLS patches for NGINX:
"Brotli Compression" by Scott Helme: