Skip to content

Instantly share code, notes, and snippets.

@Kubik-Rubik
Last active May 22, 2021 18:20
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save Kubik-Rubik/02b221bacd3b313eb5bdb1c3dec87c1c to your computer and use it in GitHub Desktop.
Save Kubik-Rubik/02b221bacd3b313eb5bdb1c3dec87c1c to your computer and use it in GitHub Desktop.
Varnish Configuration for WordPress running on Plesk Onyx
# This configuration file can be used to enable Varnish in a Docker container in Plesk Onyx to boost a WordPress website
# Replace .host with the IP address of your Plesk server
#
# Note: This is a minimal version as a POC, you most likely will have to add code for a more complex WordPress instance!
#
# Inspired by http://www.htpcguides.com/configure-wordpress-varnish-4-cache-with-apache-or-nginx/
#
/* SET THE HOST AND PORT OF WORDPRESS
* *********************************************************/
vcl 4.0;
import std;
backend default {
.host = "XXX.XXX.XXX.XXX";
.port = "7080";
.first_byte_timeout = 60s;
.connect_timeout = 300s;
}
# SET THE ALLOWED IP OF PURGE REQUESTS
# ##########################################################
acl purge {
"localhost";
"127.0.0.1";
"XXX.XXX.XXX.XXX";
}
#THE RECV FUNCTION
# ##########################################################
sub vcl_recv {
# set realIP by trimming CloudFlare IP which will be used for various checks
set req.http.X-Actual-IP = regsub(req.http.X-Forwarded-For, "[, ].*$", "");
# FORWARD THE IP OF THE REQUEST
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
# Purge request check sections for hash_always_miss, purge and ban
# BLOCK IF NOT IP is not in purge acl
# ##########################################################
# Enable smart refreshing using hash_always_miss
if (req.http.Cache-Control ~ "no-cache") {
if (client.ip ~ purge || std.ip(req.http.X-Actual-IP, "1.2.3.4") ~ purge) {
set req.hash_always_miss = true;
}
}
if (req.method == "PURGE") {
if (!client.ip ~ purge || !std.ip(req.http.X-Actual-IP, "1.2.3.4") ~ purge) {
return(synth(405,"Not allowed."));
}
return (purge);
}
if (req.method == "BAN") {
# Same ACL check as above:
if (!client.ip ~ purge || !std.ip(req.http.X-Actual-IP, "1.2.3.4") ~ purge) {
return(synth(403, "Not allowed."));
}
ban("req.http.host == " + req.http.host +
" && req.url == " + req.url);
# Throw a synthetic page so the
# request won't go to the backend.
return(synth(200, "Ban added"));
}
# Unset cloudflare cookies
# Remove has_js and CloudFlare/Google Analytics __* cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
# Remove a ";" prefix, if present.
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
# For Testing: If you want to test with Varnish passing (not caching) uncomment
# return( pass );
# DO NOT CACHE RSS FEED
if (req.url ~ "/feed(/)?") {
return ( pass );
}
#Pass wp-cron
if (req.url ~ "wp-cron\.php.*") {
return ( pass );
}
## Do not cache search results, comment these 3 lines if you do want to cache them
if (req.url ~ "/\?s\=") {
return ( pass );
}
# CLEAN UP THE ENCODING HEADER.
# SET TO GZIP, DEFLATE, OR REMOVE ENTIRELY. WITH VARY ACCEPT-ENCODING
# VARNISH WILL CREATE SEPARATE CACHES FOR EACH
# DO NOT ACCEPT-ENCODING IMAGES, ZIPPED FILES, AUDIO, ETC.
# ##########################################################
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
# No point in compressing these
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 {
# unknown algorithm
unset req.http.Accept-Encoding;
}
}
# PIPE ALL NON-STANDARD REQUESTS
# ##########################################################
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
return (pipe);
}
# ONLY CACHE GET AND HEAD REQUESTS
# ##########################################################
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# OPTIONAL: DO NOT CACHE LOGGED IN USERS (THIS OCCURS IN FETCH TOO, EITHER
# COMMENT OR UNCOMMENT BOTH
# ##########################################################
if ( req.http.cookie ~ "wordpress_logged_in|resetpass" ) {
return( pass );
}
#fix CloudFlare Mixed Content with Flexible SSL
if (req.http.X-Forwarded-Proto) {
return(hash);
}
# IF THE REQUEST IS NOT FOR A PREVIEW, WP-ADMIN OR WP-LOGIN
# THEN UNSET THE COOKIES
# ##########################################################
if (!(req.url ~ "wp-(login|admin)")
&& !(req.url ~ "&preview=true" )
){
unset req.http.cookie;
}
# IF BASIC AUTH IS ON THEN DO NOT CACHE
# ##########################################################
if (req.http.Authorization || req.http.Cookie) {
return (pass);
}
# IF YOU GET HERE THEN THIS REQUEST SHOULD BE CACHED
# ##########################################################
return (hash);
# This is for phpmyadmin
if (req.http.Host == "pmadomain.com") {
return (pass);
}
}
sub vcl_hash {
if (req.http.X-Forwarded-Proto) {
hash_data(req.http.X-Forwarded-Proto);
}
}
# HIT FUNCTION
# ##########################################################
sub vcl_hit {
return (deliver);
}
# MISS FUNCTION
# ##########################################################
sub vcl_miss {
return (fetch);
}
# FETCH FUNCTION
# ##########################################################
sub vcl_backend_response {
# I SET THE VARY TO ACCEPT-ENCODING, THIS OVERRIDES W3TC
# TENDANCY TO SET VARY USER-AGENT. YOU MAY OR MAY NOT WANT
# TO DO THIS
# ##########################################################
set beresp.http.Vary = "Accept-Encoding";
# IF NOT WP-ADMIN THEN UNSET COOKIES AND SET THE AMOUNT OF
# TIME THIS PAGE WILL STAY CACHED (TTL), add other locations or subdomains you do not want to cache here in case they set cookies
# ##########################################################
if (!(bereq.url ~ "wp-(login|admin)") && !bereq.http.cookie ~ "wordpress_logged_in|resetpass" ) {
unset beresp.http.set-cookie;
set beresp.ttl = 1w;
set beresp.grace =3d;
}
if (beresp.ttl <= 0s ||
beresp.http.Set-Cookie ||
beresp.http.Vary == "*") {
set beresp.ttl = 120 s;
# set beresp.ttl = 120s;
set beresp.uncacheable = true;
return (deliver);
}
return (deliver);
}
# DELIVER FUNCTION
# ##########################################################
sub vcl_deliver {
# IF THIS PAGE IS ALREADY CACHED THEN RETURN A 'HIT' TEXT
# IN THE HEADER (GREAT FOR DEBUGGING)
# ##########################################################
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
# IF THIS IS A MISS RETURN THAT IN THE HEADER
# ##########################################################
} else {
set resp.http.X-Cache = "MISS";
}
}
@rijans
Copy link

rijans commented Sep 15, 2018

Any update for Varnish 5.0? Anyway my subdomain keeps loading and nothing shows. I also restarted server and docker also. Initially I got the page:

Error 503 Backend fetch failed
Backend fetch failed

Guru Meditation:
XID: 65541

Varnish cache server

But after putting this, it keeps loading and sometimes get same message with this response:

Request URL: https://mysubdomain/
Request Method: GET
Status Code: 503
Remote Address: 104.28.14.68:443
Referrer Policy: no-referrer-when-downgrade
age: 0
cf-ray: 45ad86be194baa38-SIN
content-type: text/html; charset=utf-8
date: Sat, 15 Sep 2018 19:34:54 GMT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
retry-after: 5
server: cloudflare
status: 503
strict-transport-security: max-age=15552000; includeSubDomains; preload
via: 1.1 varnish (Varnish/5.0)
x-cache: HIT
x-content-type-options: nosniff
x-varnish: 98306 65546

Copy link

ghost commented Oct 23, 2018

there is an error in line 50:

# Enable smart refreshing using hash_always_miss if (req.http.Cache-Control ~ "no-cache") { if (client.ip ~ purge || std.ip(req.http.X-Actual-IP, "1.2.3.4") ~ purge) { set req.hash_always_miss = true; } }

The correct:
# Enable smart refreshing using hash_always_miss if (req.http.Cache-Control ~ "no-cache") { if (client.ip ~ purge || !std.ip(req.http.X-Actual-IP, "1.2.3.4") ~ purge) { set req.hash_always_miss = true; } }

it is possible to have support for a woocommerce configuration?
I've tried to follow this step and add code but doesn't work:
https://docs.woocommerce.com/document/configuring-caching-plugins/
https://wordpress.org/support/topic/varnish-configuration-not-working-in-woocommerce/

@sanyogs
Copy link

sanyogs commented Nov 29, 2018

After using this i am not able to load wp admin file

@januzi
Copy link

januzi commented Jan 16, 2019

Where should I make changes to this file to get the facebookall plugin working? It's directing to the main domain with ?code=x, and then everything else is being ran on the /register/ page. I can read the user data, so the page is not being cached (and the dev tools says that there is a miss), but the lines: wp_set_auth_cookie ($user_data->ID ); do_action ('wp_login', $user_data->user_login, $user_data); don't do much. The cookies aren't being set. On the other hand, the normal login form is being processed correctly and I can login as normal and admin users without any trouble at tall. So, I'm guessing that the varnish is for some reason "murdering" the cookies, so they aren't being sent to browser.

@marri2k
Copy link

marri2k commented May 22, 2021

I'm getting this error Backend fetch failed

Guru Meditation:
XID: 15

Varnish cache server

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment