Varnish caching wordpress when not instructed - wordpress

I am trying to write a good vcl file for my sites that use a very customized Wordpress installation, but I am still a newbie in the field. So I will be very thankful if anyone can point out where I make mistakes.
I am trying to have a default.vcl with common rules and per domain vcl files with domain specific rules. The problem is that I try to instruct Varnish not to cache some paths for pages and pop-up ajax boxes. And not to cache logged in users which I catch by login cookie.
I shall paste my complete config.
Also, I am bit confused about the linear execution of the vcl file if there is an included additional vcl file. Does the location where is the 'includ' matter?
I would like to investigate the case myself, but using Varnish logging is a bit complicated. Is there a way that I can find which rules are acting on specific pages?
My default.vcl
vcl 4.0;
import std;
backend domain1 {
.host = "11.111.11.1";
.port = "8001";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}
backend domain2 {
.host = "222.22.22.2";
.port = "8002";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}
acl purge {
"localhost";
"127.0.0.1";
"79.124.64.16";
"193.107.37.45";
}
sub vcl_recv {
if (req.http.host ~ "^(?i)domain1.com" || req.http.host ~ "^.*\.domain1.com" ) {
set req.backend_hint = domain1;
}
elseif (req.http.host == "^.*\.domain2.com" || req.http.host == "^.*\.domain2-alias.com") {
set req.backend_hint = domain2;
}
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;
}
}
#Pass through cache PhpMyAdmin
if (req.url ~ "^.*phpmyadmin.*") {
return(pass);
}
}
######## PER DOMAIN SUBROUTINES ###########
include "domain1.vcl";
include "domain2.vcl";
if (req.http.Cookie ~ "wordpress_logged_in_") {
return (pass);
}
# Normalize the header, remove the port (in case you're testing this on various TCP ports)
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# Allow purging from ACL
if (req.method == "PURGE") {
# If not allowed then a error 405 is returned
if (!client.ip ~ purge) {
return(synth(405, "This IP is not allowed to send PURGE requests."));
}
# If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
return (purge);
}
# Post requests will not be cached
if (req.http.Authorization || req.method == "POST") {
return (pass);
}
# Conflicting with few lines below
# # Only deal with "normal" types
# if (req.method != "GET" &&
# req.method != "HEAD" &&
# req.method != "PUT" &&
# req.method != "POST" &&
# req.method != "TRACE" &&
# req.method != "OPTIONS" &&
# req.method != "PATCH" &&
# req.method != "DELETE") {
# /* Non-RFC2616 or CONNECT which is weird. */
# return (pipe);
# }
# Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
if (req.http.Upgrade ~ "(?i)websocket") {
return (pipe);
}
# Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
if (req.method != "GET" && req.method != "HEAD") {
return (pipe);
}
# Some generic URL manipulation, useful for all templates that follow
# First remove the Google Analytics added parameters, useless for our backend
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
set req.url = regsub(req.url, "\?&", "?");
set req.url = regsub(req.url, "\?$", "");
}
# Some generic cookie manipulation, useful for all templates that follow
# Remove the "has_js" cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
# Remove any Google Analytics based cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
# Remove DoubleClick offensive cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
# Remove the AddThis cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
# Remove a ";" prefix in the cookie if present
set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");
#Remove WP cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utma.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "__utmb.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "__utmc.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "__utmt.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "__utmz.=[^;]+(; )?", "");
# set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie.=[^;]+(; )?", "");
# set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "bp-message[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "bp-message-type[^;]+(; )?", "");
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
**#Dont cache Logged-in users
if (req.http.Cookie == "wordpress_logged_in_") {
return (pass);
}
elseifif (req.http.cookie ~ "wordpress_logged_in_") {
return (pass);
}**
# Large static files are delivered directly to the end-user without
# waiting for Varnish to fully read the file first.
# Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response()
if (req.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# Remove all cookies for static files
# A valid discussion could be held on this line: do you really need to cache static files that don't cause load? Only if you have memory left.
# Sure, there's disk I/O, but chances are your OS will already have these files in their buffers (thus memory).
# Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
if (req.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|
woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# Send Surrogate-Capability headers to announce ESI support to backend
# set req.http.Surrogate-Capability = "key=ESI/1.0";
if (req.http.Authorization) {
# Not cacheable by default
return (pass);
}
# Did not cache HTTP authentication and HTTP Cookie
if (req.http.Authorization || req.http.Cookie) {
# Not cacheable by default
return (pass);
}
}
# Cache all others requests
return (hash);
}
######## PER DOMAIN SUBROUTINES ###########
include "domain1.vcl";
include "domain2.vcl";
sub vcl_pipe {
# set bereq.http.Connection = "Close";
# Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
if (req.http.upgrade) {
set bereq.http.upgrade = req.http.upgrade;
}
return (pipe);
}
sub vcl_pass {
# return (pass);
}
# The data on which the hashing will take place
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
# hash cookies for requests that have them
# if (req.http.Cookie) {
# hash_data(req.http.Cookie);
# }
}
sub vcl_hit {
if (obj.ttl >= 0s) {
# A pure unadultered hit, deliver it
return (deliver);
}
# https://www.varnish-cache.org/docs/trunk/users-guide/vcl-grace.html
# When several clients are requesting the same page Varnish will send one request to the backend and place the others on hold while fetching one copy from the backend. In some products this is called request coalescing and Varni
sh does this automatically.
# If you are serving thousands of hits per second the queue of waiting requests can get huge. There are two potential problems - one is a thundering herd problem - suddenly releasing a thousand threads to serve content might sen
d the load sky high. Secondly - nobody likes to wait. To deal with this we can instruct Varnish to keep the objects in cache beyond their TTL and to serve the waiting requests somewhat stale content.
# if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) {
# return (deliver);
# } else {
# return (fetch);
# }
# We have no fresh fish. Lets look at the stale ones.
##if (std.healthy(req.backend_hint) {
# Backend is healthy. Limit age to 10s.
##if (obj.ttl + 10s > 0s) {
#set req.http.grace = "normal(limited)";
## return (deliver);
## } else {
# No candidate for grace. Fetch a fresh object.
## return(fetch);
## }
## } else {
# backend is sick - use full grace
## if (obj.ttl + obj.grace > 0s) {
#set req.http.grace = "full";
## return (deliver);
## } else {
# no graced object.
return (fetch);
## }
## }
# fetch & deliver once we get the result
## return (fetch); # Dead code, keep as a safeguard
}
sub vcl_miss {
# Called after a cache lookup if the requested document was not found in the cache. Its purpose
# is to decide whether or not to attempt to retrieve the document from the backend, and which
# backend to use.
return (fetch);
}
# Handle the HTTP request coming from our backend
sub vcl_backend_response {
# Called after the response headers has been successfully retrieved from the backend.
if (bereq.http.Cookie ~ "(UserID|_session)") {
set beresp.http.X-Cacheable = "NO:Got Session";
set beresp.uncacheable = true;
return (deliver);
} elsif (beresp.ttl <= 0s) {
# Varnish determined the object was not cacheable
set beresp.http.X-Cacheable = "NO:Not Cacheable";
} elsif (beresp.http.set-cookie) {
# You don't wish to cache content for logged in users
set beresp.http.X-Cacheable = "NO:Set-Cookie";
set beresp.uncacheable = true;
return (deliver);
} elsif (beresp.http.Cache-Control ~ "private") {
# You are respecting the Cache-Control=private header from the backend
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
set beresp.uncacheable = true;
return (deliver);
} else {
# Varnish determined the object was cacheable
set beresp.http.X-Cacheable = "YES";
}
# Pause ESI request and remove Surrogate-Control header
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
# Enable cache for all static files
# The same argument as the static caches from above: monitor your cache size, if you get data nuked out of it, consider giving up the static file cache.
# Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
if (bereq.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|wof
f|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
unset beresp.http.set-cookie;
}
# Large static files are delivered directly to the end-user without
# waiting for Varnish to fully read the file first.
# Varnish 4 fully supports Streaming, so use streaming here to avoid locking.
if (bereq.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
unset beresp.http.set-cookie;
set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects
}
# Sometimes, a 301 or 302 redirect formed via Apache's mod_rewrite can mess with the HTTP port that is being passed along.
# This often happens with simple rewrite rules in a scenario where Varnish runs on :80 and Apache on :8080 on the same box.
# A redirect can then often redirect the end-user to a URL on :8080, where it should be :80.
# This may need finetuning on your setup.
#
# To prevent accidental replace, we only filter the 301/302 redirects for now.
if (beresp.status == 301 || beresp.status == 302) {
set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", "");
}
# Set 2min cache if unset for static files
if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
set beresp.ttl = 120s; # Important, you shouldn't rely on this, SET YOUR HEADERS in the backend
set beresp.uncacheable = true;
return (deliver);
}
# Don't cache 50x responses
if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
return (abandon);
}
# Allow stale content, in case the backend goes down.
# make Varnish keep all objects for 6 hours beyond their TTL
set beresp.grace = 6h;
return (deliver);
}
# The routine when we deliver the HTTP request to the user
# Last chance to modify headers that are sent to the client
sub vcl_deliver {
# Called before a cached object is delivered to the client.
if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
# Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object
# and obj.hits may not be reset in some cases where bans are in use. See bug 1492 for details.
# So take hits with a grain of salt
#set resp.http.X-Cache-Hits = obj.hits;
# Remove some headers: PHP version
unset resp.http.X-Powered-By;
# Remove some headers: Apache version & OS
unset resp.http.Server;
unset resp.http.X-Drupal-Cache;
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
unset resp.http.X-Generator;
return (deliver);
}
sub vcl_purge {
# Only handle actual PURGE HTTP methods, everything else is discarded
if (req.method != "PURGE") {
# restart request
set req.http.X-Purge = "Yes";
return(restart);
}
}
sub vcl_synth {
if (resp.status == 720) {
# We use this special error status 720 to force redirects with 301 (permanent) redirects
# To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
set resp.http.Location = resp.reason;
set resp.status = 301;
return (deliver);
} elseif (resp.status == 721) {
# And we use error status 721 to force redirects with a 302 (temporary) redirect
# To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
set resp.http.Location = resp.reason;
set resp.status = 302;
return (deliver);
}
return (deliver);
}
sub vcl_fini {
# Called when VCL is discarded only after all requests have exited the VCL.
# Typically used to clean up VMODs.
return (ok);
}
My domain1.vcl
vcl 4.0;
sub vcl_recv {
if (req.backend_hint == domain1) {
**#Don't store backend in case of login pop screen
if (req.url ~ "^.*wp-(login|admin).*" || req.url ~ "preview=true" || req.url ~ "^.*(login|admin).*" || req.url ~ "^.*wp-load.*") {
return (pipe);
}
# Do not cache home, search, registration pages
if (req.url ~ "\/path\/subpath\/" || req.url ~ "\/pathabc\/pathdef\/" || req.url ~ ".*register.*") {
return(pipe);
}
if (req.url ~ ".*\/members\/.*") {
return(hash);
}
}
return(hash);
}**
sub vcl_backend_response {
}
sub vcl_deliver {
}
My domain2.vcl experiences no issues when creating rules.

The problem you have is due to req.backend_hint == domain1 (this will not work). You should compare with hostname in your site specific VCL instead. So in domain1.vcl it will be:
vcl 4.0;
sub vcl_recv {
if (req.http.host ~ "^(?i)domain1.com" || req.http.host ~ "^.*\.domain1.com" ) {
# site specific logic goes here ...
}
}
You should not place include directives directly inside vcl_recv procedure. Those should go either at the very top of the file or at the bottom depending on desired priority.
In this case you should place them at the top which means :
# ...
include "domain1.vcl";
include "domain2.vcl";
sub vcl_recv {
#...
This will make sure that vcl_recv logic that is defined in your site specific VCL files will have priority in execution over the ones that you have in the main VCL file itself.
The VCL includes work in a way that every procedure in further included file will be executed last. As example, the vcl_recv routines will be executed in this order:
vcl_recv from site-specific .vcl
vcl_recv from default.vcl
vcl_recv from builtin.vcl
More info about writing site specific VCL and what builtin.vcl is you can find here.
Your VCL is unnecessarily complex. I always advise to start from the empty default.vcl that is shipped with Varnish and add more code slowly bit by bit in order to understand how things work. Blind copy pasting never leads to expected results, more often to unexpected :).
Examples
The following is completely unnecessary. Varnish 4 handles this for you before any VCL is executed in the first place:
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;
}
}
}
Furthermore, having 600s timeout values for everything would maybe make your application work, but if it doesn't work with the default values (surely enough you'd see "backend fetch failed") there is a reason for that. And Varnish is not the place to fix "backend fetch failed" - your application is :).
Finally, if you have decided to implement your caching policy based on presence of the Wordpress cookies, then stick to that and remove all the lines that filter out the known unneeded cookies. Those are unnecessary (think why would you do whitelisting and blacklisting of cookies at the same time).
I am referring to all lines similar to this:
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
# ...

Related

Varnish 4 woocommerce mini cart not working

i am using the following varnish 4 configuration and althrough POST requests are not cached, when adding to cart, mini cart is not working. This is the official documentation
https://docs.woocommerce.com/document/configuring-caching-plugins/
Varnish configuration is shown bellow. Any suggestions? All other caching on the server is turned off.
#
# 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 https://www.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;
import std;
include "/etc/varnish/letsencrypt.vcl";
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "9000";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}
# Only allow purging from specific IPs
acl purge {
"localhost";
"127.0.0.1";
}
# This function is used when a request is send by a HTTP client (Browser)
sub vcl_recv {
# if (std.port(server.ip) != 443) {
# set req.http.location = "https://" + req.http.host + req.url;
# return(synth(301));
# }
# Normalize the header, remove the port (in case you're testing this on various TCP ports)
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# WooCommerce: The code below makes sure the AJAX "add to cart" function works
set req.url = regsub(req.url, "add-to-cart=\d+_\d+&", "");
set req.http.X-Forwarded-For = client.ip;
# Allow purging from ACL
if (req.method == "PURGE") {
# If not allowed then a error 405 is returned
if (!client.ip ~ purge) {
return(synth(405, "This IP is not allowed to send PURGE requests."));
}
# If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
return (purge);
}
# Post requests will not be cached
if (req.http.Authorization || req.method == "POST") {
return (pass);
}
# --- Wordpress specific configuration
# Did not cache the RSS feed
if (req.url ~ "/feed") {
return (pass);
}
# Blitz hack
if (req.url ~ "/mu-.*") {
return (pass);
}
# Did not cache the admin and login pages
if (req.url ~ "/wp-(login|admin)") {
return (pass);
}
# Do not cache the WooCommerce pages
### REMOVE IT IF YOU DO NOT USE WOOCOMMERCE ###
if (req.url ~ "/(cart|my-account|wc-api|checkout|addons|/?add-to-cart=)") {
return (pass);
}
# Remove the "has_js" cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
# Remove any Google Analytics based cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
# Remove the wp-settings-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");
# Remove the wp-settings-time-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");
# Remove the wp test cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^ *$") {
unset req.http.cookie;
}
# Cache the following files extensions
if (req.url ~ "\.(css|js|png|gif|jp(e)?g|swf|ico)") {
unset req.http.cookie;
}
# Normalize Accept-Encoding header and compression
# https://www.varnish-cache.org/docs/3.0/tutorial/vary.html
if (req.http.Accept-Encoding) {
# Do no compress compressed files...
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
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 {
unset req.http.Accept-Encoding;
}
}
# Check the cookies for wordpress-specific items
if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
return (pass);
}
if (!req.http.cookie) {
unset req.http.cookie;
}
# --- End of Wordpress specific configuration
# Did not cache HTTP authentication and HTTP Cookie
if (req.http.Authorization || req.http.Cookie) {
# Not cacheable by default
return (pass);
}
# Cache all others requests
return (hash);
}
# sub vcl_synth {
# if (resp.status == 301) {
# set resp.http.location = req.http.location;
# set resp.status = 301;
# return (deliver);
# }
# }
sub vcl_pipe {
# Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
if (req.http.upgrade) {
set bereq.http.upgrade = req.http.upgrade;
}
return (pipe);
}
sub vcl_pass {
return (fetch);
}
# The data on which the hashing will take place
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
# # If the client supports compression, keep that in a different cache
# if (req.http.Accept-Encoding) {
# hash_data(req.http.Accept-Encoding);
# }
# hash cookies for requests that have them
if (req.http.Cookie) {
hash_data(req.http.Cookie);
}
return (lookup);
}
# This function is used when a request is sent by our backend (Nginx server)
sub vcl_backend_response {
# Remove some headers we never want to see
unset beresp.http.Server;
unset beresp.http.X-Powered-By;
# Enable cache for all static files
# The same argument as the static caches from above: monitor your cache size, if you get data nuked out of it, consider giving up the static file cache.
# Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
if (bereq.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
unset beresp.http.set-cookie;
}
# Large static files are delivered directly to the end-user without
# waiting for Varnish to fully read the file first.
# Varnish 4 fully supports Streaming, so use streaming here to avoid locking.
if (bereq.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
unset beresp.http.set-cookie;
set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects
}
# Only allow cookies to be set if we're in admin area
if (beresp.http.Set-Cookie && bereq.url !~ "^/wp-(login|admin)" && bereq.url !~ "((wp/)?wp-(login|admin)|login)") {
unset beresp.http.Set-Cookie;
}
# don't cache response to posted requests or those with basic auth
if ( bereq.method == "POST" || bereq.http.Authorization ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# don't cache search results
if ( bereq.url ~ "\?s=" ){
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# only cache status ok
if ( beresp.status != 200 ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# A TTL of 24h
set beresp.ttl = 24h;
# Define the default grace period to serve cached content
set beresp.grace = 30s;
return (deliver);
}
# The routine when we deliver the HTTP request to the user
# Last chance to modify headers that are sent to the client
sub vcl_deliver {
# Called before a cached object is delivered to the client.
if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
# Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object
# and obj.hits may not be reset in some cases where bans are in use. See bug 1492 for details.
# So take hits with a grain of salt
set resp.http.X-Cache-Hits = obj.hits;
# Remove some headers: PHP version
unset resp.http.X-Powered-By;
# Remove some headers: Apache version & OS
unset resp.http.Server;
# Remove some heanders: Varnish
unset resp.http.Via;
#Proxy cache wordpress plugin use that header
unset resp.http.X-Varnish;
return (deliver);
}
sub vcl_purge {
# Only handle actual PURGE HTTP methods, everything else is discarded
if (req.method == "PURGE") {
# restart request
set req.http.X-Purge = "Yes";
return (restart);
}
}
sub vcl_init {
return (ok);
}
sub vcl_fini {
return (ok);
}
issue resolved. Need to add on backend response:
if (!(req.url ~ "(wp-login|wp-admin|cart|my-account|checkout|addons)")) {
unset beresp.http.set-cookie;
}

Wordpress Pemalinks not working with Varnish

I installed Varnish in a Docker image using Plesk CPanel on a WordPress website with pretty permalinks enabled. I used this guide:
https://www.plesk.com/blog/product-technology/varnish-wordpress-docker-container/
When I click on any link to an article or category, I am redirected back to the homepage with a question mark inserted and the rest of the URL. ie
https://example.com/?news/world-leaders-to-meet/
instead of
https://example.com/news/world-leaders-to-meet/
Everything works fine when I disable Varnish. I even tried cloning the website to a subdomain and permalinks work on the subdomain with Varnish enabled. I have disabled plugins and it makes no difference.
What should I do to fix the problem?
Contents of default.vcl (with fake IP address for host)
vcl 4.0;
import std;
# MAIN CONFIGURATION
backend default {
.host = "123.123.123.123";
.port = "7080";
}
# ALLOWED IP OF PURGE REQUESTS
acl purge {
"localhost";
"127.0.0.1";
"172.17.0.1";
"172.17.0.2";
"123.123.123.123";
}
#THE RECV FUNCTION
# Happens before we check if we have this in cache already
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 POST AND EDIT PAGES
if (req.url ~ "(wp-admin|post\.php|edit\.php|wp-login)") {
return(pass);
}
# DO NOT CACHE SEARCH RESULTS
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);
}
# DO NOT CACHE LOGGED IN USERS (THIS OCCURS IN FETCH TOO)
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);
}
# STRIP OUT URL PARAMETERS THAT LEAD TO MULTIPLE REDUNDANT CACHING
if (req.url ~ "(\?|&)(gclid|utm_[a-z]+)=") {
set req.url = regsuball(req.url, "(gclid|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", "");
set req.url = regsub(req.url, "[?|&]+$", "");
}
}
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 {
# IF NOT WP-ADMIN THEN UNSET COOKIES AND SET THE AMOUNT OF TIME THIS PAGE WILL STAY CACHED (TTL)
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 0) {
# IF THIS PAGE IS ALREADY CACHED THEN RETURN A 'HIT' TEXT
set resp.http.X-Cache = "HIT";
} else {
# IF THIS IS A MISS RETURN THAT IN THE HEADER
set resp.http.X-Cache = "MISS";
}
}
Your VCL code looks pretty legit. My guess is that it might be the URL rewriting logic in your webserver (Apache or Nginx), or maybe even WordPress that does this redirection.
Varnishlog output
The easiest way to find out is by running varnishlog while the issue is occurring. Feel free to post a redacted record of the varnishlog output.
If you need help operating Varnishlog, have look at the following blog post I wrote a couple of years ago: https://feryn.eu/blog/varnishlog-measure-varnish-cache-performance/.
Lack of SSL awareness
Another possibility is that WordPress is not aware of the fact that an HTTP-base reverse caching proxy sits in front if it.
Varnish currently doesn't offer native SSL/TLS support, so SSL needs to be terminated and interactions between Varnish & WordPress happen over plain HTTP.
If WordPress is set up to automatically redirect plain HTTP requests into HTTPS request, you might end up in a loop.
If that is the case, please have a look at the following blog post I wrote about this: https://feryn.eu/blog/mixed-content-and-err-too-many-redirects-in-wordpress/

Varnish Not caching wordpress website. Tried some solutions present in blogs. Nothing worked for me

I was able to configure varnish, but it is not caching i guess. In the response header, i see these attributes:
Url : corp.zip.pr
Age →0
Via →1.1 varnish-v4
X-Varnish →98319
My default.vcl file is as below:
# 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 = "127.0.0.1";
.port = "8080";
}
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 (req.http.X-Purge-Method == "regex") {
ban("req.url ~ " + req.url + " && req.http.host ~ " + req.http.host);
return (synth(200, "Banned."));
} else {
return (purge);
}
}
if (req.url ~ "wp-admin|wp-login") {
return (pass);
}
if (!(req.url ~ "wp-(login|admin)")) {
unset req.http.cookie;
}
set req.http.cookie = regsuball(req.http.cookie, "wp-settings-d+=[^;]+(; )?", "");
set req.http.cookie = regsuball(req.http.cookie, "wp-settings-time-d+=[^;]+(; )?", "");
set req.http.cookie = regsuball(req.http.cookie, "wordpress_test_cookie=[^;]+(; )?", "");
if (req.http.cookie == "") {
unset req.http.cookie;
}
}
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 (beresp.ttl == 120s) {
set beresp.ttl = 600s;
}
}
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.
}
Moreover, varnishlog is not working. when i type varnishlog in the terminal, i see the below message.
Cannot open /opt/bitnami/varnish/var/varnish/_.vsm: No such file or directory
i checked the file location. _.vsm is not present here. i checked for the vsm location used by varnishd process. it was different
/var/lib/varnish/ip-172-31-10-1/
You don't have return (hash); In your vcl_recv function, add it at the end of function body, restart varnish and check if it work.
I thing your vcl is weird, maybe try this for example https://www.htpcguides.com/configure-wordpress-varnish-4-cache-with-apache-or-nginx/

varnish not cacheable symfony

i test on page http://www.okw-rutex.pl/ this site include js file
varnish cache for file - http://miejsce.eu/shared,4980,101.js
here is headers for this file
Request URL:http://miejsce.eu/shared,4980,101.js
Request Method:GET
Status Code:200 OK
Remote Address:188.165.215.9:80
Response Headers
view source
Accept-Ranges:bytes
Age:0
Cache-Control:max-age=86400, public
Connection:keep-alive
Content-Encoding:gzip
Content-Length:3673
Content-Type:text/html; charset=UTF-8
Date:Thu, 14 Jan 2016 13:35:56 GMT
Expires:Fri, 15 Jan 2016 13:35:57 GMT
Server:Apache/2.4.7 (Ubuntu)
Vary:Accept-Encoding
X-Cache:MISS
X-Cacheable:NO:Not Cacheable
X-Powered-By:PHP/5.5.9-1ubuntu4.14
XH:0
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4,pt;q=0.2,de;q=0.2,sk;q=0.2
Cache-Control:max-age=0
Connection:keep-alive
Host:miejsce.eu
Referer:http://www.okw-rutex.pl/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/47.0.2526.106 Chrome/47.0.2526.106 Safari/537.36
in symfony controller i use cache annotations -
#Cache(expires="1 day",public=true, maxage="86400")
in varnish config part return not cacheable is
} elsif (beresp.ttl <= 0s) {
# Varnish determined the object was not cacheable
set beresp.http.X-Cacheable = "NO:Not Cacheable";
how i can turn varnish cache on ?
if i refresh page with F5 (without sending Cache-Control:max-age=0)
still have
X-Cache:MISS
X-Cacheable:NO:Not Cacheable
here if full varnish config
more /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 https://www.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 = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
# Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
# if (req.method != "GET" && req.method != "HEAD") {
# return (pass);
# }
# Strip hash, server doesn't need it.
if (req.url ~ "\#") {
set req.url = regsub(req.url, "\#.*$", "");
}
# removes all cookies named _ and google analistics, tracking, utma, utmb...)
set req.http.Cookie = regsuball(req.http.Cookie, "(^|(?<=; )) *_.=[^;]+;? *", "\1");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
if (req.http.Cache-Control ~ "(?i)no-cache") {
if (! (req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) {
# return(purge); # Couple this with restart in vcl_purge and X-Purge header to avoid loops
unset req.http.Cache-Control;
}
}
# Large static files are delivered directly to the end-user without
# waiting for Varnish to fully read the file first. Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response()
if (req.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av]|webm)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# Remove all cookies for static files
if (req.url ~ "^[^?]*\.(bmp|mov|mp4|webm|avi|bz2|css|doc|eot|flv|gif|gz|ico|jpeg|jpg|js|less|pdf|png|rtf|swf|txt|woff|xml)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# 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.
set req.http.Surrogate-Capability = "abc=ESI/1.0";
if (req.http.X-Forwarded-Proto == "https" ) {
set req.http.X-Forwarded-Port = "443";
} else {
set req.http.X-Forwarded-Port = "80";
}
}
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 (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
# Enable cache for all static files
if (bereq.url ~ "^[^?]*\.(bmp|bz2|css|doc|eot|flv|gif|gz|ico|jpeg|jpg|js|less|mp[34]|pdf|png|rar|rtf|swf|tar|tgz|txt|wav|woff|xml|zip|webm)(\?.*)?$") {
unset beresp.http.set-cookie;
}
# Large static files are delivered directly to the end-user without
if (bereq.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av]|webm)(\?.*)?$") {
unset beresp.http.set-cookie;
set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, s
o only enable it for big objects
set beresp.do_gzip = false; # Don't try to compress it for storage
}
if (bereq.http.Cookie ~ "(UserID|_session)") {
set beresp.http.X-Cacheable = "NO:Got Session";
set beresp.uncacheable = true;
return (deliver);
} elsif (beresp.ttl <= 0s) {
# Varnish determined the object was not cacheable
set beresp.http.X-Cacheable = "NO:Not Cacheable";
} elsif (beresp.http.set-cookie) {
# You don't wish to cache content for logged in users
set beresp.http.X-Cacheable = "NO:Set-Cookie";
set beresp.uncacheable = true; return (deliver);
return (deliver);
} elsif (beresp.http.Cache-Control ~ "private") {
# You are respecting the Cache-Control=private header from the backend
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
set beresp.uncacheable = true;
} else {
# Varnish determined the object was cacheable
set beresp.http.X-Cacheable = "YES";
}
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.
if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
set resp.http.XH = obj.hits;
unset resp.http.X-Varnish;
unset resp.http.Via;
}
i change varnish config like here
#
# 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 https://www.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 = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
# Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
# if (req.method != "GET" && req.method != "HEAD") {
# return (pass);
# }
# Strip hash, server doesn't need it.
if (req.url ~ "\#") {
set req.url = regsub(req.url, "\#.*$", "");
}
# removes all cookies named _ and google analistics, tracking, utma, utmb...)
set req.http.Cookie = regsuball(req.http.Cookie, "(^|(?<=; )) *_.=[^;]+;? *", "\1");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
if (req.http.Cache-Control ~ "(?i)no-cache") {
if (! (req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) {
# return(purge); # Couple this with restart in vcl_purge and X-Purge header to avoid loops
unset req.http.Cache-Control;
}
}
# Large static files are delivered directly to the end-user without
# waiting for Varnish to fully read the file first. Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response()
if (req.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av]|webm)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# Remove all cookies for static files
if (req.url ~ "^[^?]*\.(bmp|mov|mp4|webm|avi|bz2|css|doc|eot|flv|gif|gz|ico|jpeg|jpg|js|less|pdf|png|rtf|swf|txt|woff|xml)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# 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.
set req.http.Surrogate-Capability = "abc=ESI/1.0";
if (req.http.X-Forwarded-Proto == "https" ) {
set req.http.X-Forwarded-Port = "443";
} else {
set req.http.X-Forwarded-Port = "80";
}
}
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 (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
# Enable cache for all static files
if (bereq.url ~ "^[^?]*\.(bmp|bz2|css|doc|eot|flv|gif|gz|ico|jpeg|jpg|js|less|mp[34]|pdf|png|rar|rtf|swf|tar|tgz|txt|wav|woff|xml|zip|webm)(\?.*)?$") {
unset beresp.http.set-cookie;
}
# Large static files are delivered directly to the end-user without
if (bereq.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av]|webm)(\?.*)?$") {
unset beresp.http.set-cookie;
set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects
set beresp.do_gzip = false; # Don't try to compress it for storage
}
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.
if (bereq.http.Cookie ~ "(UserID|_session)") {
set beresp.http.X-Cacheable = "NO:Got Session";
set beresp.uncacheable = true;
} elsif (beresp.ttl <= 0s) {
# Varnish determined the object was not cacheable
set beresp.http.X-Cacheable = "NO:Not Cacheable";
} elsif (beresp.http.set-cookie) {
# You don't wish to cache content for logged in users
set beresp.http.X-Cacheable = "NO:Set-Cookie";
set beresp.uncacheable = true;
} elsif (beresp.http.Cache-Control ~ "private") {
# You are respecting the Cache-Control=private header from the backend
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
set beresp.uncacheable = true;
} else {
# Varnish determined the object was cacheable
set beresp.http.X-Cacheable = "YES";
}
if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
set resp.http.XH = obj.hits;
unset resp.http.X-Varnish;
unset resp.http.Via;
}
this throw error
sudo service varnish restart
open files (-n) 1024
open files (-n) 1024
Error:
Message from VCC-compiler:
'bereq.http.Cookie': Not available in method 'vcl_deliver'.
At: ('input' Line 120 Pos 5)
if (bereq.http.Cookie ~ "(UserID|_session)") {
----#################-------------------------
Running VCC-compiler failed, exited with 2
VCL compilation failed
* Syntax check failed, not restarting
but removing log part from config allow to varnish cache HIT. How should look sub vcl_deliver with no cache info ?
vcl_backend_response is called before objects are written to the cache, so you are modifying the response before it enters the cache. That means that you are not seeing stale response headers. Move your diagnostics to vcl_deliver instead.

varnish 4 vcl wont compile

I am attempting to create a varnish file for a wordpress site, but I am getting the following compile error:
varnish_1 | Message from VCC-compiler:
varnish_1 | Unused acl purge, defined:
varnish_1 | ('input' Line 22 Pos 5)
varnish_1 | acl purge {
varnish_1 | ----#####--
varnish_1 |
varnish_1 | Running VCC-compiler failed, exited with 2
varnish_1 |
varnish_1 | VCL compilation failed
wp1_varnish_1 exited with code 2
The vcl file is below. If you remove the acl purge function it works totally fine. Any ideas? Thanks in advance.
#
# 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;
import directors;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "web";
.port = "80";
}
acl purge {
"localhost";
"127.0.0.1";
}
#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.
#}
#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.
#}
sub vcl_init {
# Called when VCL is loaded, before any requests pass through it. Typically used to initialize VMODs.
}
sub vcl_recv {
if (req.method == "PURGE") {
if (req.http.X-Purge-Method == "regex")
{
ban("req.url ~ " + req.url + " && req.http.host ~ " + req.http.host);
return (synth(200, "Banned."));
}
else
{
return (purge);
}
}
if (req.url ~ "\.(gif|jpg|jpeg|swf|ttf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.*$", "");
}
if (req.url ~ "\?(utm_(campaign|medium|source|term)|adParams|client|cx|eid|fbid|feed|ref(id|src)?|v(er|iew))=") {
set req.url = regsub(req.url, "\?.*$", "");
}
if (
req.url ~ "^/wp-(login|admin)" || req.url ~ "/wp-cron.php" || req.url ~ "/wp-content/uploads/"
|| req.url ~ "preview=true" || req.url ~ "xmlrpc.php" || req.url ~ "\?s=" || req.url ~ "/choose-your-logo"
|| req.url ~ "/cart" || req.url ~ "/checkout" || req.url ~ "/my-account" || req.url ~ "/addons"
) {
# do not use the cache
return(pass); // DO NOT CACHE
}
# WooCommerce
if (req.url ~ "\?add-to-cart=") {
# do not use the cache
return(pass); // DO NOT CACHE
}
# Kick DFind requests
if (req.url ~ "^/w00tw00t") {
return (synth(404, "Not Found"));
}
if (req.http.cookie) {
# Google Analytics
set req.http.Cookie = regsuball( req.http.Cookie, "(^|;\s*)(__utm[a-z]+)=([^;]*)", "");
set req.http.Cookie = regsuball( req.http.Cookie, "(^|;\s*)(_ga)=([^;]*)", "");
# Quant Capital
set req.http.Cookie = regsuball( req.http.Cookie, "(^|;\s*)(__qc[a-z]+)=([^;]*)", "");
# __gad __gads
set req.http.Cookie = regsuball( req.http.Cookie, "(^|;\s*)(__gad[a-z]+)=([^;]*)", "");
# Google Cookie consent (client javascript cookie)
set req.http.Cookie = regsuball( req.http.Cookie, "(^|;\s*)(displayCookieConsent)=([^;]*)", "");
# Other known Cookies: remove them (if found).
set req.http.Cookie = regsuball( req.http.Cookie, "(^|;\s*)(__CT_Data)=([^;]*)", "");
set req.http.Cookie = regsuball( req.http.Cookie, "(^|;\s*)(WRIgnore|WRUID)=([^;]*)", "");
# PostAction: Remove (once and if found) a ";" prefix followed by 0..n whitespaces.
# INFO \s* = 0..n whitespace characters
set req.http.Cookie = regsub( req.http.Cookie, "^;\s*", "" );
# PostAction: Unset the header if it is empty or 0..n whitespaces.
if ( req.http.cookie ~ "^\s*$" ) {
unset req.http.Cookie;
}
}
###
### Normalize the Accept-Language header
### We do not need a cache for each language-country combination! Just keep en-* and nl-* for future use.
### https://www.varnish-cache.org/docs/4.0/users-guide/increasing-your-hitrate.html#http-vary
if (req.http.Accept-Language) {
if (req.http.Accept-Language ~ "^en") {
set req.http.Accept-Language = "en";
} elsif (req.http.Accept-Language ~ "^nl") {
set req.http.Accept-Language = "nl";
} else {
# Unknown language. Set it to English.
set req.http.Accept-Language = "en";
}
}
}
# Drop any cookies Wordpress tries to send back to the client.
sub vcl_backend_response {
if ( (!(bereq.url ~ "(wp-(login|admin)|login)")) || (bereq.method == "GET") ) {
unset beresp.http.set-cookie;
set beresp.ttl = 1h;
}
if (bereq.url ~ "\.(gif|jpg|jpeg|swf|ttf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") {
set beresp.ttl = 48h;
}
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
sub vcl_hit {
if (req.method == "PURGE") {
return(synth(200,"OK"));
}
}
sub vcl_miss {
if (req.method == "PURGE") {
return(synth(404,"Not cached"));
}
}
The compiler is telling you the problem, and you already found the solution, remove the unused acl called purge:
Unused acl purge, defined:
The other option is to add a check to allow purge only from that acl:
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}

Resources