THIS VARNISH CONFIG HAS BEEN UPDATED AND IS AVAILABLE HERE
I have been tweaking a varnish vcl config for WordPress for quite some time and I wanted to share it.. Thanks to everyone(especially DocWilco) in #varnish on Linpro IRC for helping
Features:
- Load balancing
- Probing
- Does not cache wp-admin
- Puts all uploads/content requests onto one server
- Purging
- Long timeout for file uploads
- XML RPC support
- Custom 404 and 500 message
- Forwards user IP address for comments
First of all.. Let’s define some backends..
// BACKEND CONFIGS
backend server1 {
.host = "server1.example.com";
.port = "8080";
.probe = {
.url = "/";
.interval = 5s;
.timeout = 1 s;
.window = 5;
.threshold = 3;
}
// we include time outs so uploads don't time out
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
}
backend server2 {
.host = "server2.example.com;
.port = "8080";
.probe = {
.url = "/";
.interval = 5s;
.timeout = 1 s;
.window = 5;
.threshold = 3;
}
// we include time outs so uploads don't time out
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
}
// define round-robin for backends
director cluster round-robin {
{.backend = server1;}
{.backend = server2;}
}
// set the servers wordpress can purge from
acl purge {
"server1.example.com";
"server2.example.com";
}
sub vcl_fetch {
if (req.http.host ~ "ourdomain.com"
|| req.http.host ~ "ourotherdomain.com"
// don't cache wp-admin ever cause that's not cool
&& req.url !~ "wp-admin")
{
// we cache these domains for 8 hours unless they are purged.
set beresp.ttl = 8h;
set beresp.grace = 600s;
// don't cache 404 or 500 errors
if (beresp.status == 404 || beresp.status >= 500) {
set beresp.ttl = 0s;
}
}
// tell all of the files to use server1
if (req.url ~ "files") {set req.backend = server;set beresp.ttl = 8h;}
}
sub vcl_recv {
// Purge WordPress requests for purge
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
purge("req.url == " req.url " && req.http.host == " req.http.host);
error 200 "Purged.";
}
// forward the client IP so comments show up properly
set req.http.X-Forwarded-For = client.ip;
// let server2 handle all feeds
if (req.url ~ "/feed/")
{set req.backend = server2;}
// server1 must handle file uploads
if (req.url ~ "media-upload.php"
|| req.url ~ "file.php"
|| req.url ~ "async-upload.php")
{set req.backend = server1;return(pass);}
// server1 can serve all files.
if (req.url ~ "/files/")
{set req.backend = server1;}
// do not cache xmlrpc.php
if (req.url ~ "xmlrpc.php")
{return(pass);}
// strip cookies from xmlrpc
if (req.request == "GET" && req.url ~ "xmlrpc.php")
remove req.http.cookie;return(pass);}
// caching these files is fine
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 ~ "^/[^?]+\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.*|)$") {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.*$", "");
}
// Remove cookies from front page
if (req.url ~ "^/$") {
unset req.http.cookie;
}
// if the request is for our domain and not for wp-admin then load balance it to a server that is responding or send it to server1
if (req.http.host ~ "ourdomain.com"
|| req.http.host ~ "ourotherdomain.com"
&& req.url !~ "wp-admin")
{
set req.http.X-Forwarded-For = client.ip;
set req.backend = cluster;
} else {
set req.http.X-Forwarded-For = client.ip;
set req.backend = server1;
}
// Custom error message
sub vcl_error {
if(obj.status == 404) {
set obj.ttl = 0s;
set obj.http.Content-Type = "text/html; charset=utf-8";
synthetic {" <!--?xml version="1.0" encoding="utf-8"?-->
"} obj.status " " obj.response {"
</pre>
<div style="background-color: white;"><center>
<img src="http://whatever.com/heavyload.jpg" alt="" width="600px" /></center>
<h1>This page is unavailable</h1>
If you are seeing this page, either maintenance is being
performed or you are trying to access a file that doesn't exist. Please <a href="http://whatever.com/contact.html">contact us</a> if you believe this is an error
<h2>Error "} obj.status " " obj.response {"</h2>
"} obj.response {" on server "} req.backend {"
<address><a href="http://whatever.com/">Us.</a></address></div>
<pre>
"};
return (deliver);
error 404 "Not found";
}
else
{
set obj.http.Content-Type = "text/html; charset=utf-8";
synthetic {" <!--?xml version="1.0" encoding="utf-8"?-->
"} obj.status " " obj.response {"
</pre>
<div style="background-color: white;"><center>
<img src="http://whatever.com/heavyload.jpg" alt="" width="600px" /></center>
<h1>This website is unavailable</h1>
If you are seeing this page, either maintenance is being
performed
or something really bad has happened. Try returning in a few
minutes. If you still see this error in a few minutes please <a href="http://whatever.com/contact.html">contact us</a>
<h2>Error "} obj.status " " obj.response {"</h2>
"} obj.response {" on server "} req.backend {"
<address><a href="http://whatever.com/">Us.</a></address></div>
<pre>
"};
return (deliver);
}
}