Search form

Varnish and Pound with Apache

Using Varnish and Pound together is a relatively easy way to ensure the Varnish cache works for both SSL and non-SSL web sites.

Varnish is a general-purpose web cache that can make your web sites and applications run substantially faster for your visitors while reducing the overall load on your web server. It works by assembling a local cache of your HTML pages, scripts, images and other objects, comparing the hashes of incoming HTTP requests to the hashes of the objects in its cache, and supplying the cached object back to the requester if there's a match. This prevents your web server and database from having to process every request.

By default, Varnish will bypass its cache for any request in which a Set-Cookie header is present, so to maximize performance you need to tell Varnish to ignore cookies that aren't essential to the operation of your web site. For this reason, Varnish can get messy if you're running multiple applications on one server, so I tend to prefer application-specific caching methods instead of a general caching system like Varnish. Varnish also doesn't do SSL, so if you want it to work for https connections you need to run it behind a proxy or load balancer, like Pound or Nginx.

1. Install Varnish (Ubuntu 12.04 or 14.04)

$ curl http://repo.varnish-cache.org/debian/GPG-key.txt | sudo apt-key add -
$ echo "deb http://repo.varnish-cache.org/ubuntu/ precise varnish-3.0" | sudo tee -a /etc/apt/sources.list
$ sudo apt-get update
$ sudo apt-get install varnish

(Varnish 4.0 has been released, but seems to available in few package managers, so download it from https://www.varnish-cache.org/.)

Edit /etc/default/varnish (I’ll only list the settings I’m interested in):

START=yes
DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"

2. Set up Varnish to pass HTTP traffic to Apache

Edit /etc/varnish/default.vcl and add this to the top of the file (not in sub vcl_recv or other subroutines):

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

What you're doing depends on your web application: different apps use different cookies that will prevent caching. Some basic config templates are available from Github.

I've noticed that PhpMyAdmin breaks with Varnish since it tries to POST to the port Apache is running on (8080). To get around this, add a directive like this to the PhpMyAdmin config.inc.php:

$cfg['PmaAbsoluteUri'] = 'http://myserver.com/path-to-phpmyadmin';

Then, assuming your phpmyadmin lives in a directory like myserver.com/phpmyadmin, tell Varnish to just ignore it in vcl_recv:

if (req.url ~ "phpmyadmin") {
   return(pass);
}

And in sub vcl_fetch:

if (req.url ~ "phpmyadmin") {
   return(hit_for_pass);
}

3. Configure Apache to listen on 127.0.0.1:8080 instead of 80

Edit /etc/apache2/ports.conf to change its listen port:

NameVirtualHost 127.0.0.1:8080  # not applicable in Apache 2.4
Listen 127.0.0.1:8080

If you have any virtual hosts in /etc/apache2/sites-available, you should change them to listen on 127.0.0.1:8080 as well.

4. Fix your Apache logging

Once Varnish is running, all your Apache logs will show client IPs as 127.0.0.1. One workaround is to install the RPAF module:

$ apt-get install libapache2-mod-rpaf
$ vi /etc/apache2/mods-available/rpaf.conf

Edit /etc/apache2/mods-available/rpaf.conf:


RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1
RPAFheader X-Forwarded-For

$ a2enmod rpaf

Then add this to vcl_recv in your /etc/varnish/default.vcl file:

sub vcl_recv {
 
  remove req.http.X-Forwarded-For;
  set req.http.X-Forwarded-For = client.ip;
 
etc.

5. Restart everything

service apache2 restart && service varnish restart

Install Pound

Varnish doesn’t handle SSL traffic, so you need to install a proxy or load balancer like Pound or Nginx that interact with SSL traffic using your server's private key. We’ll set up Pound to listen only on port 443 and pass to Varnish on port 80.

$ apt-get install pound

Set Pound to start on system boot (in /etc/default/pound):

startup=1

Edit your Pound configuration (/etc/pound/pound.cfg):

User            "www-data"
Group           "www-data"
 
ListenHTTPS
        Address 10.0.0.1  # put your server's public IP address here
        Port 443
        Cert "/etc/ssl/private/myserver.com.pem"
        HeadRemove "X-Forwarded-Proto"
        AddHeader "X-Forwarded-Proto: https"
        Service
                BackEnd
                        Address 127.0.0.1
                        Port 80
                End
        End
End

Some notes here:

  • Pound doesn't like comments in its Listen blocks. Make sure you delete any # comments.
  • Your .pem files have to be in the order of RSA key, server certificate, intermediate certificate.
  • The "BackEnd" points to the address and port where Varnish is listening. Thus, SSL traffic goes from 443 (Pound) to 127.0.0.1:80 (Varnish) to 127.0.0.1:8080 (Apache). We also add an HTTP header to indicate that we’re forwarding SSL traffic.

Pound passes along the client IP address correctly, so for accurate logging, we want to tell Varnish not to rewrite requests with an 'X-Forwarded-Proto: https' header:

if (req.http.X-Forwarded-Proto !~ "https") {
  remove req.http.X-Forwarded-For;
  set req.http.X-Forwarded-For = client.ip;
}

If Apache is already listening on port 443, we need to move it elsewhere. Edit /etc/apache2/ports.conf and any virtual hosts:


   Listen 44333

Start/restart Apache, Varnish, and Pound:

$ service apache2 restart && service varnish restart && service pound start

Categories: