edoceo

Nginx SSL and Varnish

Firstly, lets get this out of the way: Varnish does not do SSL, at all and likely won't ever.

Varnish is not a tool for connection managment, it's a tool to cache web-pages and make them faster. That is all.

To get the speed benefits of Varnish over the SSL traffic we have to run an additional service to manage the SSL connections. Cue Nginx.

Our example configuration looks something like this, all on one server - but in real-life this should be distributed across dedicated machines.

  • Nginx Public IP 74.207.248.164
  • Varnish on Private IP 127.0.0.1:8080
  • Apache on Private IP 127.0.0.1:80

Visual Overview

The HTTP requests from the internet hit Nginx, which passes some directly to Apache and some to Varnish (based on rules). Varnish, on cache-miss, will request to Apache. And Apache will likely hit the database.

varnish, nginx, apahce

Configuring Nginx

Please see our existing howto for Nginx.

The configuration there will be adjusted along these lines, again, update as necessary for your environment. Here, we just

http {
     server {
         listen       74.207.248.164:80;
         server_name  _;

         location /c {
            root /var/www/css;
         }

         location /i {
            root /var/www/images;
         }

         location / {
            proxy_pass   http://127.0.0.1:8080;
         }
     }
}
http {
     server {

         listen       74.207.248.164:443;
         server_name  _;

         ssl          on;
         ssl_certificate /etc/ssl/server.crt;
         ssl_certificate_key /etc/ssl/server.key;
         # ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
         # ssl_ciphers   HI:!aNULL:!MD5;

         location / {
            proxy_pass   http://127.0.0.1:8080;
         }
     }
}

Configure Varnish

This can be a typical Varnish configuration, what changes here is the listening and the back-end. Configure the sub vcl_* routines as you normally would. Keep in mind however, some requests can be handled a the Nginx layer, so don't need rules here (anymore).

backend default {
    .host = "127.0.0.1";
    .port = "80";
    .connect_timeout = 16s;
    .first_byte_timeout = 96s;
    .between_bytes_timeout = 8s;
}

And remember to start varnish with -a 127.0.0.1:8080, so it's only listening on the local system, high-http port.

Configure Apache

I like to have Apache listen on the default HTTP port, then I explicitly set the hostname on the machine as well as in the Apache configuration. This way many of the running apps will think they are still publicly exposed and it helps them resolve their hostname. This is needed for example by Chiliproject, Redmine, Drupal, Wordpress and many others.

<VirtualHost 127.0.0.1:80>
	ServerName edoceo.com
	ErrorLog /dev/null
	CustomLog /dev/null fuck-it
<VirtualHost>

It should be noted here that the Apache configuration maybe able to operate with a much stripped configuration. As a result of sitting behind these other systems we can do away with many modules and remove some of the other rules which are designed for public consumption (such as Keep Alive).

Testing

We use curl to test.

See Also

Loading Comments from Disqus...