We have installed node queue module on Pressflow 6 + Varnish. For clearing the varnish cache for node queues, we developed rules using the Rules, and Cache action modules. Whenever we update the content, it is reflecting for logged in users, but it is not reflecting for anonymous users.

Could you please suggest us for how to clear varnish cache with rules or any custom code?


The Cache Expiration module is designed to clear items from caches, including Varnish.

This module acts as a grid to detect and act upon events that will expire URLs from caches like reverse proxy caches. The Cache Expiration module is a spinoff of the expiration code of the Boost expiration code so other modules can use it. This module stands on its own and does not use Boost in any way.


You may install Varnish HTTP Accelerator Integration module and set the following lines in your settings file:

 * Varnishd Configuration
 * This cache implementation can be used together with Varnish. You can't really use it to store or get any values, but you can use it to purge your caches.
 * This cache implementation should ONLY be used for cache_page and no other cache bin!
if (class_exists('VarnishCache')) {
  // Add Varnish as the page cache handler.
  $conf['cache_backends'][] = 'sites/all/modules/contrib/varnish/varnish.cache.inc';
  // Drupal 7 does not cache pages when we invoke hooks during bootstrap. This needs to be disabled.
  $conf['page_cache_invoke_hooks'] = FALSE;
  $conf['cache_class_cache_page'] = 'VarnishCache';

Then if module is enabled, standard clear cache should invoke clear caching for Varnish.

You may also call purge directly via calling: varnish_purge_all_pages();

Alternatively you can use curl, ie.

curl -X PURGE -H "Host: domain.com"

Also check:


For running Drupal 8 websites using Varnish Cache, install the Purge module. Purge will manage the Varnish Cache from Drupal 8 admin unless you need to support Cache Tags.

To Support Cache Tags with Varnish, install the Varnish Purger module. Visit this GitLab page for an example of the Varnish VCL code required to support the Purge and Varnish Purge modules:

vcl 4.0;
import std;
import directors;

# This Varnish VCL has been adapted from the Four Kitchens VCL for Varnish 3.
# This VCL is for using cache tags with drupal 8. Minor chages of VCL provided by Jeff Geerling.

# Default backend definition. Points to Apache, normally. 
# Apache is in this config on port 80.
backend default {
    .host = "";
    .port = "80";
    .first_byte_timeout = 300s;

# Access control list for PURGE requests.
# Here you need to put the IP address of your web server
acl purge {

# Respond to incoming requests.
sub vcl_recv {
    # Add an X-Forwarded-For header with the client IP address.
    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;

    # Only allow PURGE requests from IP addresses in the 'purge' ACL.
    if (req.method == "PURGE") {
        if (!client.ip ~ purge) {
            return (synth(405, "Not allowed."));
        return (hash);

    # Only allow BAN requests from IP addresses in the 'purge' ACL.
    if (req.method == "BAN") {
        # Same ACL check as above:
        if (!client.ip ~ purge) {
            return (synth(403, "Not allowed."));

        # Logic for the ban, using the Cache-Tags header. For more info
        # see https://github.com/geerlingguy/drupal-vm/issues/397.
        if (req.http.Cache-Tags) {
            ban("obj.http.Cache-Tags ~ " + req.http.Cache-Tags);
        else {
            return (synth(403, "Cache-Tags header missing."));

        # Throw a synthetic page so the request won't go to the backend.
        return (synth(200, "Ban added."));

    # Only cache GET and HEAD requests (pass through POST requests).
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);

    # Pass through any administrative or AJAX-related paths.
    if (req.url ~ "^/status\.php$" ||
        req.url ~ "^/update\.php$" ||
        req.url ~ "^/admin$" ||
        req.url ~ "^/admin/.*$" ||
        req.url ~ "^/flag/.*$" ||
        req.url ~ "^.*/ajax/.*$" ||
        req.url ~ "^.*/ahah/.*$") {
           return (pass);

    # Removing cookies for static content so Varnish caches these files.
    if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
        unset req.http.Cookie;

    # Remove all cookies that Drupal doesn't need to know about. We explicitly
    # list the ones that Drupal does need, the SESS and NO_CACHE. If, after
    # running this code we find that either of these two cookies remains, we
    # will pass as the page cannot be cached.
    if (req.http.Cookie) {
        # 1. Append a semi-colon to the front of the cookie string.
        # 2. Remove all spaces that appear after semi-colons.
        # 3. Match the cookies we want to keep, adding the space we removed
        #    previously back. (\1) is first matching group in the regsuball.
        # 4. Remove all other cookies, identifying them by the fact that they have
        #    no space after the preceding semi-colon.
        # 5. Remove all spaces and semi-colons from the beginning and end of the
        #    cookie string.
        set req.http.Cookie = ";" + req.http.Cookie;
        set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
        set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
        set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
        set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");

        if (req.http.Cookie == "") {
            # If there are no remaining cookies, remove the cookie header. If there
            # aren't any cookie headers, Varnish's default behavior will be to cache
            # the page.
            unset req.http.Cookie;
        else {
            # If there is any cookies left (a session or NO_CACHE cookie), do not
            # cache the page. Pass it on to Apache directly.
            return (pass);

# Set a header to track a cache HITs and MISSes.
sub vcl_deliver {
    # Remove ban-lurker friendly custom headers when delivering to client.
    unset resp.http.X-Url;
    unset resp.http.X-Host;
    # Comment these for easier Drupal cache tag debugging in development.
    unset resp.http.Cache-Tags;
    unset resp.http.X-Drupal-Cache-Contexts;

    if (obj.hits > 0) {
        set resp.http.Cache-Tags = "HIT";
    else {
        set resp.http.Cache-Tags = "MISS";

# Instruct Varnish what to do in the case of certain backend responses (beresp).
sub vcl_backend_response {
    # Set ban-lurker friendly custom headers.
    set beresp.http.X-Url = bereq.url;
    set beresp.http.X-Host = bereq.http.host;

    # Cache 404s, 301s, at 500s with a short lifetime to protect the backend.
    if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
        set beresp.ttl = 10m;

    # Don't allow static files to set cookies.
    # (?i) denotes case insensitive in PCRE (perl compatible regular expressions).
    # This list of extensions appears twice, once here and again in vcl_recv so
    # make sure you edit both and keep them equal.
    if (bereq.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
        unset beresp.http.set-cookie;

    # Allow items to remain in cache up to 6 hours past their cache expiration.
    set beresp.grace = 6h;

Note: This code is placed in the default.vcl for Varnish Cache & will enable support for Cache Tags in Drupal 8 with Purge.


I found a PHP example of how you can do it from a blog post:

$url = $_POST["url"];
$host = $_POST["host"];

$ip = "";
$port = "80";

$timeout = 1;
$verbose = 1;

# inits
$sock = fsockopen ($ip,$port,$errno, $errstr,$timeout);
if (!$sock) { echo "connections failed $errno $errstr"; exit; }

if ( !($url || $host) ) { echo "No params"; exit; }


$pcommand = "purge";
# Send command
$pcommand .= ".hash $url#$host#";

put ($pcommand);
put ("quit");

fclose ($sock);

function readit() {
  global $sock,$verbose;
  if (!$verbose) { return; }
  while ($sockstr = fgets($sock,1024)) {
    $str .= "rcv: " . $sockstr . "<br>";
  if ($verbose) { echo "$str\n"; }

function put($str) {
  global $sock,$verbose;
  fwrite ($sock, $str . "\r\n");
  if ($verbose) { echo "send: $str <br>\n"; }
  • 1
    googletorp, can you tell me what the program exactly does.so i can make modifications which are suitable for the various pages of my web site. – raghu Apr 2 '12 at 11:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.