Setting up Varnish
You can install varnish by following the official installation guide (this one is for Ubuntu, but you can find a official guide that supports your OS) at: https://www.varnish-cache.org/installation/ubuntu
Make sure to edit /etc/default/varnish and change DEAMON_OPTS so that varnish listens on port 80
/etc/default/varnish
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"
Caching only selected requests (white listing what to be cached)
The following code will ensure that Varnish will only cache whatever that matches the filters define. Everything else will be passed to the backend.
/etc/varnish/default.vcl
sub vcl_recv {
if (req.url ~ "^/api/method1/" ||
req.url ~ "^/api/method2.json"
) {
return(hash);
}
# pass everything to the backend by default
return(pass);
}
Cache-Control HTTP Headers
You have to set the proper cache-control HTTP headers for varnish to work properly. For example if a certain action is to be cached by varnish. You can do this inside the rails controller action.
expires_in 24.hours, public:true
This will set the appropriate cache headers.
Purging
For manually asking varnish to purge a URL you have to send a HTTP PURGE request to same URL. Also you need to make sure your varnish vcl file have whitelisted the host making the purging requests.
Ex:
/etc/varnish/default.vcl
acl purgers {
"localhost";
"xxx.xxx.xxx.xxx";
}
sub vcl_recv {
# Happens before we check if we have this in cache already.
#
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.
if (req.method == "PURGE") {
if (client.ip ~ purgers) {
return(purge);
} else {
return(synth(403, "Access denied."));
}
}
}
Also you can see some example code on how to do this in ruby under:
https://github.com/robmiller/varnisher/blob/master/lib/varnisher/purger.rb
Other Varnish Trickery
Varnish can modify http headers and a lot more on the go. So for example if you want to remove cookie headers from requests before they are looked up by varnish you can do so.
Ex:
/etc/varnish/default.vcl
sub vcl_recv {
if (req.url ~ "^/api/method1/" ||
req.url ~ "^/api/method2.json"
) {
unset req.http.Cache-Control;
unset req.http.Max-Age;
unset req.http.Pragma;
unset req.http.Cookie;
return(hash);
}
# pass everything to the backend by default
return(pass);
}
Notes
If you find that examples you found online for varnish configs are not working as expected. Make sure they are compatible with the version of Varnish you are using. Refer to the upgrading guide linked bellow for more info on how to modify whatever examples you find to the latest version of varnish (v4).
Interesting gems
Varnisher: https://github.com/robmiller/varnisher Lacquer: https://github.com/russ/lacquer
Documentation
https://www.varnish-cache.org/docs/4.0/users-guide https://www.varnish-cache.org/docs/trunk/whats-new/upgrading.html
Example VCL files
varnish.vcl
staging /etc/varnish/default.vcl
#
# 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.
# 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 = "xxx.xxx.xxx.xxx";
.port = "80";
}
acl purgers {
"xxx.xxx.xxx.xxx";
"xxx.xxx.xxx.xxx";
}
sub vcl_recv {
# Happens before we check if we have this in cache already.
#
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.
if (req.method == "PURGE") {
if (client.ip ~ purgers) {
return(purge);
} else {
return(synth(403, "Access denied."));
}
}
if (req.url ~ "^/api/method1/" ||
req.url ~ "^/api/method2.json"
) {
# unset req.http.Cache-Control;
# unset req.http.Max-Age;
# unset req.http.Pragma;
# unset req.http.Cookie;
return(hash);
}
# pass everything to the backend by default
return(pass);
}
sub vcl_backend_response {
# Happens after we have read the response headers from the backend.
#
# Here you clean the response headers, removing silly Set-Cookie headers
# and other mistakes your backend does.
if (bereq.url ~ "^/api/method1/" ||
bereq.url ~ "^/api/method2.json"
) {
# unset beresp.http.Cache-Control;
# unset beresp.http.Max-Age;
# unset beresp.http.Pragma;
# unset beresp.http.Cookie;
return(deliver);
}
}
sub vcl_deliver {
# Happens when we have all the pieces we need, and are about to send the
# response to the client.
#
# You can do accounting or modifying the final object here.
}
development
/etc/varnish/default.vcl
#
# 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.
# 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 = "localhost";
.port = "8080";
}
acl local {
"localhost";
}
sub vcl_recv {
# Happens before we check if we have this in cache already.
#
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.
if (req.method == "PURGE") {
if (client.ip ~ local) {
return(purge);
} else {
return(synth(403, "Access denied."));
}
}
if (req.url ~ "^/api/method1/" ||
req.url ~ "^/api/method2"
) {
unset req.http.Cache-Control;
unset req.http.Max-Age;
unset req.http.Pragma;
unset req.http.Cookie;
return(hash);
}
# pass everything to the backend by default
return(pass);
}
sub vcl_backend_response {
# Happens after we have read the response headers from the backend.
#
# Here you clean the response headers, removing silly Set-Cookie headers
# and other mistakes your backend does.
}
sub vcl_deliver {
# Happens when we have all the pieces we need, and are about to send the
# response to the client.
#
# You can do accounting or modifying the final object here.
}