Jump to content
  • 0
nashtu3000

Varnish Cache and Prestashop

Question

Has anyone succeeded in setting up a Varnish Cache server for Prestashop? Would you be willing to share your config? I'm thinking of doing this and i think a guide and/or possible conf files will be very useful for the community.

Share this post


Link to post
Share on other sites

27 answers to this question

Recommended Posts

  • 0

Here is what i have so far:

 

/*-
* Copyright (c) 2006 Verdens Gang AS
* Copyright (c) 2006-2011 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The default VCL code.
*
* NB! You do NOT need to copy & paste all of these functions into your
* own vcl code, if you do not provide a definition of one of these
* functions, the compiler will automatically fall back to the default
* code from this file.
*
* This code will be prefixed with a backend declaration built from the
* -b argument.
*/
# Back-End
backend default {
.host = "127.0.0.1";
  .port = "8090";
}


sub vcl_recv {


if (req.http.Accept-Encoding) {
       if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
           # No point in compressing these
           #remove req.http.Accept-Encoding;
       } elsif (req.http.Accept-Encoding ~ "gzip") {
           set req.http.Accept-Encoding = "gzip";
       } elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") {
           set req.http.Accept-Encoding = "deflate";
       } else {
           # unkown algorithm
           remove req.http.Accept-Encoding;
       }
   }   

   if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
  set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
  set req.http.X-Forwarded-For = client.ip;
}
   }


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

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

#if (req.http.Cache-Control ~ "no-cache") {
# return (pass);
#}


   #Remove has_js and Google Analytics cookies.
 #set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|__utm*|has_js|_chartbeat2)=[^;]*", "");

if (req.url ~ "\/cache\/|\.css|\.js|\.jpg|\.gif|\.png|modules") {
unset req.http.Cookie;
unset req.http.Accept-Encoding;
unset req.http.Vary;
return (lookup);
}    

if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf)$") {
unset req.http.Cookie;
unset req.http.Accept-Encoding;
unset req.http.Vary;
return (lookup);
}

   if (req.http.Authorization || req.http.Cookie || req.url ~ "admin\-|\.php|token") {
       /* Not cacheable by default */
       return (pass);
   } 

# Let's have a little grace
if (req.backend.healthy) {
set req.grace = 120s;
} else {
set req.grace = 1h;
}

   return (lookup);
}

sub vcl_pipe {
   # Note that only the first request to the backend will have
   # X-Forwarded-For set.  If you use X-Forwarded-For and want to
   # have it set for all requests, make sure to have:
   # set bereq.http.connection = "close";
   # here.  It is not set by default as it might break some broken web
   # applications, like IIS with NTLM authentication.
   set bereq.http.connection = "close";
   return (pipe);
}

sub vcl_pass {
   return (pass);
}

sub vcl_hash {
   hash_data(req.url);
   if (req.http.host) {
       hash_data(req.http.host);
   } else {
       hash_data(server.ip);
   }
   return (hash);
}

sub vcl_hit {
if (req.http.Cache-Control ~ "no-cache") {
set obj.ttl = 0s;
#asta face cache replace la hit care e fortat
}
   return (deliver);
}

sub vcl_miss {
   return (fetch);
}

sub vcl_fetch {
   #if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
#   /*
#    * Mark as "Hit-For-Pass" for the next 2 minutes
#    */
#   set beresp.ttl = 120 s;
#   return (hit_for_pass);
   #}
#
unset beresp.http.set-cookie;

set beresp.grace = 1h;

if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$") {
set beresp.ttl = 24h;
} else {
set beresp.ttl = 5m;
}

return (deliver);
}

sub vcl_deliver {
   /*return (deliver);*/

if(obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
remove resp.http.X-Varnish;
remove resp.http.Via;
#remove resp.http.Age;
remove resp.http.Server;
remove resp.http.X-Powered-By;
return (deliver);
}

sub vcl_error {
 // Let's deliver a friendlier error page.
 // You can customize this as you wish.
 set obj.http.Content-Type = "text/html; charset=utf-8";
 synthetic {"
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html>
   <head>
     <title>"} + obj.status + " " + obj.response + {"</title>
     <style type="text/css">
     #page {width: 400px; padding: 10px; margin: 20px auto; border: 1px solid black; background-color: #FFF;}
     p {margin-left:20px;}
     body {background-color: #DDD; margin: auto;}
     </style>
   </head>
   <body>
   <div id="page">
   <h1>Page Could Not Be Loaded</h1>
   <p>We're very sorry, but the page could not be loaded properly. This should be fixed very soon, and we apologize for any inconvenience.</p>
   <hr />
   <h4>Debug Info:</h4>
   <pre>Status: "} + obj.status + {"
Response: "} + obj.response + {"
XID: "} + req.xid + {"</pre>
     </div>
   </body>
  </html>
 "};
 return(deliver);
}


sub vcl_init {
return (ok);
}

sub vcl_fini {
return (ok);
}

 

The problem is that it ain't working with ps_modalcart and i don't know if there other problems as well.

Share this post


Link to post
Share on other sites
  • 0

As far as I understand the Varnish concept, you have to make a script that tells Varnish which files to cache and which not to cache, e.g. the cart.php and the rest of the checkout.

Share this post


Link to post
Share on other sites
  • 0

Yes that is true, tried it but haven't had that much success with getting the cart working. Anyone else want to contribute to this? It would be an awesome resource for the community.

Share this post


Link to post
Share on other sites
  • 0

now working with the cart, but not yet fully tested!

unstable: this code should be improved .....

small cookie problems: ... unique identifier witch tell Varnish use cache or not. (varnish_nocache)

addition and improvements welcome :)

# This is a basic VCL configuration file for varnish.  See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition.  Set this to point to your content
# server.
#
backend default {
.host = "127.0.0.1";
  .port = "8080";
}

sub vcl_recv {
if (req.request != "GET" &&
 req.request != "HEAD" &&
 req.request != "PUT" &&
 req.request != "POST" &&
 req.request != "TRACE" &&
 req.request != "OPTIONS" &&
 req.request != "DELETE") {
return (pipe);
 }
# do not cache POST requests
 if (req.request == "POST") {
return (pipe);
 }

# Remove has_js and Google Analytics cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");


#we should not cache any page for Prestashop backend
 if (req.request == "GET" && (req.url ~ "^/admin")) {
return (pass);
 }
#we should not cache any page for customers
 if (req.request == "GET" && (req.url ~ "^/authentication" || req.url ~ "^/my-account")) {
return (pass);
 }
#we should not cache any page for customers
 if (req.request == "GET" && (req.url ~ "^/identity" || req.url ~ "^/my-account.php")) {
return (pass);
 }
#we should not cache any page for sales
 if (req.request == "GET" && (req.url ~ "^/cart.php" || req.url ~ "^/order.php")) {
return (pass);
 }
#we should not cache any page for sales
 if (req.request == "GET" && (req.url ~ "^/addresses.php" || req.url ~ "^/order-detail.php")) {
return (pass);
 }
#we should not cache any page for sales
 if (req.request == "GET" && (req.url ~ "^/order-confirmation.php" || req.url ~ "^/order-return.php")) {
return (pass);
 }


#unique identifier witch tell Varnish use cache or not
 if (req.http.cookie ~ "varnish_nocache") {
       return (pass);
 }

#Even though there are few possible values for Accept-Encoding, Varnish treats
 #them literally rather than semantically, so even a small difference which makes
 #no difference to the backend can reduce cache efficiency by making Varnish cache
 #too many different versions of an object.
 #http://varnish.projects.linpro.no/wiki/FAQ/Compression
 if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
  # No point in compressing these
  remove req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
  set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
  set req.http.Accept-Encoding = "deflate";
} else {
  # unkown algorithm
  remove req.http.Accept-Encoding;
}
 }
if (req.url ~ "\/cache\/|\.css|\.js|\.jpg|\.gif|\.png") {
unset req.http.Cookie;
unset req.http.Accept-Encoding;
unset req.http.Vary;
return (lookup);
}
if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf)$") {
unset req.http.Cookie;
unset req.http.Accept-Encoding;
unset req.http.Vary;
return (lookup);
}
 return (lookup);
}
sub vcl_pipe {
 # Note that only the first request to the backend will have
 # X-Forwarded-For set.  If you use X-Forwarded-For and want to
 # have it set for all requests, make sure to have:
 # set req.http.connection = "close";
 # here.  It is not set by default as it might break some broken web
 # applications, like IIS with NTLM authentication.
 return (pipe);
}
sub vcl_pass {
 return (pass);
}
sub vcl_hit {
if (req.http.Cache-Control ~ "no-cache") {
set obj.ttl = 0s;
#asta face cache replace la hit care e fortat
}
return (deliver);
}
sub vcl_miss {
 return (fetch);
}


sub vcl_fetch {
 return (deliver);
}

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

sub vcl_error {
 // Let's deliver a friendlier error page.
 // You can customize this as you wish.
 set obj.http.Content-Type = "text/html; charset=utf-8";
 synthetic {"
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html>
<head>
  <title>"} + obj.status + " " + obj.response + {"</title>
  <style type="text/css">
  #page {width: 400px; padding: 10px; margin: 20px auto; border: 1px solid black; background-color: #FFF;}
  p {margin-left:20px;}
  body {background-color: #DDD; margin: auto;}
  </style>
</head>
<body>
<div id="page">
<h1>Page Could Not Be Loaded</h1>
<p>We're very sorry, but the page could not be loaded properly. This should be fixed very soon, and we apologize for any inconvenience.</p>
<hr />
<h4>Debug Info:</h4>
<pre>Status: "} + obj.status + {"
Response: "} + obj.response + {"
XID: "} + req.xid + {"</pre>
  </div>
</body>
<div id="page">
<h1>Page Could Not Be Loaded</h1>
<p>We're very sorry, but the page could not be loaded properly. This should be fixed very soon, and we apologize for any inconvenience.</p>
<hr />
<h4>Debug Info:</h4>
<pre>Status: "} + obj.status + {"
Response: "} + obj.response + {"
XID: "} + req.xid + {"</pre>
  </div>
</body>
  </html>
 "};
 return(deliver);
}

Share this post


Link to post
Share on other sites
  • 0

now working with the cart, but not yet fully tested!

unstable: this code should be improved .....

small cookie problems: ... unique identifier witch tell Varnish use cache or not. (nocache_stable)

addition and improvements welcome :)

 

Hi Petrovv,

 

Have you made any progress with the cookie issues/nocache_stable?

Thanks for this, it might very well save me quite a bit of time later on!

 

Cheers,

K!

Share this post


Link to post
Share on other sites
  • 0

hi layer7,

 

Today I'm working on some things to test :)

 

Login: AuthController.php login etc > setcookie("varnish_nocache", 1, 0);

Logout: FrontController.php (isset($_GET['mylogout'])) > setcookie ("varnish_nocache", "", time() - 3600);

 

with google chrome: I think it works

but Cart not always filled.. working on...cart.php (if POST > cart.php :: setcookie) <_<

 

I'll come back when I know more

 

with only this control for cookie:

#unique identifier witch tell Varnish use cache or not

if (req.http.cookie ~ "varnish_nocache") {

return (pass);

}

Share this post


Link to post
Share on other sites
  • 0

Hello petrovv,

 

How did your testing go with the setting of the unique identifier? Did you make any other updates in the meantime?

 

Best regards,

K!

 

hi layer7,

 

Today I'm working on some things to test :)

 

Login: AuthController.php login etc > setcookie("varnish_nocache", 1, 0);

Logout: FrontController.php (isset($_GET['mylogout'])) > setcookie ("varnish_nocache", "", time() - 3600);

 

with google chrome: I think it works

but Cart not always filled.. working on...cart.php (if POST > cart.php :: setcookie) <_<

 

I'll come back when I know more

 

with only this control for cookie:

#unique identifier witch tell Varnish use cache or not

if (req.http.cookie ~ "varnish_nocache") {

return (pass);

}

Share this post


Link to post
Share on other sites
  • 0

Bonjour à tous,

 

j'ai mis cette configuration en production, et pour le moment le seul souci rencontré est la session sur le backoffice qui a tendance à se déconnecter assez rapidement, c'est un peu gênant quand on travail sur la préparation des commandes.

 

Quelqu'un d'autre aurait en production Varnish + Apache2 avec son prestashop ?

 

bien à vous.

Share this post


Link to post
Share on other sites
  • 0

@narigua

il vaut mieux que la langue anglaise est maintenue dans le forum prestashop. Cela fonctionne plus vite parce que les gens viennent de partout. Exemple, je viens des Pays-Bas et aussi il suffit d'écrire en anglais parce que c'est utile. ;)

 

@narigua & layer7

I've taken out of production because session and cookie very important that they work in a shop. My confidence is not enough that I get it working. With the new version (1.5) I have been to work and am working on a modulle of it for everyone. Sorry I did not post the findings here. it should work perfectly, and it can be. But first play with it.

 

@layer7

unique identification: varnish is no cache from there. that is not a problem. The varnish that tell whether or not a "hit" is not the problem, or a browser cookie and cache. I need the core files change and that is not smart. I want prestashop core remains intact. and I work now (version 1.5)

Share this post


Link to post
Share on other sites
  • 0

@Petrovv

Je comprends le souci de langage pour tout le monde, pas de souci, je vais suivre ;)

 

Hi all,

 

You can find here my new configuration of varnish, that depend of your apache configuration.

 

# This is a basic VCL configuration file for varnish.  See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition.  Set this to point to your content
# server.
#
acl purge {
   "localhost";
   "x.x.x.x"/24;
}
backend scm {
   .host = "scm";
   .port = "80";
}
backend prod {
   .host = "prod";
   .port = "80";
}
backend preprod {
   .host = "pre-prod";
   .port = "80";
}
backend phpmyadmin {
   .host = "phpmyadmin";
   .port = "80";
}
backend old {
   .host = "old";
   .port = "80";
}
sub vcl_recv {
   if	 (req.http.host ~ "^svn.mydomain.com$")	    { set req.backend = scm; return (pipe); }
   elseif (req.http.host ~ "^redmine.mydomain.com$")    { set req.backend = scm; return (pipe); }
   elseif (req.http.host ~ "^pre-prod.mydomain.com$")   { set req.backend = preprod; }
   elseif (req.http.host ~ "^prod.mydomain.com")	    { set req.backend = prod; }
   elseif (req.http.host ~ "^phpmyadmin.mydomain.com$") { set req.backend = phpmyadmin; }
   elseif (req.http.host ~ "^old.mydomain.com$")	    { set req.backend = old; }
   else														  { set req.backend = prod; }
   # allow PURGE from ACL
   if (req.request == "PURGE") {
    if (!client.ip ~ purge) {
	    error 405 "Not allowed.";
    }
    return (lookup);
   }
   # Force cache for web assets
   if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf)$") {
    unset req.http.Cookie;
    unset req.http.Accept-Encoding;
    unset req.http.Vary;
    return (lookup);
   }
   if (req.backend == preprod || req.backend == prod) {
    #we should not cache any page for Prestashop backend
    if (req.request == "GET" && (req.url ~ "^/backpresta")) {
	    return (pass);
    }
    #we should not cache any page for customers
    if (req.request == "GET" && (req.url ~ "^/authentication" || req.url ~ "^/my-account")) {
	    return (pass);
    }
    #we should not cache any page for customers
    if (req.request == "GET" && (req.url ~ "^/identity" || req.url ~ "^/my-account.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/cart.php" || req.url ~ "^/order.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/addresses.php" || req.url ~ "^/order-detail.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/order-confirmation.php" || req.url ~ "^/order-return.php")) {
	    return (pass);
    }
   }
   # Do not cache POST request
   if (req.request == "POST") {
  return (pipe);
   }
   # default
   if (req.restarts == 0) {
    if (req.http.x-forwarded-for) {
	    set req.http.X-Forwarded-For =
		    req.http.X-Forwarded-For + ", " + client.ip;
    } else {
	    set req.http.X-Forwarded-For = client.ip;
    }
   }
   if (req.request != "GET" &&
  req.request != "HEAD" &&
  req.request != "PUT" &&
  req.request != "POST" &&
  req.request != "TRACE" &&
  req.request != "OPTIONS" &&
  req.request != "DELETE") {
    /* Non-RFC2616 or CONNECT which is weird. */
    return (pipe);
   }
   if (req.request != "GET" && req.request != "HEAD") {
    /* We only deal with GET and HEAD by default */
    return (pass);
   }
   if (req.http.Authorization || req.http.Cookie) {
    /* Not cacheable by default */
    return (pass);
   }
   return (lookup);
}
sub vcl_fetch {
   set beresp.http.X-ServerID = beresp.backend.name;
   set beresp.grace = 5m;
   if (beresp.ttl < 8h) {
    set beresp.ttl = 8h;
   }
   if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
    unset beresp.http.set-cookie;
   }
   if (beresp.status == 403 || beresp.status == 404) {
    return (hit_for_pass);
   }
   ## Default
   if (beresp.ttl <= 0s ||
    beresp.http.Set-Cookie ||
    beresp.http.Vary == "*") {
		  /*
		   * Mark as "Hit-For-Pass" for the next 2 minutes
		   */
		  set beresp.ttl = 120 s;
		  return (hit_for_pass);
   }
   ## Deliver the content
   return(deliver);
}
sub vcl_hit {
   if (req.request == "PURGE") {
   purge;
   error 200 "PURGE";
   }
   # Default
   return (deliver);
}
sub vcl_miss {
   if (req.request == "PURGE") {
   purge;
   error 200 "PURGE";
   }
   # Default
   return (fetch);
}

 

For, you need to control the timeout of varnish to complete with the timeout of apache, for exemple, when you put in your apache.conf :

 

Timeout 60

 

You need to report it as a timeout in varnish conf for your backend as :

 

backend prod {
   .host = "prod";
   .port = "80";
   .connect_timeout = 60s;
   .first_byte_timeout = 60s;
}

 

ps : sorry for my bad english :)

Share this post


Link to post
Share on other sites
  • 0

Hi all,

 

Update of my config, now work for prestashop 1.4.x, and it's in my prod server :

 

# This is a basic VCL configuration file for varnish.  See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition.  Set this to point to your content
# server.
#
acl purge {
#    "localhost";
   "192.168.10.100"/24;
}
backend scm {
   .host = "scm";
   .port = "80";
}
backend prod {
   .host = "prod";
   .port = "80";
#   .connect_timeout = 60s;
#   .first_byte_timeout = 60s;
}
backend phpmyadmin {
   .host = "phpmyadmin";
   .port = "80";
}
sub vcl_recv {
   if	 (req.http.host ~ "svn.mydomain.fr$")	    {set req.backend = scm;}
   elseif (req.http.host ~ "prod.mydomain.fr")	    {set req.backend = prod;}
   elseif (req.http.host ~ "phpmyadmin.mydomain.fr$") {set req.backend = phpmyadmin;}
   else											 {set req.backend = prod;}

   # allow PURGE from ACL
   if (req.request == "PURGE") {
    if (!client.ip ~ purge) {
	    error 405 "Not allowed.";
    }
    return (lookup);
   }
   # Force cache for web assets
   if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf)$") {
    unset req.http.Cookie;
    unset req.http.Accept-Encoding;
    unset req.http.Vary;
    return (lookup);
   }
   if (req.backend == prod) {
    #we should not cache any page for Prestashop backend
    if (req.request == "GET" && (req.url ~ "^/admin")) {
	    return (pass);
    }
    #we should not cache any page for customers
    if (req.request == "GET" && (req.url ~ "^/authentication" || req.url ~ "^/my-account")) {
	    return (pass);
    }
    #we should not cache any page for customers
    if (req.request == "GET" && (req.url ~ "^/identity" || req.url ~ "^/my-account.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/cart.php" || req.url ~ "^/order.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/addresses.php" || req.url ~ "^/order-detail.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/order-confirmation.php" || req.url ~ "^/order-return.php")) {
	    return (pass);
    }
   }
   # Do not cache POST request
   if (req.request == "POST") {
  return (pipe);
   }
   # default
   if (req.restarts == 0) {
    if (req.http.x-forwarded-for) {
	    set req.http.X-Forwarded-For =
		    req.http.X-Forwarded-For + ", " + client.ip;
    } else {
	    set req.http.X-Forwarded-For = client.ip;
    }
   }
   if (req.request != "GET" &&
  req.request != "HEAD" &&
  req.request != "PUT" &&
  req.request != "POST" &&
  req.request != "TRACE" &&
  req.request != "OPTIONS" &&
  req.request != "DELETE") {
    /* Non-RFC2616 or CONNECT which is weird. */
    return (pipe);
   }
   if (req.request != "GET" && req.request != "HEAD") {
    /* We only deal with GET and HEAD by default */
    return (pass);
   }
   if (req.http.Authorization || req.http.Cookie) {
    /* Not cacheable by default */
    return (pass);
   }
   return (lookup);
}
sub vcl_fetch {
   set beresp.http.X-ServerID = beresp.backend.name;
   set beresp.grace = 5m;
   if (beresp.ttl < 8h) {
    set beresp.ttl = 8h;
   }
   if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
    unset beresp.http.set-cookie;
   }
   if (beresp.status == 403 || beresp.status == 404) {
    return (hit_for_pass);
   }
   ## Default
   if (beresp.ttl <= 0s ||
    beresp.http.Set-Cookie ||
    beresp.http.Vary == "*") {
		  /*
		   * Mark as "Hit-For-Pass" for the next 2 minutes
		   */
		  set beresp.ttl = 120 s;
		  return (hit_for_pass);
   }
   ## Deliver the content
   return(deliver);
}
sub vcl_hit {
   if (req.request == "PURGE") {
   purge;
   error 200 "PURGE";
   }
   # Default
   return (deliver);
}
sub vcl_miss {
   if (req.request == "PURGE") {
   purge;
   error 200 "PURGE";
   }
   # Default
   return (fetch);
}
sub vcl_error {
 // Let's deliver a friendlier error page.
 // You can customize this as you wish.
 set obj.http.Content-Type = "text/html; charset=utf-8";
 synthetic {"
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html>
    <head>
	  <title>"} + obj.status + " " + obj.response + {"</title>
	  <style type="text/css">
	  #page {width: 400px; padding: 10px; margin: 20px auto; border: 1px solid black; background-color: #FFF;}
	  p {margin-left:20px;}
	  body {background-color: #DDD; margin: auto;}
	  </style>
    </head>
    <body>
    <div id="page">
    <h1>Page Could Not Be Loaded</h1>
    <p>We're very sorry, but the page could not be loaded properly. This should be fixed very soon, and we apologize for any inconv$
    <hr />
    <h4>Debug Info:</h4>
    <pre>Status: "} + obj.status + {"
Response: "} + obj.response + {"
XID: "} + req.xid + {"</pre>
	  </div>
    </body>
    <div id="page">
    <h1>Page Could Not Be Loaded</h1>
    <p>We're very sorry, but the page could not be loaded properly. This should be fixed very soon, and we apologize for any inconv$
    <hr />
    <h4>Debug Info:</h4>
    <pre>Status: "} + obj.status + {"
Response: "} + obj.response + {"
XID: "} + req.xid + {"</pre>
	  </div>
    </body>
  </html>
 "};
 return(deliver);
}

Share this post


Link to post
Share on other sites
  • 0
slx    0

Hi Narigua,

Thanks for the config. This is the most detailed config I found on the web.

 

We have two problems with it. One is the backoffice connection lost (return to login page) very quickly and the other is a javascript error on product page of the backoffice (manufacturer AJAX error:parsererror).

Don't you have this kind of problems ?

 

My prestashop is 1.4.8.2

 

Regards

Share this post


Link to post
Share on other sites
  • 0

Hello narigua & petrovv,

 

For french reader: my old post about varnish : http://www.prestashop.com/forums/topic/130173-prestashop-et-les-serveurs-cache-http/page__p__632517?do=findComment&comment=632517

 

I think prestadev team is highly interested by varnish as i had a contact with someone from the team some month ago in order to look over my server config which was running varnish...

 

I had a similar config than yours but my main problem is when you update price on product page or product list...

 

Varnish still deliver old cache with wrong price and so on... The only solution i found is to update manualy varnsihcache via adm but it's very long when you have hundred of price updated..

 

So my question is: how did you manage this ?

Did you create a prestashop module which purge each time automatically varnish cache when you update the product page?

Or did you find a varnish cmd which compare stored page with apache server live

 

 

Thanks in advance

Share this post


Link to post
Share on other sites
  • 0

Hi

We are having some trouble with this varnish setup. First of all, when had commented out the line "the "Content-type" for static content, we lost the gzip compression for static assets. Commented it out, and gzip is working fine.

On the other side, varnish is not caching *any* dinamic page, and we think this is caused by cookies.

We added a non-ciphered cookie in order to track authenticated users, so we can make cat and don't cache anything for them, but for the anonymous ones, when the php file is served from varnish cache, and cookies are deleted, their sessions is lost.

 

In order to cache content for anonymous users, we are thinking about using ESI (edge side includes) for the cart part, but we don't know if the cookie will be served correctly to backends, nor if this solution is not so many experimental for a production site.

Edited by jorgevazquez

Share this post


Link to post
Share on other sites
  • 0

Hello,

 

Interesting topic, Prestashop can be an excellent candidate for ESI but you need to rewrite some components : basically, you have to create a new "Controller" to handle ESI sub-requests. We did this for Basket and some Session related modules.

 

After that, we cache all products, categories, CMS, home pages in Varnish for ALL users (since the dynamic parts are served by ESI).

 

Result .... much better, but not enough ! Because the each static page sub-requests will load all the Prestashop core, configuration etc..... To improve it, you can rewrite the ESI controller w/o Prestashop (but it will take some time...).

 

Note: you can replace ESI tags by AJAX calls (for test purpose or not), the user will receive the static page that will load the small dynamic fragments with AJAX, it can be sometime better than ESI (I mean the page will render faster than wait for ESI sub-requests since AJAX is async. but ESI not).

 

Note: before using Varnish, take a time to optimize the Mysql server (cache queries help a lot for Prestashop, mysql thread number ....), consider that Prestashop executes alsmot 100 queries per page (thats horrible) !

Share this post


Link to post
Share on other sites
  • 0

Hi everyone ;)

 

A little update of my config :

 

backend scm {
   .host = "scm";
   .port = "80";
}
backend prod {
   .host = "prod";
   .port = "80";
#   .connect_timeout = 60s;
#   .first_byte_timeout = 60s;
}
backend phpmyadmin {
   .host = "phpmyadmin";
   .port = "80";
}
sub vcl_recv {
   if	 (req.http.host ~ "svn.yourdomaine.fr$")	    {set req.backend = scm;}
   elseif (req.http.host ~ "prod.yourdomaine.fr")	    {set req.backend = prod;}
   elseif (req.http.host ~ "phpmyadmin.yourdomaine.fr$") {set req.backend = phpmyadmin;}
   else											 {set req.backend = prod;}

   # allow PURGE from ACL
#   if (req.request == "PURGE") {
#	   if (!client.ip ~ purge) {
#		   error 405 "Not allowed.";
#	   }
#	   return (lookup);
#   }
   # Force cache for web assets
   if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf)$") {
    unset req.http.Cookie;
    unset req.http.Accept-Encoding;
    unset req.http.Vary;
    return (lookup);
   }
if (req.backend == prod) {
    #we should not cache any page for Prestashop backend
    if (req.request == "GET" && (req.url ~ "^/admin")) {
	    return (pass);
    }
    #we should not cache any page for customers
    if (req.request == "GET" && (req.url ~ "^/authentication" || req.url ~ "^/my-account")) {
	    return (pass);
    }
    #we should not cache any page for customers
    if (req.request == "GET" && (req.url ~ "^/identity" || req.url ~ "^/my-account.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/cart.php" || req.url ~ "^/order.php")) {
	    return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/addresses.php" || req.url ~ "^/order-detail.php")) {
	  return (pass);
    }
    #we should not cache any page for sales
    if (req.request == "GET" && (req.url ~ "^/order-confirmation.php" || req.url ~ "^/order-return.php")) {
	    return (pass);
    }
   }
   # Do not cache POST request
   if (req.request == "POST") {
  return (pipe);
   }
   # default
   if (req.restarts == 0) {
    if (req.http.x-forwarded-for) {
	    set req.http.X-Forwarded-For =
		    req.http.X-Forwarded-For + ", " + client.ip;
    } else {
	    set req.http.X-Forwarded-For = client.ip;
    }
   }
   if (req.request != "GET" &&
  req.request != "HEAD" &&
  req.request != "PUT" &&
  req.request != "POST" &&
  req.request != "TRACE" &&
  req.request != "OPTIONS" &&
  req.request != "DELETE") {
    /* Non-RFC2616 or CONNECT which is weird. */
    return (pipe);
   }
   if (req.request != "GET" && req.request != "HEAD") {
    /* We only deal with GET and HEAD by default */
    return (pass);
   }
   if (req.http.Authorization || req.http.Cookie) {
    /* Not cacheable by default */
    return (pass);
   }
   return (lookup);
}
sub vcl_fetch {
   set beresp.http.X-ServerID = beresp.backend.name;
   set beresp.grace = 5m;
   if (beresp.ttl < 8h) {
    set beresp.ttl = 8h;
   }
   if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
    unset beresp.http.set-cookie;
   }
   if (beresp.status == 403 || beresp.status == 404) {
    return (hit_for_pass);
   }
   ## Default
   if (beresp.ttl <= 0s ||
    beresp.http.Set-Cookie ||
    beresp.http.Vary == "*") {
		  /*
		   * Mark as "Hit-For-Pass" for the next 2 minutes
		   */
		  set beresp.ttl = 120 s;
		  return (hit_for_pass);
   }
## Deliver the content
   return(deliver);
}
sub vcl_hit {
   if (req.request == "PURGE") {
   purge;
   error 200 "PURGE";
   }
   # Default
   return (deliver);
}
sub vcl_miss {
   if (req.request == "PURGE") {
   purge;
   error 200 "PURGE";
   }
   # Default
   return (fetch);
}

 

 

 

I just have a little problem with this configuration, if I run more than 20 simultaneous request, my server crashes ... An idea?

Share this post


Link to post
Share on other sites
  • 0

Found this. Did it work for everyone without issues?

 

http://blog.dh42.com/fastest-prestashop/

include "/usr/local/varnish/etc/varnish/cpanel.backend.vcl";
include "/usr/local/varnish/etc/varnish/vhost.vcl";
 
sub vcl_recv {
set req.backend = default;
include "/usr/local/varnish/etc/varnish/acl.vcl";
include "/usr/local/varnish/etc/varnish/vhost.exclude.vcl";
set req.grace = 5m;
 
   # Handle IPv6
   if (req.http.Host ~ "^ipv6.*") {
        set req.http.host = regsub(req.http.host, "^ipv6\.(.*)","www\.\1");
   }
 
    # Sanitise X-Forwarded-For...
    remove req.http.X-Forwarded-For;
    set req.http.X-Forwarded-For = client.ip;
     include "/usr/local/varnish/etc/varnish/cpanel.url.vcl"; 
    # Remove has_js and Google Analytics cookies.
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
 
    # Normalize the Accept-Encoding header
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv|pdf|ico)$") {
            # No point in compressing these
            remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            # unknown algorithm
            remove req.http.Accept-Encoding;
        }
    }
 
include "/usr/local/varnish/etc/varnish/url.exclude.vcl"; 
    # Ignore empty cookies
    if (req.http.Cookie ~ "^\s*$") {
        remove req.http.Cookie;
    }
 
          if (req.request == "PURGE") {
        if (!client.ip ~ acl127_0_0_1) {error 405 "Not permitted";}
        return (lookup);
}
 
    if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "POST" &&
       req.request != "PUT" &&
       req.request != "PURGE" &&
       req.request != "DELETE" ) {
    return (pipe);    
}
 
    if (req.request != "GET" && req.request != "HEAD") {
        /* We only deal with GET and HEAD by default, the rest get passed direct to backend */
        return (pass);
    }
 
if (req.http.Cookie ~ "^\s*$") {
        unset req.http.Cookie;
}
 
    if (req.http.Authorization || req.http.Cookie) {
        return (pass);
    }
 
set req.url = regsub(req.url, "\.js\?.*", ".js");
set req.url = regsub(req.url, "\.css\?.*", ".css");
set req.url = regsub(req.url, "\.jpg\?.*", ".jpg");
set req.url = regsub(req.url, "\.gif\?.*", ".gif");
set req.url = regsub(req.url, "\.swf\?.*", ".swf");
set req.url = regsub(req.url, "\.xml\?.*", ".xml");
 
# Cache things with these extensions
if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|pdf)$" && ! (req.url ~ "\.(php)") ) {
    unset req.http.Cookie;
    return (lookup);
}
 
return (lookup);
}
 
sub vcl_fetch {
 
set beresp.ttl = 45s;
set beresp.http.Server = " - ApacheBooster";
set beresp.http.cache-control = "max-age=90000";
set beresp.do_gzip = true;
set beresp.do_gunzip = false;
set beresp.do_stream = false;
set beresp.do_esi = false;
 
set beresp.grace = 5m;
 
unset beresp.http.expires;
if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|pdf|ico)$" && ! (req.url ~ "\.(php)") ) {
        unset beresp.http.set-cookie;
       include  "/usr/local/varnish/etc/varnish/static_file.vcl";
}
else {
         include  "/usr/local/varnish/etc/varnish/dynamic_file.vcl";
}
 
if (beresp.status == 503 || beresp.status == 500) {
        set beresp.http.X-Cacheable = "NO: beresp.status";
        set beresp.http.X-Cacheable-status = beresp.status;
        return (hit_for_pass);
}
 
if (beresp.status == 404) {
        set beresp.http.magicmarker = "1";
        set beresp.http.X-Cacheable = "YES";
        set beresp.ttl = 20s;
        return (deliver);
}
 
set beresp.http.magicmarker = "1";
set beresp.http.X-Cacheable = "YES";
 
}
sub vcl_deliver {
 
if ( obj.hits == 0 ) {
  set req.http.X-Stats-HitMiss = "miss";
 } else {
  set req.http.X-Stats-HitMiss = "hit";
 }
 
}
# what files to cache
sub vcl_recv {
   if (req.url ~ "\.(png|gif|jpg|ico|txt|swf|css|js)$") {
      return(lookup);
   }
}
 
# strip the cookie before the image is inserted into cache
sub vcl_fetch {
   if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
      unset beresp.http.set-cookie;
    unset req.http.Cookie;
 remove req.http.Cookie;
   }
}
 
# add response header to see if document was cached
sub vcl_deliver {
   if (obj.hits > 0) {
      set resp.http.X-Cache = "HIT";
   } else {
      set resp.http.X-Cache = "MISS";
   }
}

Share this post


Link to post
Share on other sites
  • 0

 

Found this. Did it work for everyone without issues?

 

http://blog.dh42.com/fastest-prestashop/

include "/usr/local/varnish/etc/varnish/cpanel.backend.vcl";
include "/usr/local/varnish/etc/varnish/vhost.vcl";
 
sub vcl_recv {
set req.backend = default;
include "/usr/local/varnish/etc/varnish/acl.vcl";
include "/usr/local/varnish/etc/varnish/vhost.exclude.vcl";
set req.grace = 5m;
 
   # Handle IPv6
   if (req.http.Host ~ "^ipv6.*") {
        set req.http.host = regsub(req.http.host, "^ipv6\.(.*)","www\.\1");
   }
 
    # Sanitise X-Forwarded-For...
    remove req.http.X-Forwarded-For;
    set req.http.X-Forwarded-For = client.ip;
     include "/usr/local/varnish/etc/varnish/cpanel.url.vcl"; 
    # Remove has_js and Google Analytics cookies.
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
 
    # Normalize the Accept-Encoding header
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv|pdf|ico)$") {
            # No point in compressing these
            remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            # unknown algorithm
            remove req.http.Accept-Encoding;
        }
    }
 
include "/usr/local/varnish/etc/varnish/url.exclude.vcl"; 
    # Ignore empty cookies
    if (req.http.Cookie ~ "^\s*$") {
        remove req.http.Cookie;
    }
 
          if (req.request == "PURGE") {
        if (!client.ip ~ acl127_0_0_1) {error 405 "Not permitted";}
        return (lookup);
}
 
    if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "POST" &&
       req.request != "PUT" &&
       req.request != "PURGE" &&
       req.request != "DELETE" ) {
    return (pipe);    
}
 
    if (req.request != "GET" && req.request != "HEAD") {
        /* We only deal with GET and HEAD by default, the rest get passed direct to backend */
        return (pass);
    }
 
if (req.http.Cookie ~ "^\s*$") {
        unset req.http.Cookie;
}
 
    if (req.http.Authorization || req.http.Cookie) {
        return (pass);
    }
 
set req.url = regsub(req.url, "\.js\?.*", ".js");
set req.url = regsub(req.url, "\.css\?.*", ".css");
set req.url = regsub(req.url, "\.jpg\?.*", ".jpg");
set req.url = regsub(req.url, "\.gif\?.*", ".gif");
set req.url = regsub(req.url, "\.swf\?.*", ".swf");
set req.url = regsub(req.url, "\.xml\?.*", ".xml");
 
# Cache things with these extensions
if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|pdf)$" && ! (req.url ~ "\.(php)") ) {
    unset req.http.Cookie;
    return (lookup);
}
 
return (lookup);
}
 
sub vcl_fetch {
 
set beresp.ttl = 45s;
set beresp.http.Server = " - ApacheBooster";
set beresp.http.cache-control = "max-age=90000";
set beresp.do_gzip = true;
set beresp.do_gunzip = false;
set beresp.do_stream = false;
set beresp.do_esi = false;
 
set beresp.grace = 5m;
 
unset beresp.http.expires;
if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|pdf|ico)$" && ! (req.url ~ "\.(php)") ) {
        unset beresp.http.set-cookie;
       include  "/usr/local/varnish/etc/varnish/static_file.vcl";
}
else {
         include  "/usr/local/varnish/etc/varnish/dynamic_file.vcl";
}
 
if (beresp.status == 503 || beresp.status == 500) {
        set beresp.http.X-Cacheable = "NO: beresp.status";
        set beresp.http.X-Cacheable-status = beresp.status;
        return (hit_for_pass);
}
 
if (beresp.status == 404) {
        set beresp.http.magicmarker = "1";
        set beresp.http.X-Cacheable = "YES";
        set beresp.ttl = 20s;
        return (deliver);
}
 
set beresp.http.magicmarker = "1";
set beresp.http.X-Cacheable = "YES";
 
}
sub vcl_deliver {
 
if ( obj.hits == 0 ) {
  set req.http.X-Stats-HitMiss = "miss";
 } else {
  set req.http.X-Stats-HitMiss = "hit";
 }
 
}
# what files to cache
sub vcl_recv {
   if (req.url ~ "\.(png|gif|jpg|ico|txt|swf|css|js)$") {
      return(lookup);
   }
}
 
# strip the cookie before the image is inserted into cache
sub vcl_fetch {
   if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
      unset beresp.http.set-cookie;
    unset req.http.Cookie;
 remove req.http.Cookie;
   }
}
 
# add response header to see if document was cached
sub vcl_deliver {
   if (obj.hits > 0) {
      set resp.http.X-Cache = "HIT";
   } else {
      set resp.http.X-Cache = "MISS";
   }
}

Did anyone managed to run Varnish with 1.5.6.2? And might PM me his Varnish conf? :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×