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