About Varnish
Varnish is a HTTP accelerator; in other words a caching server. It allows us to speed up websites by directing HTTP requests static copy of the website maintained and produced by Varnish.
About Nginx
Nginx is a lightweight, high performance HTTP server that will serve as the backend service to Varnish. It will not directly serve websites to visitors; however, it will respond to requests from Varnish whenever cache is required to be built.
How do Nginx and Varnish work?

Install nginx, varnish
yum install varnish
yum install nginx
Config nginx listen on port 8081
server {
listen 8081;
server_name www.example.com;
rewrite ^(.*) http://example.com$1 permanent;
}
server {
listen 8081 default_server;
server_name example.com;
....................
}
Varnish
- Stop nginx and varnish
- Config varnish vi /etc/varnish/default.vcl (for wordpress)
#
# This is an example VCL file for Varnish.
#
# It does not do anything by default, delegating control to the
# builtin VCL. The builtin VCL is called when there is no explicit
# return statement.
#
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/
# and http://varnish-cache.org/trac/wiki/VCLExamples for more examples.
# Update for work with Varnish 4
# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "8081";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}
# Only allow purging from specific IPs
acl purge {
"localhost";
"127.0.0.1";
}
# This function is used when a request is send by a HTTP client (Browser)
sub vcl_recv {
# Normalize the header, remove the port (in case you're testing this on various TCP ports)
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# Allow purging from ACL
if (req.method == "PURGE") {
# If not allowed then a error 405 is returned
if (!client.ip ~ purge) {
return(synth(405, "This IP is not allowed to send PURGE requests."));
}
# If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
return (purge);
}
# Post requests will not be cached
if (req.http.Authorization || req.method == "POST") {
return (pass);
}
# --- WordPress specific configuration
# Did not cache the RSS feed
if (req.url ~ "/feed") {
return (pass);
}
# Blitz hack
if (req.url ~ "/mu-.*") {
return (pass);
}
# Did not cache the admin and login pages
if (req.url ~ "/wp-(login|admin)") {
return (pass);
}
# Unset Cookies except for WordPress admin and WooCommerce pages
if (!(req.url ~ "(wp-login|wp-admin|wc-ajax|cart|my-account/*|checkout|addons|logout|lost-password|product/*)")) {
unset req.http.cookie;
}
# Pass through the WooCommerce dynamic pages
if (req.url ~ "^/(cart|my-account/*|checkout|wc-ajax|addons|logout|lost-password|product/*)") {
return (pass);
}
# Pass through the WooCommerce add to cart
if (req.url ~ "\?add-to-cart=" ) {
return (pass);
}
# Remove the "has_js" cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
# Remove any Google Analytics based cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
# Remove the wp-settings-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");
# Remove the wp-settings-time-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");
# Remove the wp test cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^ *$") {
unset req.http.cookie;
}
# Cache the following files extensions
if (req.url ~ "\.(css|js|png|gif|jp(e)?g|swf|ico)") {
unset req.http.cookie;
}
# Normalize Accept-Encoding header and compression
# https://www.varnish-cache.org/docs/3.0/tutorial/vary.html
if (req.http.Accept-Encoding) {
# Do no compress compressed files...
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
unset 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 {
unset req.http.Accept-Encoding;
}
}
# Check the cookies for wordpress-specific items
if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
return (pass);
}
if (!req.http.cookie) {
unset req.http.cookie;
}
# --- End of WordPress specific configuration
# Did not cache HTTP authentication and HTTP Cookie
if (req.http.Authorization || req.http.Cookie) {
# Not cacheable by default
return (pass);
}
# Cache all others requests
return (hash);
}
sub vcl_pipe {
return (pipe);
}
sub vcl_pass {
return (fetch);
}
# The data on which the hashing will take place
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
# If the client supports compression, keep that in a different cache
if (req.http.Accept-Encoding) {
hash_data(req.http.Accept-Encoding);
}
return (lookup);
}
# This function is used when a request is sent by our backend (Nginx server)
sub vcl_backend_response {
# Remove some headers we never want to see
unset beresp.http.Server;
unset beresp.http.X-Powered-By;
# For static content strip all backend cookies
if (bereq.url ~ "\.(css|js|png|gif|jp(e?)g)|swf|ico") {
unset beresp.http.cookie;
}
# Only allow cookies to be set if we're in admin area
#if (beresp.http.Set-Cookie && bereq.url !~ "/wp-(login|admin)") {
# unset beresp.http.Set-Cookie;
#}
#Only allow cookies to be set if we're in admin area and WooCommerce pages
# Unset Cookies except for WordPress admin and WooCommerce pages
if ( (!(bereq.url ~ "(wp-login|wp-admin|login|cart|my-account/*|checkout|addons|logout|lost-password|product/*)")) || (bereq.method == "GET") ) {
unset beresp.http.Set-Cookie;
}
# don't cache response to posted requests or those with basic auth
if ( bereq.method == "POST" || bereq.http.Authorization ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# don't cache search results
if ( bereq.url ~ "\?s=" ){
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# only cache status ok
if ( beresp.status != 200 ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# A TTL of 24h
set beresp.ttl = 24h;
# Define the default grace period to serve cached content
set beresp.grace = 30s;
return (deliver);
}
# The routine when we deliver the HTTP request to the user
# Last chance to modify headers that are sent to the client
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "Hit";
} else {
set resp.http.x-Cache = "Miss";
}
# Remove some headers: PHP version
unset resp.http.X-Powered-By;
# Remove some headers: Apache version & OS
unset resp.http.Server;
# Remove some heanders: Varnish
unset resp.http.Via;
unset resp.http.X-Varnish;
return (deliver);
}
sub vcl_init {
return (ok);
}
sub vcl_fini {
return (ok);
}
- Config varnish vi /etc/varnish/varnish.params
# Varnish environment configuration description. This was derived from
# the old style sysconfig/defaults settings
# Set this to 1 to make systemd reload try to switch vcl without restart.
RELOAD_VCL=1
# Main configuration file. You probably want to change it.
VARNISH_VCL_CONF=/etc/varnish/default.vcl
# Default address and port to bind to. Blank address means all IPv4
# and IPv6 interfaces, otherwise specify a host name, an IPv4 dotted
# quad, or an IPv6 address in brackets.
VARNISH_LISTEN_ADDRESS=
VARNISH_LISTEN_PORT=80
# Admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
# Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret
# Backend storage specification, see Storage Types in the varnishd(5)
# man page for details.
VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G"
# Default TTL used when the backend does not specify one
VARNISH_TTL=120
# User and group for the varnishd worker processes
VARNISH_USER=varnish
VARNISH_GROUP=varnish
# Other options, see the man page varnishd(1)
#DAEMON_OPTS="-a :80 -p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"
check varnish cli: varnishstat
check varnish listening on port 80: netstat -tulpn (Notice: check varnish listening on port 80 TCP(ipv4) and TCP6(ipv6) )
# netstat -tulpn
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 646/exim
tcp 0 0 127.0.0.1:6082 0.0.0.0:* LISTEN 7895/varnishd
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 8543/php-fpm: pool
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 25150/mysqld
tcp 0 0 0.0.0.0:587 0.0.0.0:* LISTEN 646/exim
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7896/varnishd
tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 8135/nginx: master
tcp 0 0 0.0.0.0:465 0.0.0.0:* LISTEN 646/exim
tcp 0 0 0.0.0.0:1235 0.0.0.0:* LISTEN 8135/nginx: master
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 637/sshd
tcp6 0 0 :::25 :::* LISTEN 646/exim
tcp6 0 0 ::1:6082 :::* LISTEN 7895/varnishd
tcp6 0 0 :::587 :::* LISTEN 646/exim
tcp6 0 0 :::80 :::* LISTEN 7896/varnishd
tcp6 0 0 :::465 :::* LISTEN 646/exim
tcp6 0 0 :::21 :::* LISTEN 5791/vsftpd
tcp6 0 0 :::22 :::* LISTEN 637/sshd
udp 0 0 0.0.0.0:68 0.0.0.0:* 9023/dhclient
udp 0 0 0.0.0.0:53346 0.0.0.0:* 9023/dhclient
udp 0 0 0.0.0.0:57953 0.0.0.0:* 361/avahi-daemon: r
udp 0 0 0.0.0.0:5353 0.0.0.0:* 361/avahi-daemon: r
udp6 0 0 :::15871 :::* 9023/dhclient
Restart service (stop nginx before start varnish. If nginx still running, it will keep port 80)
systemctl stop nginx
systemctl restart varnishd
systemctl restart varnishncsa
systemctl restart varnishlog (By defualt Varnish log directory path is /var/log/varnish/)
systemctl restart nginx
Test Varnish
curl -I http://example.com
HTTP/1.1 200 OK
Date: Wed, 13 Apr 2016 10:58:25 GMT
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding, Cookie
X-Pingback: http://example.com
Link: <http://example.com/>; rel=shortlink
Age: 57047
X-Cache: Hit
Connection: keep-alive
Install Vanisher
yum install rubygems
yum install ruby-devel
yum install zlib-devel
yum install libxml2-devel
yum install libxslt-devel
gem install nokogiri
gem install varnisher
gem install bundler
Purge cache
varnisher purge http://example.com/
or
varnishadm "ban req.http.host ~ example.com"
or
curl -X PURGE http://example.com/