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); } }