Skip to content

Instantly share code, notes, and snippets.

@cybersholt
Forked from fevangelou/default.vcl_PREFACE.md
Created January 8, 2018 15:56
Show Gist options
  • Select an option

  • Save cybersholt/16befdf9a8a7090709e348e9bd5aa6fa to your computer and use it in GitHub Desktop.

Select an option

Save cybersholt/16befdf9a8a7090709e348e9bd5aa6fa to your computer and use it in GitHub Desktop.

Revisions

  1. @fevangelou fevangelou revised this gist Dec 1, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion default.vcl_PREFACE.md
    Original file line number Diff line number Diff line change
    @@ -62,4 +62,4 @@ However, if we want Varnish to allow frontend logins in Joomla, without breaking



    _**DOCUMENT LAST UPDATED: December 1st, 2016**_
    _**Updated on December 1st, 2016**_
  2. @fevangelou fevangelou revised this gist Dec 1, 2016. 1 changed file with 17 additions and 37 deletions.
    54 changes: 17 additions & 37 deletions default.vcl_PREFACE.md
    Original file line number Diff line number Diff line change
    @@ -2,17 +2,11 @@

    IMPORTANT: Read this before implementing one of the configuration files below (for either Varnish 3.x or 4.x+).

    USE: Replace the contents of the main Varnish configuration file located in /etc/varnish/default.vcl
    (root server access required - obviously) with the contents of the configuration you'll use (depending on your Varnish version)
    from the 2 examples provided below.
    USE: Replace the contents of the main Varnish configuration file located in /etc/varnish/default.vcl (root server access required - obviously) with the contents of the configuration you'll use (depending on your Varnish version) from the 2 examples provided below.

    IMPORTANT: The following setup assumes a 2 minute cache time. You can safely increase
    this to 5 mins for less busier sites or drop it to 1 min or even 30s for high traffic sites.
    IMPORTANT: The following setup assumes a 2 minute cache time. You can safely increase this to 5 mins for less busier sites or drop it to 1 min or even 30s for high traffic sites.

    This configuration requires an HTTP Header and a user cookie (see the Joomla section)
    to identify if a user is logged in a site, in order to bypass caching overall. If your CMS provides a way to add
    these 2 requirements, then you can use this configuration to speed up your site or entire server. You can even
    exclude the domains you don't want to cache if you're looking to use it in a multi-site setup.
    This configuration requires an HTTP Header and a user cookie (see the Joomla section) to identify if a user is logged in a site, in order to bypass caching overall. If your CMS provides a way to add these 2 requirements, then you can use this configuration to speed up your site or entire server. You can even exclude the domains you don't want to cache if you're looking to use it in a multi-site setup.



    @@ -21,10 +15,7 @@ Since Joomla v3.6, all you need to do to have Joomla play nicely with Varnish is

    Or you can install this handy plugin from JoomlaWorks http://www.joomlaworks.net/downloads/?f=plg_urlnormalizer-v1.1_j1.5-3.x.zip which covers all Joomla versions from 1.5 to 3.x and extends/improves the built-in changes introduced in Joomla v3.6 (as stated above).

    If you're using Joomla before version 3.6 and you don't wish to use the plugin above, you need to do the following:
    This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether
    some user is logged in or not inside Joomla. To insert the HTTP header, simply append the following code block
    in your template's "index.php" file, right after the line:
    If you're using Joomla before version 3.6 and you don't wish to use the plugin above, you need to do the following: This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether some user is logged in or not inside Joomla. To insert the HTTP header, simply append the following code block in your template's "index.php" file, right after the line:
    ```
    defined('_JEXEC') or die;
    ```
    @@ -53,33 +44,22 @@ if ($getUserState->guest) {
    // Make Joomla Varnish-friendly [FINISH]
    ```

    IMPORTANT: If you use K2 (getk2.org) in your Joomla site, simply set the "Cookie Domain" option in the K2 parameters
    ("Advanced" tab) and all the above will be automatically enabled for your entire Joomla site.
    **IMPORTANT: If you use K2 (getk2.org) in your Joomla site, simply set the "Cookie Domain" option in the K2 parameters
    ("Advanced" tab) and all the above will be automatically enabled for your entire Joomla site.**



    ## HOW TO HANDLE FRONTEND LOGINS (e.g. for use with member areas, forums etc.)
    It is important for you to understand that since Joomla (in a very amateur way) uses session cookies for any user
    (even guests) supposedly for additional security (debatable), Varnish *cannot* work with Joomla out-of-the-box. If
    you installed Varnish without any modification to its configuration besides the cache time, it could not properly
    cache Joomla content because of the session cookies Joomla uses for both guest and logged in visitors. To bypass
    Joomla's behaviour, we must additionally set Varnish to strip any cookies set by Joomla, except for a specific one (userID).
    For even better control, we also set a custom HTTP header (X-Logged-In), which we have Varnish check on all requests. All
    this is explained how to integrate into Joomla via your template in the code sample above.
    However, if we want Varnish to allow frontend logins in Joomla, without breaking Joomla (because we strip its session cookies),
    we must explicitly tell Varnish which entry pages (=login pages) not to cache. Such a page could be for example the default
    Joomla login form (e.g. with an alias "login"). In the 2 Varnish exclusion lists defined in the configuration below, we would add
    "^/login" to make sure Varnish completely switches off when a user visits this page. In that case, Joomla's session cookie gets
    set and the form can be submitted normally, passing all Joomla security checks. Same goes for any page in Joomla that requires
    user input: a contact form, a newsletter signup form, a forum, comments and so on. So the solution to keep in mind is simple:
    - If the action requires the user to login first (e.g. a forum), we must create a specific/unique page for users to login first.
    Once they log in, Varnish switches off completely and then a user can post in the forum or write comments or use a contact form
    as if Varnish did not exist. If the user continues to browse the site while logged in, Varnish will be completely off ONLY for
    this user. If the user logs out, Varnish will kick back in.
    - If the action does not require a user to be logged in first, e.g. a contact form, we simply exclude the contact form's URL from
    Varnish, in which case -again- Varnish will switch off completely and the user will be able to submit the form passing the
    Joomla security checks. If the user browses anywhere else in the site, Varnish will kick back in.
    ### HOW TO HANDLE FRONTEND LOGINS (e.g. for use with member areas, forums etc.)
    It is important for you to understand that since Joomla (in a very amateur way) uses session cookies for any user (even guests) supposedly for additional security (debatable), Varnish *cannot* work with Joomla out-of-the-box.

    If you installed Varnish without any modification to its configuration besides the cache time, it could not properly cache Joomla content because of the session cookies Joomla uses for both guest and logged in visitors. To bypass Joomla's behaviour, we must additionally set Varnish to strip any cookies set by Joomla, except for a specific one (userID). For even better control, we also set a custom HTTP header (X-Logged-In), which we have Varnish check on all requests. All this is explained how to integrate into Joomla via your template in the code sample above.

    However, if we want Varnish to allow frontend logins in Joomla, without breaking Joomla (because we strip its session cookies), we must explicitly tell Varnish which entry pages (=login pages) not to cache. Such a page could be for example the default Joomla login form (e.g. with an alias "login"). In the 2 Varnish exclusion lists defined in the configuration below, we would add "^/login" to make sure Varnish completely switches off when a user visits this page. In that case, Joomla's session cookie gets set and the form can be submitted normally, passing all Joomla security checks. Same goes for any page in Joomla that requires user input: a contact form, a newsletter signup form, a forum, comments and so on. So the solution to keep in mind is simple:

    *** DOCUMENT LAST UPDATED: December 1st, 2016 ***
    - If the action requires the user to login first (e.g. a forum), we must create a specific/unique page for users to login first. Once they log in, Varnish switches off completely and then a user can post in the forum or write comments or use a contact form as if Varnish did not exist. If the user continues to browse the site while logged in, Varnish will be completely off ONLY for this user. If the user logs out, Varnish will kick back in.

    - If the action does not require a user to be logged in first, e.g. a contact form, we simply exclude the contact form's URL from Varnish, in which case -again- Varnish will switch off completely and the user will be able to submit the form passing the Joomla security checks. If the user browses anywhere else in the site, Varnish will kick back in.



    _**DOCUMENT LAST UPDATED: December 1st, 2016**_
  3. @fevangelou fevangelou revised this gist Dec 1, 2016. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions default.vcl_PREFACE.md
    Original file line number Diff line number Diff line change
    @@ -17,8 +17,7 @@ exclude the domains you don't want to cache if you're looking to use it in a mul


    ## JOOMLA & VARNISH
    Since Joomla v3.6, all you need to do to have Joomla play nicely with Varnish is add your exclusion points (URLs)
    - see the 2 blocks starting with "Exclude the following paths..." below in the configuration.
    Since Joomla v3.6, all you need to do to have Joomla play nicely with Varnish is add your exclusion points (URLs). Just have a look at the 2 blocks starting with "Exclude the following paths..." below in the Varnish configurations.

    Or you can install this handy plugin from JoomlaWorks http://www.joomlaworks.net/downloads/?f=plg_urlnormalizer-v1.1_j1.5-3.x.zip which covers all Joomla versions from 1.5 to 3.x and extends/improves the built-in changes introduced in Joomla v3.6 (as stated above).

  4. @fevangelou fevangelou revised this gist Dec 1, 2016. 1 changed file with 9 additions and 7 deletions.
    16 changes: 9 additions & 7 deletions default.vcl_PREFACE.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,4 @@

    ##########################################################################################
    ### The perfect Varnish configuration for Joomla, WordPress & other CMS based websites ###
    ##########################################################################################
    # The perfect Varnish configuration for Joomla, WordPress & other CMS based websites

    IMPORTANT: Read this before implementing one of the configuration files below (for either Varnish 3.x or 4.x+).

    @@ -19,19 +16,23 @@ exclude the domains you don't want to cache if you're looking to use it in a mul



    === JOOMLA & VARNISH ===
    ## JOOMLA & VARNISH
    Since Joomla v3.6, all you need to do to have Joomla play nicely with Varnish is add your exclusion points (URLs)
    - see the 2 blocks starting with "Exclude the following paths..." below in the configuration.

    Or you can install this handy plugin from JoomlaWorks http://www.joomlaworks.net/downloads/?f=plg_urlnormalizer-v1.1_j1.5-3.x.zip which covers all Joomla versions from 1.5 to 3.x and extends/improves the built-in changes introduced in Joomla v3.6 (as stated above).

    If you're using Joomla before version 3.6, you need to do the following:
    If you're using Joomla before version 3.6 and you don't wish to use the plugin above, you need to do the following:
    This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether
    some user is logged in or not inside Joomla. To insert the HTTP header, simply append the following code block
    in your template's "index.php" file, right after the line:
    ```
    defined('_JEXEC') or die;
    ```

    ...and make sure you set the $cookieDomain value:

    ```
    // Make Joomla Varnish-friendly [START]
    $cookieDomain = 'domain.tld'; // Replace "domain.tld" with your "naked" domain
    @@ -51,13 +52,14 @@ if ($getUserState->guest) {
    }
    }
    // Make Joomla Varnish-friendly [FINISH]
    ```

    IMPORTANT: If you use K2 (getk2.org) in your Joomla site, simply set the "Cookie Domain" option in the K2 parameters
    ("Advanced" tab) and all the above will be automatically enabled for your entire Joomla site.



    === HOW TO HANDLE FRONTEND LOGINS (e.g. for use with member areas, forums etc.) ===
    ## HOW TO HANDLE FRONTEND LOGINS (e.g. for use with member areas, forums etc.)
    It is important for you to understand that since Joomla (in a very amateur way) uses session cookies for any user
    (even guests) supposedly for additional security (debatable), Varnish *cannot* work with Joomla out-of-the-box. If
    you installed Varnish without any modification to its configuration besides the cache time, it could not properly
  5. @fevangelou fevangelou renamed this gist Dec 1, 2016. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion default.vcl_PREFACE.txt → default.vcl_PREFACE.md
    Original file line number Diff line number Diff line change
    @@ -23,6 +23,8 @@ exclude the domains you don't want to cache if you're looking to use it in a mul
    Since Joomla v3.6, all you need to do to have Joomla play nicely with Varnish is add your exclusion points (URLs)
    - see the 2 blocks starting with "Exclude the following paths..." below in the configuration.

    Or you can install this handy plugin from JoomlaWorks http://www.joomlaworks.net/downloads/?f=plg_urlnormalizer-v1.1_j1.5-3.x.zip which covers all Joomla versions from 1.5 to 3.x and extends/improves the built-in changes introduced in Joomla v3.6 (as stated above).

    If you're using Joomla before version 3.6, you need to do the following:
    This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether
    some user is logged in or not inside Joomla. To insert the HTTP header, simply append the following code block
    @@ -79,4 +81,4 @@ user input: a contact form, a newsletter signup form, a forum, comments and so o



    *** DOCUMENT LAST UPDATED: September 21st, 2016 ***
    *** DOCUMENT LAST UPDATED: December 1st, 2016 ***
  6. @fevangelou fevangelou revised this gist Nov 29, 2016. 2 changed files with 91 additions and 92 deletions.
    64 changes: 18 additions & 46 deletions for_Varnish_3.x_default.vcl
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@

    backend default {
    .host = "127.0.0.1"; # don't change this if the web server is on the same machine
    .port = "XXXX"; # replace XXXX with your web server's port
    .port = "XXXX"; # replace XXXX with your web server's (internal) port, e.g. 8080
    }

    sub vcl_recv {
    @@ -30,6 +30,9 @@ sub vcl_recv {
    }
    }

    # httpoxy
    unset req.http.proxy;

    # Non-RFC2616 or CONNECT which is weird.
    if (
    req.request != "GET" &&
    @@ -103,20 +106,12 @@ sub vcl_recv {
    }
    }

    # Cache files with these extensions
    if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # Remove all cookies for static files & deliver directly
    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|ogg|ogm|opus|otf|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 (lookup);
    }

    # Set how long Varnish will cache content depending on whether your backend is healthy or not
    if (req.backend.healthy) {
    # Remember to adjust beresp.ttl & beresp.http.Cache-Control inside vcl_fetch()
    # to the same time
    set req.grace = 2m;
    } else {
    set req.grace = 1h;
    }

    return (lookup);

    }
    @@ -182,44 +177,21 @@ sub vcl_fetch {
    unset beresp.http.Set-Cookie;
    }

    # Allow items to be stale if needed (this value should be the same as with "set req.grace"
    # inside the sub vcl_recv {…} block (the 2nd part of the if/else statement)
    set beresp.grace = 1h;

    # Serve pages from the cache should we get a sudden error and re-check in 3 minutes
    if (beresp.status == 503 || beresp.status == 502 || beresp.status == 501 || beresp.status == 500) {
    set beresp.grace = 3m;
    return (restart);
    }

    # This is how long Varnish will keep cached content.
    # If you change it, remember to adjust "beresp.http.Cache-Control" lower and
    # "req.grace" in the vcl_recv() section
    set beresp.ttl = 2m;

    # OPTIONAL:
    # Nice trick from https://www.varnish-cache.org/trac/wiki/VCLExampleIgnoreCacheHeadersFromBackend
    # Essentially caches anything with a cache time lower than the specified time.
    # May not work on all cases so use with caution.
    #if (beresp.ttl < 2m) {
    # set beresp.ttl = 2m;
    #}

    # Unset the "etag" header (suggested)
    unset beresp.http.etag;

    # Unset the "pragma" header
    unset beresp.http.Pragma;

    # Modify "expires" header - https://www.varnish-cache.org/trac/wiki/VCLExampleSetExpires
    set beresp.http.Expires = "" + (now + beresp.ttl);
    # Allow stale content, in case the backend goes down
    set beresp.grace = 6h;

    # If your backend server does not set the right caching headers for static assets,
    # you can set them below (uncomment first and change 604800 - which 1 week - to whatever you
    # want (in seconds)
    #if (req.url ~ "\.(ico|jpg|jpeg|gif|png|bmp|webp|tiff|svg|svgz|pdf|mp3|flac|ogg|mid|midi|wav|mp4|webm|mkv|ogv|wmv|eot|otf|woff|ttf|rss|atom|zip|7z|tgz|gz|rar|bz2|tar|exe|doc|docx|xls|xlsx|ppt|pptx|rtf|odt|ods|odp)(\?[a-zA-Z0-9=]+)$") {
    # set beresp.http.Cache-Control = "public, max-age=604800";
    #}
    # This is how long Varnish will keep cached content
    set beresp.ttl = 2m;

    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|ogg|ogm|opus|otf|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;
    }

    # We have content to cache, but it's got no-cache or other Cache-Control values sent
    # So let's reset it to our main caching time (2m as used in this example configuration)
    @@ -228,8 +200,8 @@ sub vcl_fetch {
    # cache time respectively.
    # This final setting will normalize CMSs like Joomla which set max-age=0 even when
    # Joomla's cache is enabled.
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0"){
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=600";
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0") {
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=480";
    }

    return (deliver);
    @@ -247,7 +219,7 @@ sub vcl_deliver {
    ) {
    set resp.http.X-Domain-Status = "EXCLUDED";
    }
    # Enforce redirect to HTTPS for specified domains only
    if (
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)" &&
    119 changes: 73 additions & 46 deletions for_Varnish_4.x_or_newer_default.vcl
    Original file line number Diff line number Diff line change
    @@ -17,7 +17,7 @@ import std;
    # Default backend definition. Set this to point to your content server.
    backend default {
    .host = "127.0.0.1"; # don't change this if the web server is on the same machine
    .port = "XXXX"; # replace XXXX with your web server's port
    .port = "XXXX"; # replace XXXX with your web server's (internal) port, e.g. 8080
    }

    sub vcl_recv {
    @@ -39,8 +39,6 @@ sub vcl_recv {
    set req.http.X-Forwarded-For = req.http.X-Real-IP;
    } else if (req.http.X-Forwarded-For) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    # In Varnish 4.x, comment the above line & uncomment the following
    #set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip;
    } else {
    set req.http.X-Forwarded-For = client.ip;
    }
    @@ -49,6 +47,9 @@ sub vcl_recv {
    # httpoxy
    unset req.http.proxy;

    # Normalize the query arguments
    set req.url = std.querysort(req.url);

    # Non-RFC2616 or CONNECT which is weird.
    if (
    req.method != "GET" &&
    @@ -76,6 +77,9 @@ sub vcl_recv {
    req.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    req.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    #set req.http.Cache-Control = "private, max-age=0, no-cache, no-store";
    #set req.http.Expires = "Mon, 01 Jan 2001 00:00:00 GMT";
    #set req.http.Pragma = "no-cache";
    return (pass);
    }

    @@ -87,43 +91,57 @@ sub vcl_recv {
    if(
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/socialconnect" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/contact" ||
    req.url ~ "^/connect" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/any-other-url-path"
    req.url ~ "^/wp-login.php"
    ) {
    #set req.http.Cache-Control = "private, max-age=0, no-cache, no-store";
    #set req.http.Expires = "Mon, 01 Jan 2001 00:00:00 GMT";
    #set req.http.Pragma = "no-cache";
    return (pass);
    }

    # Don't cache ajax requests
    if(req.http.X-Requested-With == "XMLHttpRequest" || req.url ~ "nocache") {
    #set req.http.Cache-Control = "private, max-age=0, no-cache, no-store";
    #set req.http.Expires = "Mon, 01 Jan 2001 00:00:00 GMT";
    #set req.http.Pragma = "no-cache";
    return (pass);
    }

    # Check for the custom "X-Logged-In" header (used by K2 and other apps) to identify
    # if the visitor is a guest, then unset any cookie (including session cookies) provided
    # it's not a POST request.
    if(req.http.X-Logged-In == "False" && req.method != "POST"){
    if(req.http.X-Logged-In == "False" && req.method != "POST") {
    unset req.http.Cookie;
    }

    # Properly handle different encoding types
    if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    unset req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    unset req.http.Accept-Encoding;
    }
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    unset req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    unset req.http.Accept-Encoding;
    }
    }

    # Cache files with these extensions
    if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    #if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # return (hash);
    #}

    # Remove all cookies for static files & deliver directly
    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|ogg|ogm|opus|otf|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);
    }

    @@ -145,6 +163,16 @@ sub vcl_backend_response {
    }
    */

    # Don't cache 50x responses
    if (
    beresp.status == 500 ||
    beresp.status == 502 ||
    beresp.status == 503 ||
    beresp.status == 504
    ) {
    return (abandon);
    }

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    @@ -153,11 +181,16 @@ sub vcl_backend_response {
    if(
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/socialconnect" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/contact" ||
    bereq.url ~ "^/connect" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/any-other-url-path"
    bereq.url ~ "^/wp-login.php"
    ) {
    #set beresp.http.Cache-Control = "private, max-age=0, no-cache, no-store";
    #set beresp.http.Expires = "Mon, 01 Jan 2001 00:00:00 GMT";
    #set beresp.http.Pragma = "no-cache";
    set beresp.uncacheable = true;
    return (deliver);
    }
    @@ -171,12 +204,18 @@ sub vcl_backend_response {
    bereq.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    bereq.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    #set beresp.http.Cache-Control = "private, max-age=0, no-cache, no-store";
    #set beresp.http.Expires = "Mon, 01 Jan 2001 00:00:00 GMT";
    #set beresp.http.Pragma = "no-cache";
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache ajax requests
    if(beresp.http.X-Requested-With == "XMLHttpRequest" || bereq.url ~ "nocache") {
    #set beresp.http.Cache-Control = "private, max-age=0, no-cache, no-store";
    #set beresp.http.Expires = "Mon, 01 Jan 2001 00:00:00 GMT";
    #set beresp.http.Pragma = "no-cache";
    set beresp.uncacheable = true;
    return (deliver);
    }
    @@ -197,37 +236,20 @@ sub vcl_backend_response {
    unset beresp.http.Set-Cookie;
    }

    # Allow items to be stale if needed (this value should be the same as with "set req.grace"
    # inside the sub vcl_recv {…} block (the 2nd part of the if/else statement)
    set beresp.grace = 1h;

    # Serve pages from the cache should we get a sudden error and re-check in 3 minutes
    if (beresp.status == 503 || beresp.status == 502 || beresp.status == 501 || beresp.status == 500) {
    set beresp.grace = 3m;
    return (retry);
    }

    # This is how long Varnish will keep cached content.
    # If you change it, remember to adjust "beresp.http.Cache-Control" lower and
    # "req.grace" in the vcl_recv() section
    set beresp.ttl = 2m;

    # OPTIONAL:
    # Nice trick from https://www.varnish-cache.org/trac/wiki/VCLExampleIgnoreCacheHeadersFromBackend
    # Essentially caches anything with a cache time lower than the specified time.
    # May not work on all cases so use with caution.
    #if (beresp.ttl < 2m) {
    # set beresp.ttl = 2m;
    #}

    # Unset the "etag" header (suggested)
    unset beresp.http.etag;

    # Unset the "pragma" header
    unset beresp.http.Pragma;

    # Allow stale content, in case the backend goes down
    set beresp.grace = 6h;

    # This is how long Varnish will keep cached content
    set beresp.ttl = 2m;

    # Modify "expires" header - https://www.varnish-cache.org/trac/wiki/VCLExampleSetExpires
    set beresp.http.Expires = "" + (now + beresp.ttl);
    #set beresp.http.Expires = "" + (now + beresp.ttl);

    # If your backend server does not set the right caching headers for static assets,
    # you can set them below (uncomment first and change 604800 - which 1 week - to whatever you
    @@ -236,15 +258,20 @@ sub vcl_backend_response {
    # set beresp.http.Cache-Control = "public, max-age=604800";
    #}

    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|ogg|ogm|opus|otf|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;
    set beresp.do_stream = true;
    }

    # We have content to cache, but it's got no-cache or other Cache-Control values sent
    # So let's reset it to our main caching time (2m as used in this example configuration)
    # The additional parameters specified (stale-while-revalidate & stale-if-error) are used
    # by modern browsers to better control caching. Set there to twice & five times your main
    # cache time respectively.
    # This final setting will normalize CMSs like Joomla which set max-age=0 even when
    # Joomla's cache is enabled.
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0"){
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=600";
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0") {
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=480";
    }

    return (deliver);
  7. @fevangelou fevangelou revised this gist Sep 21, 2016. 3 changed files with 2 additions and 1 deletion.
    1 change: 0 additions & 1 deletion default.vcl → default.vcl_PREFACE.txt
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@
    === PREFACE ===

    ##########################################################################################
    ### The perfect Varnish configuration for Joomla, WordPress & other CMS based websites ###
    1 change: 1 addition & 0 deletions for_Varnish_3.x_default.vcl
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@

    ##############################################################################################
    ### The perfect Varnish 3.x configuration for Joomla, WordPress & other CMS based websites ###
    ##############################################################################################
    1 change: 1 addition & 0 deletions for_Varnish_4.x_or_newer_default.vcl
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@

    ###############################################################################################
    ### The perfect Varnish 4.x+ configuration for Joomla, WordPress & other CMS based websites ###
    ###############################################################################################
  8. @fevangelou fevangelou renamed this gist Sep 21, 2016. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions ...& other CMS based websites [PREFACE]_.txt → default.vcl
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    === PREFACE ===

    ##########################################################################################
    ### The perfect Varnish configuration for Joomla, WordPress & other CMS based websites ###
    ##########################################################################################
  9. @fevangelou fevangelou renamed this gist Sep 21, 2016. 1 changed file with 0 additions and 0 deletions.
  10. @fevangelou fevangelou revised this gist Sep 21, 2016. 2 changed files with 280 additions and 280 deletions.
    82 changes: 41 additions & 41 deletions for_Varnish_3.x_default.vcl
    Original file line number Diff line number Diff line change
    @@ -49,12 +49,12 @@ sub vcl_recv {

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    req.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    req.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    return (pass);
    }
    @@ -65,11 +65,11 @@ sub vcl_recv {
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/any-other-url-path"
    ) {
    return (pass);
    @@ -89,17 +89,17 @@ sub vcl_recv {

    # Properly handle different encoding types
    if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    remove req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    remove req.http.Accept-Encoding;
    }
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    remove req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    remove req.http.Accept-Encoding;
    }
    }

    # Cache files with these extensions
    @@ -139,24 +139,24 @@ sub vcl_fetch {
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/any-other-url-path"
    ) {
    return (hit_for_pass);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    bereq.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    bereq.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    return (hit_for_pass);
    }
    @@ -247,14 +247,14 @@ sub vcl_deliver {
    set resp.http.X-Domain-Status = "EXCLUDED";
    }
    # Enforce redirect to HTTPS for specified domains only
    if (
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)" &&
    req.http.X-Forwarded-Proto !~ "(?i)https"
    ) {
    set resp.http.Location = "https://" + req.http.host + req.url;
    set resp.status = 302;
    }
    # Enforce redirect to HTTPS for specified domains only
    if (
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)" &&
    req.http.X-Forwarded-Proto !~ "(?i)https"
    ) {
    set resp.http.Location = "https://" + req.http.host + req.url;
    set resp.status = 302;
    }
    */

    # Send special headers that indicate the cache status of each web page
    478 changes: 239 additions & 239 deletions for_Varnish_4.x_or_newer_default.vcl
    Original file line number Diff line number Diff line change
    @@ -22,263 +22,263 @@ backend default {
    sub vcl_recv {

    /*
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    return (pass);
    }
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    return (pass);
    }
    */

    # Forward client's IP to the backend
    if (req.restarts == 0) {
    if (req.http.X-Real-IP) {
    set req.http.X-Forwarded-For = req.http.X-Real-IP;
    } else if (req.http.X-Forwarded-For) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    # In Varnish 4.x, comment the above line & uncomment the following
    #set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip;
    } else {
    set req.http.X-Forwarded-For = client.ip;
    }
    }

    # httpoxy
    unset req.http.proxy;

    # Non-RFC2616 or CONNECT which is weird.
    if (
    req.method != "GET" &&
    req.method != "HEAD" &&
    req.method != "PUT" &&
    req.method != "POST" &&
    req.method != "TRACE" &&
    req.method != "OPTIONS" &&
    req.method != "DELETE"
    ) {
    return (pipe);
    }

    # We only deal with GET and HEAD by default
    if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    req.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    return (pass);
    }

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    # Forward client's IP to the backend
    if (req.restarts == 0) {
    if (req.http.X-Real-IP) {
    set req.http.X-Forwarded-For = req.http.X-Real-IP;
    } else if (req.http.X-Forwarded-For) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    # In Varnish 4.x, comment the above line & uncomment the following
    #set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip;
    } else {
    set req.http.X-Forwarded-For = client.ip;
    }
    }

    # httpoxy
    unset req.http.proxy;

    # Non-RFC2616 or CONNECT which is weird.
    if (
    req.method != "GET" &&
    req.method != "HEAD" &&
    req.method != "PUT" &&
    req.method != "POST" &&
    req.method != "TRACE" &&
    req.method != "OPTIONS" &&
    req.method != "DELETE"
    ) {
    return (pipe);
    }

    # We only deal with GET and HEAD by default
    if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    req.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    return (pass);
    }

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/any-other-url-path"
    ) {
    return (pass);
    }

    # Don't cache ajax requests
    if(req.http.X-Requested-With == "XMLHttpRequest" || req.url ~ "nocache") {
    return (pass);
    }

    # Check for the custom "X-Logged-In" header (used by K2 and other apps) to identify
    # if the visitor is a guest, then unset any cookie (including session cookies) provided
    # it's not a POST request.
    if(req.http.X-Logged-In == "False" && req.method != "POST"){
    unset req.http.Cookie;
    }

    # Properly handle different encoding types
    if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    unset req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    unset req.http.Accept-Encoding;
    }
    }

    # Cache files with these extensions
    if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    return (hash);
    }

    return (hash);
    ) {
    return (pass);
    }

    # Don't cache ajax requests
    if(req.http.X-Requested-With == "XMLHttpRequest" || req.url ~ "nocache") {
    return (pass);
    }

    # Check for the custom "X-Logged-In" header (used by K2 and other apps) to identify
    # if the visitor is a guest, then unset any cookie (including session cookies) provided
    # it's not a POST request.
    if(req.http.X-Logged-In == "False" && req.method != "POST"){
    unset req.http.Cookie;
    }

    # Properly handle different encoding types
    if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    unset req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    unset req.http.Accept-Encoding;
    }
    }

    # Cache files with these extensions
    if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    return (hash);
    }

    return (hash);

    }

    sub vcl_backend_response {

    /*
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    bereq.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    bereq.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    bereq.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    bereq.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }
    */

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/any-other-url-path"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    bereq.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache ajax requests
    if(beresp.http.X-Requested-With == "XMLHttpRequest" || bereq.url ~ "nocache") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache backend response to posted requests
    if (bereq.method == "POST") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Ok, we're cool & ready to cache things
    # so let's clean up some headers and cookies
    # to maximize caching.

    # Check for the custom "X-Logged-In" header to identify if the visitor is a guest,
    # then unset any cookie (including session cookies) provided it's not a POST request.
    if(bereq.method != "POST" && beresp.http.X-Logged-In == "False") {
    unset beresp.http.Set-Cookie;
    }

    # Allow items to be stale if needed (this value should be the same as with "set req.grace"
    # inside the sub vcl_recv {…} block (the 2nd part of the if/else statement)
    set beresp.grace = 1h;

    # Serve pages from the cache should we get a sudden error and re-check in 3 minutes
    if (beresp.status == 503 || beresp.status == 502 || beresp.status == 501 || beresp.status == 500) {
    set beresp.grace = 3m;
    return (retry);
    }

    # This is how long Varnish will keep cached content.
    # If you change it, remember to adjust "beresp.http.Cache-Control" lower and
    # "req.grace" in the vcl_recv() section
    set beresp.ttl = 2m;

    # OPTIONAL:
    # Nice trick from https://www.varnish-cache.org/trac/wiki/VCLExampleIgnoreCacheHeadersFromBackend
    # Essentially caches anything with a cache time lower than the specified time.
    # May not work on all cases so use with caution.
    #if (beresp.ttl < 2m) {
    # set beresp.ttl = 2m;
    #}

    # Unset the "etag" header (suggested)
    unset beresp.http.etag;

    # Unset the "pragma" header
    unset beresp.http.Pragma;

    # Modify "expires" header - https://www.varnish-cache.org/trac/wiki/VCLExampleSetExpires
    set beresp.http.Expires = "" + (now + beresp.ttl);

    # If your backend server does not set the right caching headers for static assets,
    # you can set them below (uncomment first and change 604800 - which 1 week - to whatever you
    # want (in seconds)
    #if (req.url ~ "\.(ico|jpg|jpeg|gif|png|bmp|webp|tiff|svg|svgz|pdf|mp3|flac|ogg|mid|midi|wav|mp4|webm|mkv|ogv|wmv|eot|otf|woff|ttf|rss|atom|zip|7z|tgz|gz|rar|bz2|tar|exe|doc|docx|xls|xlsx|ppt|pptx|rtf|odt|ods|odp)(\?[a-zA-Z0-9=]+)$") {
    # set beresp.http.Cache-Control = "public, max-age=604800";
    #}

    # We have content to cache, but it's got no-cache or other Cache-Control values sent
    # So let's reset it to our main caching time (2m as used in this example configuration)
    # The additional parameters specified (stale-while-revalidate & stale-if-error) are used
    # by modern browsers to better control caching. Set there to twice & five times your main
    # cache time respectively.
    # This final setting will normalize CMSs like Joomla which set max-age=0 even when
    # Joomla's cache is enabled.
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0"){
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=600";
    }

    return (deliver);
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    bereq.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache ajax requests
    if(beresp.http.X-Requested-With == "XMLHttpRequest" || bereq.url ~ "nocache") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache backend response to posted requests
    if (bereq.method == "POST") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Ok, we're cool & ready to cache things
    # so let's clean up some headers and cookies
    # to maximize caching.

    # Check for the custom "X-Logged-In" header to identify if the visitor is a guest,
    # then unset any cookie (including session cookies) provided it's not a POST request.
    if(bereq.method != "POST" && beresp.http.X-Logged-In == "False") {
    unset beresp.http.Set-Cookie;
    }

    # Allow items to be stale if needed (this value should be the same as with "set req.grace"
    # inside the sub vcl_recv {…} block (the 2nd part of the if/else statement)
    set beresp.grace = 1h;

    # Serve pages from the cache should we get a sudden error and re-check in 3 minutes
    if (beresp.status == 503 || beresp.status == 502 || beresp.status == 501 || beresp.status == 500) {
    set beresp.grace = 3m;
    return (retry);
    }

    # This is how long Varnish will keep cached content.
    # If you change it, remember to adjust "beresp.http.Cache-Control" lower and
    # "req.grace" in the vcl_recv() section
    set beresp.ttl = 2m;

    # OPTIONAL:
    # Nice trick from https://www.varnish-cache.org/trac/wiki/VCLExampleIgnoreCacheHeadersFromBackend
    # Essentially caches anything with a cache time lower than the specified time.
    # May not work on all cases so use with caution.
    #if (beresp.ttl < 2m) {
    # set beresp.ttl = 2m;
    #}

    # Unset the "etag" header (suggested)
    unset beresp.http.etag;

    # Unset the "pragma" header
    unset beresp.http.Pragma;

    # Modify "expires" header - https://www.varnish-cache.org/trac/wiki/VCLExampleSetExpires
    set beresp.http.Expires = "" + (now + beresp.ttl);

    # If your backend server does not set the right caching headers for static assets,
    # you can set them below (uncomment first and change 604800 - which 1 week - to whatever you
    # want (in seconds)
    #if (req.url ~ "\.(ico|jpg|jpeg|gif|png|bmp|webp|tiff|svg|svgz|pdf|mp3|flac|ogg|mid|midi|wav|mp4|webm|mkv|ogv|wmv|eot|otf|woff|ttf|rss|atom|zip|7z|tgz|gz|rar|bz2|tar|exe|doc|docx|xls|xlsx|ppt|pptx|rtf|odt|ods|odp)(\?[a-zA-Z0-9=]+)$") {
    # set beresp.http.Cache-Control = "public, max-age=604800";
    #}

    # We have content to cache, but it's got no-cache or other Cache-Control values sent
    # So let's reset it to our main caching time (2m as used in this example configuration)
    # The additional parameters specified (stale-while-revalidate & stale-if-error) are used
    # by modern browsers to better control caching. Set there to twice & five times your main
    # cache time respectively.
    # This final setting will normalize CMSs like Joomla which set max-age=0 even when
    # Joomla's cache is enabled.
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0"){
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=600";
    }

    return (deliver);

    }

    sub vcl_deliver {

    /*
    # Send a special header for excluded domains only
    # The if statement can be identical to the ones in the vcl_recv() and vcl_fetch() functions above
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    set resp.http.X-Domain-Status = "EXCLUDED";
    }
    # Enforce redirect to HTTPS for specified domains only
    if (
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)" &&
    req.http.X-Forwarded-Proto !~ "(?i)https"
    ) {
    set resp.http.Location = "https://" + req.http.host + req.url;
    set resp.status = 302;
    }
    # Send a special header for excluded domains only
    # The if statement can be identical to the ones in the vcl_recv() and vcl_fetch() functions above
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    set resp.http.X-Domain-Status = "EXCLUDED";
    }
    # Enforce redirect to HTTPS for specified domains only
    if (
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)" &&
    req.http.X-Forwarded-Proto !~ "(?i)https"
    ) {
    set resp.http.Location = "https://" + req.http.host + req.url;
    set resp.status = 302;
    }
    */
    # Send special headers that indicate the cache status of each web page
    if (obj.hits > 0) {
    set resp.http.X-Cache = "HIT";
    set resp.http.X-Cache-Hits = obj.hits;
    } else {
    set resp.http.X-Cache = "MISS";
    }

    return (deliver);
    # Send special headers that indicate the cache status of each web page
    if (obj.hits > 0) {
    set resp.http.X-Cache = "HIT";
    set resp.http.X-Cache-Hits = obj.hits;
    } else {
    set resp.http.X-Cache = "MISS";
    }

    return (deliver);

    }
  11. @fevangelou fevangelou revised this gist Sep 21, 2016. No changes.
  12. @fevangelou fevangelou revised this gist Sep 21, 2016. 3 changed files with 0 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
  13. @fevangelou fevangelou revised this gist Sep 21, 2016. 3 changed files with 405 additions and 156 deletions.
    196 changes: 40 additions & 156 deletions default.vcl → default.vcl_for_Varnish_3.x
    Original file line number Diff line number Diff line change
    @@ -1,91 +1,6 @@
    #################################################################################
    ### The perfect Varnish configuration for Joomla (& other CMS based) websites ###
    #################################################################################

    # USE: Place the contents of this configuration inside the main
    # Varnish configuration file, located in: /etc/varnish/default.vcl (root server access required - obviously)


    # IMPORTANT: The following setup assumes a 2 minute cache time. You can safely increase
    # this to 5 mins for less busier sites or drop it to 1 min or even 30s for high traffic sites.


    # USE BEYOND JOOMLA: This configuration requires an HTTP Header and a user cookie (see the Joomla section)
    # to identify if a user is logged in a site, in order to bypass caching overall. If your CMS provides a way to add
    # these 2 requirements, then you can use this configuration to speed up your site or entire server. You can even
    # exclude the domains you don't want to cache if you're looking to use it in a multi-site setup.


    # === FOR JOOMLA ONLY [start] ===
    #
    # This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether
    # some user is logged in or not inside Joomla. To insert the HTTP header, simply append the following code block,
    # while setting the $cookieDomain value:
    #
    #// Make Joomla Varnish-friendly [START]
    #$cookieDomain = 'domain.tld'; // Replace "domain.tld" with your "naked" domain
    #
    #$getUserState = JFactory::getUser();
    #
    #if ($getUserState->guest) {
    # JResponse::allowCache(true);
    # JResponse::setHeader('X-Logged-In', 'False', true);
    # if($_COOKIE["userID"]){
    # setcookie("userID", "", time() - 3600, '/', $cookieDomain, 0);
    # }
    #} else {
    # JResponse::allowCache(true);
    # JResponse::setHeader('X-Logged-In', 'True', true);
    # if(!isset($_COOKIE["userID"])){
    # setcookie("userID", $getUserState->id, 0, '/', $cookieDomain, 0);
    # }
    #}
    #// Make Joomla Varnish-friendly [FINISH]
    #
    # in your template's "index.php" file, right after the line:
    # defined('_JEXEC') or die;
    #
    # IMPORTANT: If you use K2 (getk2.org) in your Joomla site, simply set the "Cookie Domain" option in the K2 parameters
    # ("Advanced" tab) and all the above will be automatically enabled for your entire Joomla site.
    #
    #
    # === HOW TO HANDLE FRONTEND LOGINS (e.g. for use with member areas, forums etc.) ===
    # It is important for you to understand that since Joomla (in a very amateur way) uses session cookies for any user
    # (even guests) supposedly for additional security (debatable), Varnish *cannot* work with Joomla out-of-the-box. If
    # you installed Varnish without any modification to its configuration besides the cache time, it could not properly
    # cache Joomla content because of the session cookies Joomla uses for both guest and logged in visitors. To bypass
    # Joomla's behaviour, we must additionally set Varnish to strip any cookies set by Joomla, except for a specific one (userID).
    # For even better control, we also set a custom HTTP header (X-Logged-In), which we have Varnish check on all requests. All
    # this is explained how to integrate into Joomla via your template in the code sample above.
    # However, if we want Varnish to allow frontend logins in Joomla, without breaking Joomla (because we strip its session cookies),
    # we must explicitly tell Varnish which entry pages (=login pages) not to cache. Such a page could be for example the default
    # Joomla login form (e.g. with an alias "login"). In the 2 Varnish exclusion lists defined in the configuration below, we would add
    # "^/login" to make sure Varnish completely switches off when a user visits this page. In that case, Joomla's session cookie gets
    # set and the form can be submitted normally, passing all Joomla security checks. Same goes for any page in Joomla that requires
    # user input: a contact form, a newsletter signup form, a forum, comments and so on. So the solution to keep in mind is simple:
    # - If the action requires the user to login first (e.g. a forum), we must create a specific/unique page for users to login first.
    # Once they log in, Varnish switches off completely and then a user can post in the forum or write comments or use a contact form
    # as if Varnish did not exist. If the user continues to browse the site while logged in, Varnish will be completely off ONLY for
    # this user. If the user logs out, Varnish will kick back in.
    # - If the action does not require a user to be logged in first, e.g. a contact form, we simply exclude the contact form's URL from
    # Varnish, in which case -again- Varnish will switch off completely and the user will be able to submit the form passing the
    # Joomla security checks. If the user browses anywhere else in the site, Varnish will kick back in.
    #
    # === FOR JOOMLA ONLY [finish] ===


    # === CHANGELOG ===
    # Nov 3rd, 2015:
    # - Updated configuration with new more robust rules
    # - Added Varnish 4.x compatibility notes
    # - Added JRememberMe cookie to allow Varnish to work properly with Joomla's "remember me" login option. Please
    # refer to this pull request on GitHub https://github.com/joomla/joomla-cms/pull/7677 on how to implement
    # on your Joomla site.
    # - Configuration moved to GitHub from snipt.net (https://snipt.net/fevangelou/the-perfect-varnish-configuration-for-joomla-websites/)
    #


    ### /etc/varnish/default.vcl - START ###
    ##############################################################################################
    ### The perfect Varnish 3.x configuration for Joomla, WordPress & other CMS based websites ###
    ##############################################################################################

    backend default {
    .host = "127.0.0.1"; # don't change this if the web server is on the same machine
    @@ -94,6 +9,7 @@ backend default {

    sub vcl_recv {

    /*
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    @@ -102,13 +18,12 @@ sub vcl_recv {
    ) {
    return (pass);
    }
    */

    # Forward client's IP to the backend
    if (req.restarts == 0) {
    if (req.http.x-forwarded-for) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    # In Varnish 4.x, comment the above line & uncomment the one below
    #set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip;
    } else {
    set req.http.X-Forwarded-For = client.ip;
    }
    @@ -134,11 +49,12 @@ sub vcl_recv {
    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "JRememberMe"
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    req.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    return (pass);
    }
    @@ -149,11 +65,11 @@ sub vcl_recv {
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/any-other-url-path"
    ) {
    return (pass);
    @@ -206,94 +122,53 @@ sub vcl_recv {

    sub vcl_fetch {

    /*
    # Some (uncommented by default) rules for debugging cache status
    # ###
    # Varnish determined the object was not cacheable
    if (beresp.ttl <= 0s) {
    set beresp.http.X-Cacheable = "NO:Not Cacheable";
    # You don't wish to cache content for logged in users
    } elseif (req.http.Cookie ~ "userID") {
    set beresp.http.X-Cacheable = "NO:Got userID cookie";
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    # You are respecting the Cache-Control=private header from the backend
    } elseif (beresp.http.Cache-Control ~ "private") {
    set beresp.http.X-Cacheable = "NO:Cache-Control=private";
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    # Ajax
    } elseif (req.http.X-Requested-With == "XMLHttpRequest") {
    set beresp.http.X-Cacheable = "NO:Ajax";
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    # Varnish determined the object was cacheable
    } else {
    set beresp.http.X-Cacheable = "YES";
    }
    */

    /*
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    bereq.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    bereq.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }
    */

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/any-other-url-path"
    ) {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "JRememberMe"
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    bereq.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }
    # Don't cache ajax requests
    if(beresp.http.X-Requested-With == "XMLHttpRequest" || bereq.url ~ "nocache") {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }

    # Don't cache backend response to posted requests
    if (bereq.request == "POST") {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }
    # Ok, we're cool & ready to cache things
    @@ -362,6 +237,7 @@ sub vcl_fetch {
    sub vcl_deliver {
    /*
    # Send a special header for excluded domains only.
    # The if statement can be identical to the ones in the vcl_recv() and vcl_fetch() functions above
    if (
    @@ -370,6 +246,16 @@ sub vcl_deliver {
    ) {
    set resp.http.X-Domain-Status = "EXCLUDED";
    }
    # Enforce redirect to HTTPS for specified domains only
    if (
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)" &&
    req.http.X-Forwarded-Proto !~ "(?i)https"
    ) {
    set resp.http.Location = "https://" + req.http.host + req.url;
    set resp.status = 302;
    }
    */
    # Send special headers that indicate the cache status of each web page
    if (obj.hits > 0) {
    @@ -385,5 +271,3 @@ sub vcl_deliver {
    return (deliver);
    }

    ### /etc/varnish/default.vcl - END ###
    284 changes: 284 additions & 0 deletions default.vcl_for_Varnish_4.x_or_newer
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,284 @@
    ###############################################################################################
    ### The perfect Varnish 4.x+ configuration for Joomla, WordPress & other CMS based websites ###
    ###############################################################################################

    # Varnish Reference:
    # 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;

    # Imports
    import std;

    # Default backend definition. Set this to point to your content server.
    backend default {
    .host = "127.0.0.1"; # don't change this if the web server is on the same machine
    .port = "XXXX"; # replace XXXX with your web server's port
    }

    sub vcl_recv {

    /*
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    return (pass);
    }
    */

    # Forward client's IP to the backend
    if (req.restarts == 0) {
    if (req.http.X-Real-IP) {
    set req.http.X-Forwarded-For = req.http.X-Real-IP;
    } else if (req.http.X-Forwarded-For) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    # In Varnish 4.x, comment the above line & uncomment the following
    #set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip;
    } else {
    set req.http.X-Forwarded-For = client.ip;
    }
    }

    # httpoxy
    unset req.http.proxy;

    # Non-RFC2616 or CONNECT which is weird.
    if (
    req.method != "GET" &&
    req.method != "HEAD" &&
    req.method != "PUT" &&
    req.method != "POST" &&
    req.method != "TRACE" &&
    req.method != "OPTIONS" &&
    req.method != "DELETE"
    ) {
    return (pipe);
    }

    # We only deal with GET and HEAD by default
    if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    req.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    return (pass);
    }

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/any-other-url-path"
    ) {
    return (pass);
    }

    # Don't cache ajax requests
    if(req.http.X-Requested-With == "XMLHttpRequest" || req.url ~ "nocache") {
    return (pass);
    }

    # Check for the custom "X-Logged-In" header (used by K2 and other apps) to identify
    # if the visitor is a guest, then unset any cookie (including session cookies) provided
    # it's not a POST request.
    if(req.http.X-Logged-In == "False" && req.method != "POST"){
    unset req.http.Cookie;
    }

    # Properly handle different encoding types
    if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    unset req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    unset req.http.Accept-Encoding;
    }
    }

    # Cache files with these extensions
    if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    return (hash);
    }

    return (hash);

    }

    sub vcl_backend_response {

    /*
    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    bereq.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    bereq.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }
    */

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/any-other-url-path"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "joomla_[a-zA-Z0-9_]+" ||
    bereq.http.Cookie ~ "(wordpress_[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+)"
    ) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache ajax requests
    if(beresp.http.X-Requested-With == "XMLHttpRequest" || bereq.url ~ "nocache") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Don't cache backend response to posted requests
    if (bereq.method == "POST") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # Ok, we're cool & ready to cache things
    # so let's clean up some headers and cookies
    # to maximize caching.

    # Check for the custom "X-Logged-In" header to identify if the visitor is a guest,
    # then unset any cookie (including session cookies) provided it's not a POST request.
    if(bereq.method != "POST" && beresp.http.X-Logged-In == "False") {
    unset beresp.http.Set-Cookie;
    }

    # Allow items to be stale if needed (this value should be the same as with "set req.grace"
    # inside the sub vcl_recv {…} block (the 2nd part of the if/else statement)
    set beresp.grace = 1h;

    # Serve pages from the cache should we get a sudden error and re-check in 3 minutes
    if (beresp.status == 503 || beresp.status == 502 || beresp.status == 501 || beresp.status == 500) {
    set beresp.grace = 3m;
    return (retry);
    }

    # This is how long Varnish will keep cached content.
    # If you change it, remember to adjust "beresp.http.Cache-Control" lower and
    # "req.grace" in the vcl_recv() section
    set beresp.ttl = 2m;

    # OPTIONAL:
    # Nice trick from https://www.varnish-cache.org/trac/wiki/VCLExampleIgnoreCacheHeadersFromBackend
    # Essentially caches anything with a cache time lower than the specified time.
    # May not work on all cases so use with caution.
    #if (beresp.ttl < 2m) {
    # set beresp.ttl = 2m;
    #}

    # Unset the "etag" header (suggested)
    unset beresp.http.etag;

    # Unset the "pragma" header
    unset beresp.http.Pragma;

    # Modify "expires" header - https://www.varnish-cache.org/trac/wiki/VCLExampleSetExpires
    set beresp.http.Expires = "" + (now + beresp.ttl);

    # If your backend server does not set the right caching headers for static assets,
    # you can set them below (uncomment first and change 604800 - which 1 week - to whatever you
    # want (in seconds)
    #if (req.url ~ "\.(ico|jpg|jpeg|gif|png|bmp|webp|tiff|svg|svgz|pdf|mp3|flac|ogg|mid|midi|wav|mp4|webm|mkv|ogv|wmv|eot|otf|woff|ttf|rss|atom|zip|7z|tgz|gz|rar|bz2|tar|exe|doc|docx|xls|xlsx|ppt|pptx|rtf|odt|ods|odp)(\?[a-zA-Z0-9=]+)$") {
    # set beresp.http.Cache-Control = "public, max-age=604800";
    #}

    # We have content to cache, but it's got no-cache or other Cache-Control values sent
    # So let's reset it to our main caching time (2m as used in this example configuration)
    # The additional parameters specified (stale-while-revalidate & stale-if-error) are used
    # by modern browsers to better control caching. Set there to twice & five times your main
    # cache time respectively.
    # This final setting will normalize CMSs like Joomla which set max-age=0 even when
    # Joomla's cache is enabled.
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0"){
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=600";
    }

    return (deliver);

    }

    sub vcl_deliver {

    /*
    # Send a special header for excluded domains only
    # The if statement can be identical to the ones in the vcl_recv() and vcl_fetch() functions above
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    set resp.http.X-Domain-Status = "EXCLUDED";
    }

    # Enforce redirect to HTTPS for specified domains only
    if (
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)" &&
    req.http.X-Forwarded-Proto !~ "(?i)https"
    ) {
    set resp.http.Location = "https://" + req.http.host + req.url;
    set resp.status = 302;
    }
    */
    # Send special headers that indicate the cache status of each web page
    if (obj.hits > 0) {
    set resp.http.X-Cache = "HIT";
    set resp.http.X-Cache-Hits = obj.hits;
    } else {
    set resp.http.X-Cache = "MISS";
    }

    return (deliver);

    }
    81 changes: 81 additions & 0 deletions preface.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    ##########################################################################################
    ### The perfect Varnish configuration for Joomla, WordPress & other CMS based websites ###
    ##########################################################################################

    IMPORTANT: Read this before implementing one of the configuration files below (for either Varnish 3.x or 4.x+).

    USE: Replace the contents of the main Varnish configuration file located in /etc/varnish/default.vcl
    (root server access required - obviously) with the contents of the configuration you'll use (depending on your Varnish version)
    from the 2 examples provided below.

    IMPORTANT: The following setup assumes a 2 minute cache time. You can safely increase
    this to 5 mins for less busier sites or drop it to 1 min or even 30s for high traffic sites.

    This configuration requires an HTTP Header and a user cookie (see the Joomla section)
    to identify if a user is logged in a site, in order to bypass caching overall. If your CMS provides a way to add
    these 2 requirements, then you can use this configuration to speed up your site or entire server. You can even
    exclude the domains you don't want to cache if you're looking to use it in a multi-site setup.



    === JOOMLA & VARNISH ===
    Since Joomla v3.6, all you need to do to have Joomla play nicely with Varnish is add your exclusion points (URLs)
    - see the 2 blocks starting with "Exclude the following paths..." below in the configuration.

    If you're using Joomla before version 3.6, you need to do the following:
    This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether
    some user is logged in or not inside Joomla. To insert the HTTP header, simply append the following code block
    in your template's "index.php" file, right after the line:
    defined('_JEXEC') or die;
    ...and make sure you set the $cookieDomain value:

    // Make Joomla Varnish-friendly [START]
    $cookieDomain = 'domain.tld'; // Replace "domain.tld" with your "naked" domain

    $getUserState = JFactory::getUser();

    if ($getUserState->guest) {
    JResponse::allowCache(true);
    JResponse::setHeader('X-Logged-In', 'False', true);
    if($_COOKIE["userID"]){
    setcookie("userID", "", time() - 3600, '/', $cookieDomain, 0);
    }
    } else {
    JResponse::allowCache(true);
    JResponse::setHeader('X-Logged-In', 'True', true);
    if(!isset($_COOKIE["userID"])){
    setcookie("userID", $getUserState->id, 0, '/', $cookieDomain, 0);
    }
    }
    // Make Joomla Varnish-friendly [FINISH]

    IMPORTANT: If you use K2 (getk2.org) in your Joomla site, simply set the "Cookie Domain" option in the K2 parameters
    ("Advanced" tab) and all the above will be automatically enabled for your entire Joomla site.



    === HOW TO HANDLE FRONTEND LOGINS (e.g. for use with member areas, forums etc.) ===
    It is important for you to understand that since Joomla (in a very amateur way) uses session cookies for any user
    (even guests) supposedly for additional security (debatable), Varnish *cannot* work with Joomla out-of-the-box. If
    you installed Varnish without any modification to its configuration besides the cache time, it could not properly
    cache Joomla content because of the session cookies Joomla uses for both guest and logged in visitors. To bypass
    Joomla's behaviour, we must additionally set Varnish to strip any cookies set by Joomla, except for a specific one (userID).
    For even better control, we also set a custom HTTP header (X-Logged-In), which we have Varnish check on all requests. All
    this is explained how to integrate into Joomla via your template in the code sample above.
    However, if we want Varnish to allow frontend logins in Joomla, without breaking Joomla (because we strip its session cookies),
    we must explicitly tell Varnish which entry pages (=login pages) not to cache. Such a page could be for example the default
    Joomla login form (e.g. with an alias "login"). In the 2 Varnish exclusion lists defined in the configuration below, we would add
    "^/login" to make sure Varnish completely switches off when a user visits this page. In that case, Joomla's session cookie gets
    set and the form can be submitted normally, passing all Joomla security checks. Same goes for any page in Joomla that requires
    user input: a contact form, a newsletter signup form, a forum, comments and so on. So the solution to keep in mind is simple:
    - If the action requires the user to login first (e.g. a forum), we must create a specific/unique page for users to login first.
    Once they log in, Varnish switches off completely and then a user can post in the forum or write comments or use a contact form
    as if Varnish did not exist. If the user continues to browse the site while logged in, Varnish will be completely off ONLY for
    this user. If the user logs out, Varnish will kick back in.
    - If the action does not require a user to be logged in first, e.g. a contact form, we simply exclude the contact form's URL from
    Varnish, in which case -again- Varnish will switch off completely and the user will be able to submit the form passing the
    Joomla security checks. If the user browses anywhere else in the site, Varnish will kick back in.



    *** DOCUMENT LAST UPDATED: September 21st, 2016 ***
  14. @fevangelou fevangelou revised this gist Nov 4, 2015. 1 changed file with 4 additions and 5 deletions.
    9 changes: 4 additions & 5 deletions default.vcl
    Original file line number Diff line number Diff line change
    @@ -5,16 +5,17 @@
    # USE: Place the contents of this configuration inside the main
    # Varnish configuration file, located in: /etc/varnish/default.vcl (root server access required - obviously)


    # IMPORTANT: The following setup assumes a 2 minute cache time. You can safely increase
    # this to 5 mins for less busier sites or drop it to 1 min or even 30s for high traffic sites.


    # USE BEYOND JOOMLA: This configuration requires an HTTP Header and a user cookie (see the Joomla section)
    # to identify if a user is logged in a site, in order to bypass caching overall. If your CMS provides a way to add
    # these 2 requirements, then you can use this configuration to speed up your site or entire server. You can even
    # exclude the domains you don't want to cache if you're looking to use it in a multi-site setup.



    # === FOR JOOMLA ONLY [start] ===
    #
    # This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether
    @@ -72,7 +73,8 @@
    #
    # === FOR JOOMLA ONLY [finish] ===

    # CHANGELOG

    # === CHANGELOG ===
    # Nov 3rd, 2015:
    # - Updated configuration with new more robust rules
    # - Added Varnish 4.x compatibility notes
    @@ -83,14 +85,11 @@
    #



    ### /etc/varnish/default.vcl - START ###

    backend default {

    .host = "127.0.0.1"; # don't change this if the web server is on the same machine
    .port = "XXXX"; # replace XXXX with your web server's port

    }

    sub vcl_recv {
  15. @fevangelou fevangelou revised this gist Nov 4, 2015. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions default.vcl
    Original file line number Diff line number Diff line change
    @@ -79,6 +79,7 @@
    # - Added JRememberMe cookie to allow Varnish to work properly with Joomla's "remember me" login option. Please
    # refer to this pull request on GitHub https://github.com/joomla/joomla-cms/pull/7677 on how to implement
    # on your Joomla site.
    # - Configuration moved to GitHub from snipt.net (https://snipt.net/fevangelou/the-perfect-varnish-configuration-for-joomla-websites/)
    #


  16. @fevangelou fevangelou revised this gist Nov 4, 2015. No changes.
  17. @fevangelou fevangelou created this gist Nov 4, 2015.
    389 changes: 389 additions & 0 deletions default.vcl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,389 @@
    #################################################################################
    ### The perfect Varnish configuration for Joomla (& other CMS based) websites ###
    #################################################################################

    # USE: Place the contents of this configuration inside the main
    # Varnish configuration file, located in: /etc/varnish/default.vcl (root server access required - obviously)

    # IMPORTANT: The following setup assumes a 2 minute cache time. You can safely increase
    # this to 5 mins for less busier sites or drop it to 1 min or even 30s for high traffic sites.

    # USE BEYOND JOOMLA: This configuration requires an HTTP Header and a user cookie (see the Joomla section)
    # to identify if a user is logged in a site, in order to bypass caching overall. If your CMS provides a way to add
    # these 2 requirements, then you can use this configuration to speed up your site or entire server. You can even
    # exclude the domains you don't want to cache if you're looking to use it in a multi-site setup.



    # === FOR JOOMLA ONLY [start] ===
    #
    # This Varnish configuration makes use of a custom HTTP header plus a user cookie to determine whether
    # some user is logged in or not inside Joomla. To insert the HTTP header, simply append the following code block,
    # while setting the $cookieDomain value:
    #
    #// Make Joomla Varnish-friendly [START]
    #$cookieDomain = 'domain.tld'; // Replace "domain.tld" with your "naked" domain
    #
    #$getUserState = JFactory::getUser();
    #
    #if ($getUserState->guest) {
    # JResponse::allowCache(true);
    # JResponse::setHeader('X-Logged-In', 'False', true);
    # if($_COOKIE["userID"]){
    # setcookie("userID", "", time() - 3600, '/', $cookieDomain, 0);
    # }
    #} else {
    # JResponse::allowCache(true);
    # JResponse::setHeader('X-Logged-In', 'True', true);
    # if(!isset($_COOKIE["userID"])){
    # setcookie("userID", $getUserState->id, 0, '/', $cookieDomain, 0);
    # }
    #}
    #// Make Joomla Varnish-friendly [FINISH]
    #
    # in your template's "index.php" file, right after the line:
    # defined('_JEXEC') or die;
    #
    # IMPORTANT: If you use K2 (getk2.org) in your Joomla site, simply set the "Cookie Domain" option in the K2 parameters
    # ("Advanced" tab) and all the above will be automatically enabled for your entire Joomla site.
    #
    #
    # === HOW TO HANDLE FRONTEND LOGINS (e.g. for use with member areas, forums etc.) ===
    # It is important for you to understand that since Joomla (in a very amateur way) uses session cookies for any user
    # (even guests) supposedly for additional security (debatable), Varnish *cannot* work with Joomla out-of-the-box. If
    # you installed Varnish without any modification to its configuration besides the cache time, it could not properly
    # cache Joomla content because of the session cookies Joomla uses for both guest and logged in visitors. To bypass
    # Joomla's behaviour, we must additionally set Varnish to strip any cookies set by Joomla, except for a specific one (userID).
    # For even better control, we also set a custom HTTP header (X-Logged-In), which we have Varnish check on all requests. All
    # this is explained how to integrate into Joomla via your template in the code sample above.
    # However, if we want Varnish to allow frontend logins in Joomla, without breaking Joomla (because we strip its session cookies),
    # we must explicitly tell Varnish which entry pages (=login pages) not to cache. Such a page could be for example the default
    # Joomla login form (e.g. with an alias "login"). In the 2 Varnish exclusion lists defined in the configuration below, we would add
    # "^/login" to make sure Varnish completely switches off when a user visits this page. In that case, Joomla's session cookie gets
    # set and the form can be submitted normally, passing all Joomla security checks. Same goes for any page in Joomla that requires
    # user input: a contact form, a newsletter signup form, a forum, comments and so on. So the solution to keep in mind is simple:
    # - If the action requires the user to login first (e.g. a forum), we must create a specific/unique page for users to login first.
    # Once they log in, Varnish switches off completely and then a user can post in the forum or write comments or use a contact form
    # as if Varnish did not exist. If the user continues to browse the site while logged in, Varnish will be completely off ONLY for
    # this user. If the user logs out, Varnish will kick back in.
    # - If the action does not require a user to be logged in first, e.g. a contact form, we simply exclude the contact form's URL from
    # Varnish, in which case -again- Varnish will switch off completely and the user will be able to submit the form passing the
    # Joomla security checks. If the user browses anywhere else in the site, Varnish will kick back in.
    #
    # === FOR JOOMLA ONLY [finish] ===

    # CHANGELOG
    # Nov 3rd, 2015:
    # - Updated configuration with new more robust rules
    # - Added Varnish 4.x compatibility notes
    # - Added JRememberMe cookie to allow Varnish to work properly with Joomla's "remember me" login option. Please
    # refer to this pull request on GitHub https://github.com/joomla/joomla-cms/pull/7677 on how to implement
    # on your Joomla site.
    #



    ### /etc/varnish/default.vcl - START ###

    backend default {

    .host = "127.0.0.1"; # don't change this if the web server is on the same machine
    .port = "XXXX"; # replace XXXX with your web server's port

    }

    sub vcl_recv {

    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    return (pass);
    }

    # Forward client's IP to the backend
    if (req.restarts == 0) {
    if (req.http.x-forwarded-for) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    # In Varnish 4.x, comment the above line & uncomment the one below
    #set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip;
    } else {
    set req.http.X-Forwarded-For = client.ip;
    }
    }

    # Non-RFC2616 or CONNECT which is weird.
    if (
    req.request != "GET" &&
    req.request != "HEAD" &&
    req.request != "PUT" &&
    req.request != "POST" &&
    req.request != "TRACE" &&
    req.request != "OPTIONS" &&
    req.request != "DELETE"
    ) {
    return (pipe);
    }

    # We only deal with GET and HEAD by default
    if (req.request != "GET" && req.request != "HEAD") {
    return (pass);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    req.http.Authorization ||
    req.http.Authenticate ||
    req.http.X-Logged-In == "True" ||
    req.http.Cookie ~ "userID" ||
    req.http.Cookie ~ "JRememberMe"
    ) {
    return (pass);
    }

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    req.url ~ "^/administrator" ||
    req.url ~ "^/component/banners" ||
    req.url ~ "^/component/users" ||
    req.url ~ "^/wp-admin" ||
    req.url ~ "^/wp-login.php" ||
    req.url ~ "^/any-other-url-path"
    ) {
    return (pass);
    }

    # Don't cache ajax requests
    if(req.http.X-Requested-With == "XMLHttpRequest" || req.url ~ "nocache") {
    return (pass);
    }

    # Check for the custom "X-Logged-In" header (used by K2 and other apps) to identify
    # if the visitor is a guest, then unset any cookie (including session cookies) provided
    # it's not a POST request.
    if(req.http.X-Logged-In == "False" && req.request != "POST"){
    unset req.http.Cookie;
    }

    # Properly handle different encoding types
    if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    # No point in compressing these
    remove req.http.Accept-Encoding;
    } elseif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    # unknown algorithm (aka crappy browser)
    remove req.http.Accept-Encoding;
    }
    }

    # Cache files with these extensions
    if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
    return (lookup);
    }

    # Set how long Varnish will cache content depending on whether your backend is healthy or not
    if (req.backend.healthy) {
    # Remember to adjust beresp.ttl & beresp.http.Cache-Control inside vcl_fetch()
    # to the same time
    set req.grace = 2m;
    } else {
    set req.grace = 1h;
    }

    return (lookup);

    }

    sub vcl_fetch {

    /*
    # Some (uncommented by default) rules for debugging cache status
    # ###
    # Varnish determined the object was not cacheable
    if (beresp.ttl <= 0s) {
    set beresp.http.X-Cacheable = "NO:Not Cacheable";
    # You don't wish to cache content for logged in users
    } elseif (req.http.Cookie ~ "userID") {
    set beresp.http.X-Cacheable = "NO:Got userID cookie";
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    # You are respecting the Cache-Control=private header from the backend
    } elseif (beresp.http.Cache-Control ~ "private") {
    set beresp.http.X-Cacheable = "NO:Cache-Control=private";
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    # Ajax
    } elseif (req.http.X-Requested-With == "XMLHttpRequest") {
    set beresp.http.X-Cacheable = "NO:Ajax";
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    # Varnish determined the object was cacheable
    } else {
    set beresp.http.X-Cacheable = "YES";
    }
    */

    # If we host multiple domains on a server, here you can list the domains you DO NOT want to cache
    # The first check matches both naked & "www" subdomains. Use the second for non generic subdomains.
    if (
    bereq.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    bereq.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }

    # Exclude the following paths (e.g. backend admins, user pages or ad URLs that require tracking)
    # In Joomla specifically, you are advised to create specific entry points (URLs) for users to
    # interact with the site (either common user logins or even commenting), e.g. make a menu item
    # to point to a user login page (e.g. /login), including all related functionality such as
    # password reset, email reminder and so on.
    if(
    bereq.url ~ "^/administrator" ||
    bereq.url ~ "^/component/banners" ||
    bereq.url ~ "^/component/users" ||
    bereq.url ~ "^/wp-admin" ||
    bereq.url ~ "^/wp-login.php" ||
    bereq.url ~ "^/any-other-url-path"
    ) {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }

    # Don't cache HTTP authorization/authentication pages and pages with certain headers or cookies
    if (
    bereq.http.Authorization ||
    bereq.http.Authenticate ||
    bereq.http.X-Logged-In == "True" ||
    bereq.http.Cookie ~ "userID" ||
    bereq.http.Cookie ~ "JRememberMe"
    ) {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }

    # Don't cache ajax requests
    if(beresp.http.X-Requested-With == "XMLHttpRequest" || bereq.url ~ "nocache") {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }

    # Don't cache backend response to posted requests
    if (bereq.request == "POST") {
    return (hit_for_pass);
    # In Varnish 4.x, comment the above line & uncomment the one below
    #return (pass);
    }

    # Ok, we're cool & ready to cache things
    # so let's clean up some headers and cookies
    # to maximize caching.

    # Check for the custom "X-Logged-In" header to identify if the visitor is a guest,
    # then unset any cookie (including session cookies) provided it's not a POST request.
    if(bereq.request != "POST" && beresp.http.X-Logged-In == "False") {
    unset beresp.http.Set-Cookie;
    }

    # Allow items to be stale if needed (this value should be the same as with "set req.grace"
    # inside the sub vcl_recv {…} block (the 2nd part of the if/else statement)
    set beresp.grace = 1h;

    # Serve pages from the cache should we get a sudden error and re-check in 3 minutes
    if (beresp.status == 503 || beresp.status == 502 || beresp.status == 501 || beresp.status == 500) {
    set beresp.grace = 3m;
    return (restart);
    }

    # This is how long Varnish will keep cached content.
    # If you change it, remember to adjust "beresp.http.Cache-Control" lower and
    # "req.grace" in the vcl_recv() section
    set beresp.ttl = 2m;

    # OPTIONAL:
    # Nice trick from https://www.varnish-cache.org/trac/wiki/VCLExampleIgnoreCacheHeadersFromBackend
    # Essentially caches anything with a cache time lower than the specified time.
    # May not work on all cases so use with caution.
    #if (beresp.ttl < 2m) {
    # set beresp.ttl = 2m;
    #}

    # Unset the "etag" header (suggested)
    unset beresp.http.etag;

    # Unset the "pragma" header
    unset beresp.http.Pragma;

    # Modify "expires" header - https://www.varnish-cache.org/trac/wiki/VCLExampleSetExpires
    set beresp.http.Expires = "" + (now + beresp.ttl);

    # If your backend server does not set the right caching headers for static assets,
    # you can set them below (uncomment first and change 604800 - which 1 week - to whatever you
    # want (in seconds)
    #if (req.url ~ "\.(ico|jpg|jpeg|gif|png|bmp|webp|tiff|svg|svgz|pdf|mp3|flac|ogg|mid|midi|wav|mp4|webm|mkv|ogv|wmv|eot|otf|woff|ttf|rss|atom|zip|7z|tgz|gz|rar|bz2|tar|exe|doc|docx|xls|xlsx|ppt|pptx|rtf|odt|ods|odp)(\?[a-zA-Z0-9=]+)$") {
    # set beresp.http.Cache-Control = "public, max-age=604800";
    #}

    # We have content to cache, but it's got no-cache or other Cache-Control values sent
    # So let's reset it to our main caching time (2m as used in this example configuration)
    # The additional parameters specified (stale-while-revalidate & stale-if-error) are used
    # by modern browsers to better control caching. Set there to twice & five times your main
    # cache time respectively.
    # This final setting will normalize CMSs like Joomla which set max-age=0 even when
    # Joomla's cache is enabled.
    if (beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control ~ "max-age=0"){
    set beresp.http.Cache-Control = "public, max-age=120, stale-while-revalidate=240, stale-if-error=600";
    }

    return (deliver);

    }

    sub vcl_deliver {

    # Send a special header for excluded domains only.
    # The if statement can be identical to the ones in the vcl_recv() and vcl_fetch() functions above
    if (
    req.http.host ~ "(www\.)?(domain1.com|domain2.org|domain3.net)" ||
    req.http.host ~ "(subdomain.domain4.tld|othersubdomain.domain5.tld)"
    ) {
    set resp.http.X-Domain-Status = "EXCLUDED";
    }

    # Send special headers that indicate the cache status of each web page
    if (obj.hits > 0) {
    set resp.http.X-Cache = "HIT";
    } else {
    set resp.http.X-Cache = "MISS";
    }

    # If you hookup you server to a CDN that offers "website acceleration" features
    # you might need to uncomment the following line for the CDN to fetch content properly.
    #remove resp.http.Age;

    return (deliver);

    }

    ### /etc/varnish/default.vcl - END ###