> ## Content Index
> Fetch the complete content index at: https://blog.mebooks.co.nz/llms.txt
> Use this file to discover other available public pages before exploring further.

# Fast HTTPS using Pound, Varnish, LetsEncrypt and Pagespeed
- URL: https://blog.mebooks.co.nz/fast-https-using-pound-varnish-letsencrypt-and-pagespeed/
- Published: 2016-03-25T03:27:00.000Z
- Updated: 2017-10-01T03:28:59.000Z
- Author: Jason Darwin
- Tags: #Import 2026-09-23 10:11

*Image courtesy of [Jay Mantri](http://jaymantri.com/?ref=blog.mebooks.co.nz).*

## Making https fast

[Let’s Encrypt](https://letsencrypt.org/?ref=blog.mebooks.co.nz) is a great initiative allowing anyone to easily generate and install SSL certificates so that traffic can be securely served over https.

As well as gaining the benefits of secure traffic, by using https we're also setting ourselves up to benefit from [HTTP/2](https://www.smashingmagazine.com/2016/02/getting-ready-for-http2/?ref=blog.mebooks.co.nz), which will allow a number of performance benefits, but is only available over https.

However, generating and installing SSL certificates using [Let’s Encrypt](https://letsencrypt.org/?ref=blog.mebooks.co.nz) doesn't inherently make our site faster, and actually adds some overhead in terms of extra negotiation between the client and the server, as well as requiring the client to check with the certificate authorities to determine whether a certificate has been revoked (at least until we configure the server to take over this task using [OCSP stapling](https://en.wikipedia.org/wiki/OCSP%5Fstapling?ref=blog.mebooks.co.nz).)

Two great measures for improving website performance are [Varnish](https://www.varnish-cache.org/?ref=blog.mebooks.co.nz) and Google's [Pagespeed Module for Apache and Nginx](https://developers.google.com/speed/pagespeed/module/?ref=blog.mebooks.co.nz).

Below, we'll look at how to generate and install SSL certificates with Let’s Encrypt, and then how to configure our site so that we can still make use of Varnish and the Pagespeed Module to optimise our site performance.

We're assuming here that you've already got a site up and running using Varnish, and Apache/Nginx, serving http traffic on port 80.

## Let’s Encrypt

[Let’s Encrypt](https://letsencrypt.org/?ref=blog.mebooks.co.nz) is now in public beta, meaning that it's available for anyone to use, though you'll need to be aware of the [rate-limiting](https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769?ref=blog.mebooks.co.nz) to prevent abuse of the service, the most relevant parts of which are:

- *Names/Certificate* is the limit on how many domain names you can include in a single certificate. This is currently limited to 100 names, or websites, per certificate issued.
- *Certificates/Domain* you could run into through repeated re-issuance. This limit measures certificates issued for a given combination of Public Suffix + Domain (a "registered domain"). This is limited to 5 certificates per domain per week.

To install and use Let’s Encrypt, we'll do the following (presuming you're running Ubunutu or Debian):

```
# Create a directory for letsencrypt
mkdir /usr/local/letsencrypt

# Clone letsencrypt from the repo.
# You may want to adjust the release tag
cd /usr/local/letsencrypt
git clone https://github.com/letsencrypt/letsencrypt.git#v0.4.2

# Stop any webservers
service apache2 stop
service nginx stop

# Run letsencrypt to create our certificate.
./letsencrypt-auto certonly --email whoever@gmail.com --agree-tos \
    -d whatever.nz -d www.whatever.nz \
    -d whatever.co.nz -d www.whatever.co.nz

```

Note that we stop our webservers before running letsencrypt, as it needs to use ports 80 and 443 for communication with the certificate authorities.

We're also using `--agree-tos` to automatically agree to the terms of service, and `--email` to provide our email so that letsencrypt can create our account. We actually use [Ansible](https://www.ansible.com/?ref=blog.mebooks.co.nz) configuration management scripts for provisioning our webservers and so need these scripts to run automatically, but in the interests of simplicity, we're not showing that here.

Letsencrypt can include a number of domains on a given certificate (currently up to a 100), though it can't produce wildcard certificates, and we use the `-d` option above to specify each domain.

Note also that we're using the `certonly` function; letsencrypt can automatically update webserver configuration files to use the newly generated certificate, but in our case we're going to use [Pound](http://www.apsis.ch/pound/?ref=blog.mebooks.co.nz) to handle https, and our webservers will therefore only be dealing with http traffic.

More information about running letsencrypt can be found on [the letsencrypt site](https://letsencrypt.org/getting-started/?ref=blog.mebooks.co.nz).

Letsencypt certificates are currently valid for 90 days, and in the interests of making life easier for ourselves, we'll set up a cron job to automatically attempt to renew the certificate on a weekly basis. Our bash script, `/usr/local/letsencrypt/letsencrypt-auto-renew.sh`, is as follows:

```
#!/bin/bash

# letsencrypt needs access to port 80
monit stop pound

# To simulate a dry-run near the end of the certificate term:
# /usr/local/letsencrypt/letsencrypt-auto renew --dry-run --email mebooks.support@gmail.com --agree-tos
if ! /usr/local/letsencrypt/letsencrypt-auto renew --email mebooks.support@gmail.com --agree-tos > /var/log/le-renew.log 2>&1; then
    echo Automated renewal failed:
    cat /var/log/le-renew.log
    exit 1
fi

# Restart pound
monit start pound

# Cat the privkey and fullchain for pound
cat /etc/letsencrypt/live/whatever.co.nz/privkey.pem /etc/letsencrypt/live/whatever.co.nz/fullchain.pem > /etc/letsencrypt/archive/whatever.co.nz/privkey_fullchain.pem

# Recreate the symlink
unlink /etc/letsencrypt/live/whatever.co.nz/privkey_fullchain.pem
ln -s /etc/letsencrypt/archive/whatever.co.nz/privkey_fullchain.pem /etc/letsencrypt/live/whatever.co.nz/privkey_fullchain.pem

```

We can ensure that this runs on a weekly frequency by entering a line in our cron file, using `crontab -e`:

```
# m h  dom mon dow   command
 30 2  *   *   1     /usr/local/letsencrypt/letsencrypt-auto-renew.sh >> /var/log/le-renew.log

```

So, we've now got a newly-generated certificate installed, but we actually need to make some use of it.

## Varnish

[Varnish](https://www.varnish-cache.org/?ref=blog.mebooks.co.nz) provides a great http caching layer for websites, and is probably the single most important mechanism for ensuring that your site can serve traffic quickly to a large audience.

However, Varnish only serves traffic via http, and this comment from the maintainer makes it pretty clear it's [unlikely it will ever have support for https](https://www.varnish-cache.org/docs/3.0/phk/ssl.html?ref=blog.mebooks.co.nz):

> Would I be able to write a better stand-alone SSL proxy process than the many which already exists ?

> Probably not, unless I also write my own SSL implementation library, including support for hardware crypto engines and the works.

> That is not one of the things I dreamt about doing as a kid and if I dream about it now I call it a nightmare.

So, if we want to use https, we have to use another service in front of Varnish to proxy https traffic as http to and from Varnish.

If you are using Varnish to directly cache traffic on port 80, your `/etc/default/varnish` would probably have a line that looks like:

```
DAEMON_OPTS="-a :80 \

```

However, as we'll now use Pound to receive traffic in front of Varnish, we'll ensure that Varnish is receiving traffic on its default port of 6081:

```
DAEMON_OPTS="-a :6081 \

```

## Enter Pound

[Pound](http://www.apsis.ch/pound/?ref=blog.mebooks.co.nz) is a great project, and works very nicely in front of Varnish as reverse proxy, accepting http and/or https traffic as configured, and passing it through to Varnish as http.

In order to be able to disable the SSLv3 protocol to cope with the [POODLE vulnerability](https://www.digitalocean.com/community/tutorials/how-to-protect-your-server-against-the-poodle-sslv3-vulnerability?ref=blog.mebooks.co.nz), we'll need to use Pound 2.7f, as [outlined here](http://www.apsis.ch/pound/pound%5Flist/archive/2015/2015-11/1447518215000?ref=blog.mebooks.co.nz). Currently, the standard Ubuntu repositories only make Pound 2.6 available.

```
# Add the PPA
sudo add-apt-repository 'deb https://mslinn-ppa.s3.amazonaws.com stable main'

# Update our apt-get cache
sudo apt-get update

# Check that we see: Candidate:2.7f-0ubuntu1
sudo apt-cache policy pound

# Install Pound
sudo apt-get install pound

```

Once installed, we'll use the following `/etc/pound/pound.cfg`:

```
## Minimal sample pound.cfg
##
## see pound(8) for details
######################################################################
## global options:

User            "www-data"
Group           "www-data"
#RootJail       "/chroot/pound"

## Logging: (goes to syslog by default)
##      0       no logging
##      1       normal
##      2       extended
##      3       Apache-style (common log format)
LogLevel        1

## check backend every X secs:
Alive           30

## use hardware-accelleration card supported by openssl(1):
#SSLEngine      "<hw>"

# poundctl control socket
Control "/var/run/pound/poundctl.socket"
######################################################################
## listen, redirect and ... to:

ListenHTTP
    # 0.0.0.0 below should be your public IP address
    Address  0.0.0.0
    Port     80
    # This part makes sure you redirect all HTTP traffic to HTTPS
    Service
        HeadRequire "Host: whatever.co.nz"
        Redirect 301 "https://whatever.co.nz"
    End
End

# As per https://milos.jakovljevic.me/howto-lets-encrypt-ssl-with-varnish-and-pound-on-ubuntu-server/
ListenHTTPS
        HeadRemove "X-Forwarded-Proto"
        AddHeader  "X-Forwarded-Proto: https"
        Address    {{ public_ip }}
        Port       443
        Cert       "/etc/letsencrypt/live/whatever.co.nz/privkey.pem"
        # http://permalink.gmane.org/gmane.comp.web.pound.general/7489
        Disable SSLv2
        Disable SSLv3
        SSLAllowClientRenegotiation 0
        SSLHonorCipherOrder 1
        # We want to get an A on the Qualys SSL Test (https://www.ssllabs.com/ssltest)
        # https://scotthelme.co.uk/a-plus-rating-qualys-ssl-test/
        Ciphers     "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS"
        # Ensure pound doesn't rewrite location headers, as this can cause a redirect loop
        RewriteLocation 0
        Service
                BackEnd
                        Address 127.0.0.1
                        Port    6081
                End
        End
End

# Get pound to do our hostname redirects (whether they come in as HTTP or HTTPS)
Service
        HeadRequire "^Host: www.whatever.co.nz$"
        Redirect 301 "https://whatever.nz"
End

```

Note the following:

- We're using the `ListenHTTP` block to listen for http traffic on port 80, and redirect it (permanently) to port 443.
- We use the `ListenHTTPS` block to listen for https traffic on port 443, and direct it to Varnish on port 6081
- We disable the SSLv2 and SSLv3 protocols using `Disable SSLv2` and `Disable SSLv3`
- We disallow client renegotiation of the SSL protocol using `SSLAllowClientRenegotiation`, in order to stop attackers trying to demote a secure connection to a less secure connection
- We use `SSLHonorCipherOrder` to ensure our ciphers are applied in the order that we specify them; this allows us to ensure that the browsers will use the most secure first, if they have support for it
- We specify our allowed ciphers using `Ciphers`
- We use `RewriteLocation` to stop Pound rewriting location headers, as this can lead to redirect loops
- We use Pound to do our hostname redirects (whether they come in as HTTP or HTTPS), redirecting www.whatever.co.nz to [http://whatever.co.nz](http://whatever.co.nz/?ref=blog.mebooks.co.nz).

Note that, in order to avoid the POODLE vulnerability, we're disabling the SSLv3 protocol, and not just the SSLv3 cipher. There appears to be some confusion, with some thinking that disabling the SSLv3 cipher is enough to avoid POODLE, but that's [not the case](http://permalink.gmane.org/gmane.comp.web.pound.general/7489?ref=blog.mebooks.co.nz).

Our `Ciphers` is a list of reasonably modern ciphers, ordered from most-secure to least-secure:

```
ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS

```

We don't provide support for ciphers such as RC4, as this is considered too weak. This means people using Internet Explorer 6 won't be able to access our site, but that's not really a problem these days.

We're using Scott Helme's [article on Getting an A+ rating on the Qualys SSL Test](https://scotthelme.co.uk/a-plus-rating-qualys-ssl-test/?ref=blog.mebooks.co.nz) to ensure that we follow good practice regarding security. The [Qualsys SSLTest](https://www.ssllabs.com/ssltest?ref=blog.mebooks.co.nz) is a great resource to determine how secure your site is, and using the above ciphers and SSLv2/SSLv3 migitations, we're able to acheive a solid **A** grade.

![](https://res.cloudinary.com/mebooks/image/upload/v1458869320/qualsys_lz5zzb.jpg)

As security good practice evolves, you'll want to revisit the [Qualsys SSLTest](https://www.ssllabs.com/ssltest?ref=blog.mebooks.co.nz) and ensure that you're continuing to provide a secure site.

As we're going to be using Pound to listen for traffic on port 443, we need to ensure that our webserver doesn't bind to this port.

For Apache, our `/etc/apache2/ports.conf` will look like:

```
# Varnish serves traffic to Apache on port 8080
Listen 8080

<IfModule ssl_module>
    # We'll park Apache's SSL to listen on 8443
    Listen 8443
</IfModule>

<IfModule mod_gnutls.c>
    # We'll park Apache's SSL to listen on 8443
    Listen 8443
</IfModule>

```

You'll want to ensure that your Apache config changes are valid before restarting Apache:

```
apache2ctl configtest

```

In order to activate Pound, we need to enable it:

```
# Check that our pound.cfg is valid
pound -c

# Remove the pound default startup state in /etc/default/pound
sed -i '/startup=0/startup=1/' /etc/default/pound

# Start pound 
service pound start

```

## Pagespeed module

We've now got pound enforcing that all traffic is https, and working nicely with Varnish, which continues to cache our site content.

We've not had to make any changes to our Apache or Nginx site vhost configs, as they're still seeing traffic as http.

Google's [Pagespeed Module for Apache and Nginx](https://developers.google.com/speed/pagespeed/module/?ref=blog.mebooks.co.nz) is a great drop-in webserver module for speeding up our site by making a number of on-the-fly optimisations. It's a topic in itself, and it's worth reading through the documentation to understand how it works and how it can benefit you.

```
sudo dpkg -i mod-pagespeed-*.deb
sudo apt-get -f install

```

This results in the Pagespeed module being installed, and since we're using Apache, we'll find the Pagespeed configuration at `/etc/apache2/mods-enabled/pagespeed.conf`.

We'll want to make the following changes in `/etc/apache2/mods-enabled/pagespeed.conf`:

- Ensure it's on: `ModPagespeed on`
- Respect **X-Forwarded-Proto headers**: `ModPagespeedRespectXForwardedProto on`

As Pagespeed is seeing all traffic coming from Varnish as http, it will normally serve any optimisations accordingly as http. However, this will cause `Mixed content` warnings in our browser, as http assets are being served on an https site.

Using `ModPagespeedRespectXForwardedProto on` ensures that Pagespeed checks for the `X-Forwarded-Proto: https` header added by Pound, and serves any associated optimisations as https.

## Summary

We've glossed over a few things above, as it's presumed that you've already installed and are using Varnish and a web-server such as Apache or Nginx to serve traffic on port 80.

However, the above is hopefully easy enough to follow, and will help you to serve your site securely using [Let’s Encrypt](https://letsencrypt.org/?ref=blog.mebooks.co.nz) and [Pound](http://www.apsis.ch/pound/?ref=blog.mebooks.co.nz), and fast, using [Varnish](https://www.varnish-cache.org/?ref=blog.mebooks.co.nz) and Google's [Pagespeed Module for Apache and Nginx](https://developers.google.com/speed/pagespeed/module/?ref=blog.mebooks.co.nz).

More notes about configuring Pound and Varnish can be found at the following:

- [Web Server Performance Part II: Varnish and Pound](http://www.geoffstratton.com/2013/11/web-server-performance-part-ii-varnish-pound/?ref=blog.mebooks.co.nz)
- [Let's Encrypt Certificates and Pound Load Balancer](https://secwise.nl/lets-encrypt-certifcates-and-pound-load-balancer/?ref=blog.mebooks.co.nz)