How to Setup Varnish 3.0 in Front of Nginx, PHP5.4 (PHP-FPM)

Share this Article :

In the previous post, i have describes the steps to setup web server that running on Nginx and PHP5.4 (PHP-FPM). The setup and configuration work well with the WordPress site. This article will describe how to speed up the existing NGINX + PHP web server with one of the popular web accelerator called Varnish Cache, also known as caching HTTP reverse proxy. Varnish cache will speed up the website delivery to the visitor and reduce the CPU time, less database requests and file lookups. This steps to setup varnish has been tested on CentOS 6, CentOS 7, Oracle Linux 7 and RHEL 7.

Setup Varnish in front of Nginx

Varnish is a HTTP accelerator that can run side by side with either Apache or Nginx web server. In this tutorial, i will setup Varnish to run on port 80 while NGINX on port 8080.

Setup Varnish

Benefits of Varnish

1. Reduce server CPU load and time
2. Increase website load speed
3. Can handle large number of websites visitors
4. Varnish supports load balancing

How to Setup Varnish

1. Setup Nginx, PHP5.4 (PHP-FPM) as web server. Refer to this tutorial.

2. Install varnish :

[[email protected] ~]# wget https://repo.varnish-cache.org/redhat/varnish-3.0/el6/noarch/varnish-release/varnish-release-3.0-1.el6.noarch.rpm
[[email protected] ~]# rpm -Uvh varnish-release-3.0-1.el6.noarch.rpm
[[email protected] ~]# yum install varnish -y

3. Configure and setup Varnish :

Below configuration for /etc/sysconfig/varnish and /etc/varnish/default.vcl say that NGINX are running as the backend server on localhost at port 8080 while Varnish will run in front of it listening on port 80.

a. Modify /etc/sysconfig/varnish :

[[email protected] ~]# vim /etc/sysconfig/varnish

Add the following. if your VPS running SSD disk, you can select varnish_storage as a cache method instead of memory (-s malloc) :

..
..
DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -u varnish -g varnish \
             -S /etc/varnish/secret \
             -p thread_pool_add_delay=2 \
             -p thread_pools=2 \
             -p thread_pool_min=400 \
             -p thread_pool_max=4000 \
             -p session_linger=50 \
             -p sess_workspace=262144 \
             -s file,/var/lib/varnish/varnish_storage.bin,512m"
..
..
VARNISH_LISTEN_PORT=80
..
..

b. Modify /etc/varnish/default.vcl :

[[email protected] ~]# vim /etc/varnish/default.vcl

Add as below :

backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .connect_timeout = 600s;
    .first_byte_timeout = 600s;
    .between_bytes_timeout = 600s;
    .max_connections = 800;
}


acl purge {
	"127.0.0.1";
}

sub vcl_recv {


	# Allow purge requests
	if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        ban("req.url ~ ^" + req.url + " && req.http.host == " + req.http.host);
        return(lookup);
    }

	# Add header for sending client ip to backend
	set	req.http.X-Forwarded-For = client.ip;

	# Normalize	content-encoding
	if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
            remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set	req.http.Accept-Encoding = "deflate";
        } else {
            remove req.http.Accept-Encoding;
        }
    }

    # Remove cookies and query string for real static files
    if (req.url ~ "^/[^?]+\.(gif|jpg|jpeg|swf|css|js|txt|flv|mp3|mp4|pdf|ico|png|gz|zip|lzma|bz2|tgz|tbz)(\?.*|)$") {
       unset req.http.cookie;
       set req.url = regsub(req.url, "\?.*$", "");
    }

    # Don't cache admin
    if (req.url ~ "((wp-(login|admin|comments-post.php|cron.php))|login)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
        return (pass);
    } else {
    	unset req.http.cookie;
    }
}

sub vcl_hit {
	# purge cached objects from memory
	if (req.request == "PURGE") {
		purge;
		error 200 "Purged";
	}
}

sub vcl_miss {
	# purge cached objects varients from memory
	if (req.request == "PURGE") {
		purge;
		error 404 "Purged varients";
	}
}

sub vcl_fetch {
	# Dont cache admin
	if (req.url ~ "(wp-(login|admin|comments-post.php|cron.php))|login" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
    	    return (deliver);
	} else {
    	    if ( beresp.ttl > 0s ) {
    	        unset beresp.http.set-cookie;
    	    }
	}
}


sub vcl_deliver {

	# Remove unnecessary headers
	remove resp.http.Server;
	remove resp.http.X-Powered-By;
	remove resp.http.X-Varnish;
	remove resp.http.Via;

	# DIAGNOSTIC HEADERS
	if (obj.hits > 0) {
		set resp.http.X-Cache = "HIT";
	} else {
		set resp.http.X-Cache = "MISS";
	}

}

4. Reconfigure NGINX to work with Varnish :

a. Configure default.conf :

[[email protected] ~]# vim /etc/nginx/conf.d/default.conf

Add the following :

..
server {
    listen       127.0.0.1:8080;
    server_name  localhost;
..

b. Configure common.conf :

[[email protected] ~]# vim /etc/nginx/conf.d/common.conf
..
..

listen 127.0.0.1:8080;
..
..

c. Configure Vhost for domain example.com :

[[email protected] ~]# vim /etc/nginx/sites-available/example.com.conf

Change listen to 127.0.0.1:8080; :

server {
listen       127.0.0.1:8080;
    server_name example.com;
    rewrite ^/(.*)$ http://www.example.com/$1 permanent;
}
..

5. Restart NGINX, php-fpm and Varnish :

[[email protected] ~]# service nginx restart; service php-fpm restart; service varnish restart

6. Make sure NGINX listening to port 8080 and Varnish port 80 :

[[email protected] ~]# netstat -plunt  | grep LISTEN
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      3119/varnishd
tcp        0      0 127.0.0.1:8080              0.0.0.0:*                   LISTEN      3065/nginx

Thats All.

Leave a Reply