hoangweb
4/16/2016 - 1:09 PM

varnish/default.vcl

varnish/default.vcl

# Define the internal network subnet.
# These are used below to allow internal access to certain files while not
# allowing access from the public internet.
# define the allowed addresses which can access the cron.php or install.php
acl internal {
  "192.10.0.0"/24;
}

backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .connect_timeout = 600s;
    .first_byte_timeout = 600s;
    .between_bytes_timeout = 600s;
    .max_connections = 800;
    .saintmode_threshold = 0;
    .probe = {
      .url = "/";
      .interval = 5s;
      .timeout = 1s;
      .window = 5;
      .threshold = 3;
    }
}
# Port 80 Backend Servers
backend web1 {
    .host = "192.10.0.1";
    .port = "80";
    .connect_timeout = 1s;
    .first_byte_timeout = 5s;
    .between_bytes_timeout = 2s;
}
# Port 443 Backend Servers for SSL
backend web1_ssl { 
    .host = "192.10.0.1"; 
    .port = "443"; 
    .probe = { 
        .url = "/status.php"; 
        .interval = 5s; 
        .timeout = 1 s; 
        .window = 5;
        .threshold = 3; 
    }
}

backend web2 { 
    .host = "192.10.0.2"; 
    .probe = { 
        .url = "/status.php"; 
        .interval = 5s; 
        .timeout = 1s; 
        .window = 5;
        .threshold = 3; 
    }
}
backend web2_ssl { 
    .host = "192.10.0.2"; 
    .port = "443"; 
    .probe = { 
        .url = "/status.php"; 
        .interval = 5s; 
        .timeout = 1 s; 
        .window = 5;
        .threshold = 3; 
    }
}

# Define the director that determines how to distribute incoming requests.
director default_director round-robin {
  { .backend = web1; }
  { .backend = web2; }
}

director ssl_director round-robin {
  { .backend = web1_ssl; }
  { .backend = web2_ssl; }
}

# -------------------------------------------------------------------
# usage: (client.ip ~ purge)
acl purge { # Who is allowed to purge?
    # Web server with plugin which will issue PURGE requests
    "localhost";
    "127.0.0.1";
    "wheezy.dimitri.eu";      # Just my server its hostname
}

# Respond to incoming requests.
sub vcl_recv {
    
    # Set the director to cycle between web servers.
    if (server.port == 443) {
        set req.backend = ssl_director;
    }
    else {
        set req.backend = default_director;
    }
    if (req.http.host ~ "^dayhocphotoshop.com$") { 
        set req.backend = dayhocpts; 
    }
    else {
        return (pass);  # prevent 503 error Guru Meditation
    }
    if (req.backend.healthy) {
        set req.grace = 2h;
        set req.ttl = 5s;
      } else {
        # Accept serving stale object (extend TTL by 6h)
        # Allow the backend to serve up stale content if it is responding slowly.
        set req.grace = 6h;
      }
      
    # Block the forbidden IP addresse
    #if (client.ip ~ forbidden) {
    #    	error 403 "Forbidden";
	#}
    
    # Do not allow outside access to cron.php or install.php.
    if (req.url ~ "^/(cron|install)\.php$" && !client.ip ~ internal) {
        # Have Varnish throw the error directly.
        error 404 "Page not found.";
        # Use a custom error page that you've defined in Drupal at the path "404".
        # set req.url = "/404";
    }
  
    # Only cache the following sites
    #if ((req.http.host ~ "(blog.nicolargo.com)") || (req.http.host ~ "(blogtest.nicolargo.com)")) { 
	if ((req.http.host ~ "(blog.nicolargo.com)")) { 
		set req.backend = default; 
	} else { 
		return (pass); 
	}
    
    # Compatibility with Apache format log
    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;
	 	}
    }
    
    # Normalize the header, remove the port (in case you're testing this on various TCP ports)
    set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
    
    # Check if we may purge (only localhost)
    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "This IP is not allowed to send PURGE requests";
        }
        ban("req.url ~ ^" + req.url + "$ && req.http.host == " + req.http.host);
        #Below is used with Varnish version < 3.0. Comment out ban above if using those versions
        #purge("req.url ~ ^" req.url "$ && req.http.host == "req.http.host);
        return(lookup);
    }
    # Default request checks
    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.request != "GET" && req.request != "HEAD") {
    # We only deal with GET and HEAD by default
        return (pass);
    }

    ## Modified from default to allow caching if cookies are set, but not http auth
    if (req.http.Authorization) {
        /* Not cacheable by default */
        return (pass);
    }
    
    # Pipe these paths directly to Apache for streaming.
    if (req.url ~ "^/admin/content/backup_migrate/export") {
      return (pipe);
    }
    # example for drupal
    if (req.request != "GET" && req.request != "HEAD") {
        # /* We only deal with GET and HEAD by default */
        return (pass);
    }

    # Normalize content-encoding
    # Properly handle different encoding types
    # NOTE: Varnish 3 you can remove the Accept-Encoding logic
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
            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 {
            #remove req.http.Accept-Encoding;
            unset req.http.Accept-Encoding;    #or
        }
    }
    # admin users always miss the cache
    if( req.url ~ "^/wp-(login|admin)" || 
        req.http.Cookie ~ "wordpress_logged_in_" ){
            return (pass);
    }
    # Check the cookies for wordpress-specific items
    if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
		return (pass);
	}
            
    # Remove cookies set by Google Analytics (pattern: '__utmABC')
    if (req.http.Cookie) {
        set req.http.Cookie = regsuball(req.http.Cookie,
            "(^|; ) *__utm.=[^;]+;? *", "\1");
        if (req.http.Cookie == "") {
            unset req.http.Cookie;      # or remove
        }
    }
    
    # Set client IP
    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;
    }
    
    # always pass through POST requests and those with basic auth
    if (req.http.Authorization || req.request == "POST") {
        return (pass);
    }
    # Did not cache HTTP authentication and HTTP Cookie
    if (req.http.Authorization || req.http.Cookie) {
		# Not cacheable by default
		return (pass);
	}
    
    # Do not cache these paths
    if (req.url ~ "^/wp-cron\.php$" ||
        req.url ~ "^/xmlrpc\.php$" ||
        req.url ~ "^/wp-admin/.*$" ||
        req.url ~ "^/wp-includes/.*$" ||
        req.url ~ "\?s=") {
            return (pass);
    }
    
    # ignore cookie for product page, it might pesudo static page
    if (req.url ~ "^/[^?]+-product-?+\.(html)(\?.*|)$") {
        unset req.http.cookie;
    }
    # remove Cookies on home page
    if (req.url ~ "^/$") {
        unset req.http.cookie;
    }
    # Remove cookies and query string for real static files
    if (req.url ~ "^/[^?]+\.(gif|jpg|jpeg|swf|css|js|txt|flv|mp3|mp4|pdf|ico|png|gz|zip|lzma|bz2|tgz|tbz)(\?.*|)$") {
       unset req.http.cookie;
       set req.url = regsub(req.url, "\?.*$", "");
    }
    if (req.url ~ "\?(utm_(campaign|medium|source|term)|adParams|client|cx|eid|fbid|feed|ref(id|src)?|v(er|iew))=") {
       set req.url = regsub(req.url, "\?.*$", "");
    }
    
    # Force lookup if the request is a no-cache request from the client
#   if (req.http.Cache-Control ~ "no-cache") {
#       return (pass);
#   }

    # Define the default grace period to serve cached content
    # Allow a grace period for offering "stale" data in case backend lags
    set req.grace = 30s;
    
    remove req.http.X-Forwarded-For;
    set req.http.X-Forwarded-For = client.ip;
    
    if (req.http.cookie) {
       if (req.http.cookie ~ "(wp-settings-)") {
         return(pass);
       } else {
         unset req.http.cookie;
       }
    }
    
    # Remove the "has_js" cookie and Google Analytics cookies.
    set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");

	# Remove any Google Analytics based cookies
	set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");

	# Remove the Quant Capital cookies (added by some plugin, all __qca)
	set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");

	# Remove the wp-settings-1 cookie
	set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");

	# Remove the wp-settings-time-1 cookie
	set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");

	# Remove the wp test cookie
	set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");
    
    # Are there cookies left with only spaces or that are empty?
    if (req.http.cookie ~ "^ *$" || req.http.Cookie == "" || req.http.Cookie ~ "^\s*$") {
		unset req.http.cookie;
	}
    
    # Don't cache backend
    if (req.url ~ "wp-(login|admin|comments-post.php|cron.php)") {
        return (pass);
    }
    # Did not cache the RSS feed
    if (req.url ~ "/feed") {
		return (pass);
	}
    # Blitz hack
    if (req.url ~ "/mu-.*") {
            return (pass);
    }
    ## Pass php page
    if (req.url ~ ".php") {
        return (pass);
    }
    
    # By ignoring any other cookies, it is now ok to get a page
    #unset req.http.Cookie;
    # Use anonymous, cached pages if all backends are down.
    if (!req.backend.healthy) {     # If all web servers go down, this flag becomes FALSE
        unset req.http.Cookie;
    }
    
    # don't do a return (lookup) so the default vcl_recv runs anyway and it will pass if any cookie is present. 
    #return (lookup); 
}

# Code determining what to do when serving items from the Apache servers.
sub vcl_fetch {

    # remove some headers we never want to see
    unset beresp.http.Server;
    unset beresp.http.X-Powered-By;
    
    # keep all objects for 6h beyond their TTL
    # Allow items to be stale if needed.
    set beresp.grace = 6h;
    
    if (beresp.ttl < 3600s) {
        set beresp.ttl = 3600s;
    }
        
    # If we fetch a 500, serve stale content instead
    if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 ) {
        set beresp.saintmode = 30s;
        return(restart);
    }

    # do not cache blank pages
    if (beresp.http.Content-Length == "0"){
        return(restart);
    }
    if( beresp.status>=500) {
        set beresp.ttl = 0s;
        set beresp.uncacheable = true;   # or cacheable = false
    }
  
  # Don't store backend
  if (req.url ~ "wp-(login|admin|comments-post.php|cron.php)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
    return (hit_for_pass);
  }
    # For static content strip all backend cookies
    if (req.url ~ "\.(css|js|png|gif|jp(e?)g)|swf|ico") {
		unset beresp.http.cookie;
	}
    # only allow cookies to be set if we're in admin area
    if( beresp.http.Set-Cookie && req.url !~ "^/wp-(login|admin)" ){
        unset beresp.http.Set-Cookie;
    }
    if ( (!(req.url ~ "(wp-(login|admin|comments-post.php|cron.php)|login)")) || (req.request == "GET") ) {
        unset beresp.http.set-cookie;
        set beresp.ttl = 4h;
    }
    # don't cache response to posted requests or those with basic auth
    if ( req.request == "POST" || req.http.Authorization ) {
        return (hit_for_pass);
    }
    # don't cache search results
    if( req.url ~ "\?s=" ){
        return (hit_for_pass);
    }
    
  if (req.url ~ "\.(gif|jpg|jpeg|swf|css|js|txt|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") {
     set beresp.ttl = 30d;
  } #else {
  # set beresp.do_esi = true;
  #}
    # Cache the following files extensions 
    if (req.url ~ "\.(css|js|png|gif|jp(e)?g|swf|ico)") {
		unset req.http.cookie;
	}
    
    # only cache status ok
    if ( beresp.status != 200 ) {
        return (hit_for_pass);
    }
    
    # If our backend returns 5xx status this will reset the grace time
    # set in vcl_recv so that cached content will be served and 
    # the unhealthy backend will not be hammered by requests
    if (beresp.status == 500) {
        set beresp.grace = 60s;
        return (restart);
    }
    if (beresp.cacheable && !beresp.http.cache-control) {
      set beresp.ttl = 600s;
      set beresp.http.cache-control = "max-age=600";
    }
    # GZip the cached content if possible
    if (beresp.http.content-type ~ "text") {
        set beresp.do_gzip = true;
    }
 
    # if nothing abovce matched it is now ok to cache the response
    set beresp.ttl = 24h;
    return (deliver);
}


sub vcl_hit {
    if (req.request == "PURGE") {
        purge;
        set obj.ttl = 0s;
        error 200 "Purged.";
    }
    return (deliver);
}

sub vcl_miss {
    # Set up invalidation of the cache so purging gets done properly
    if (req.request == "PURGE") {
        purge;
        error 200 "Purged.";
    }
    return (fetch);
}

sub vcl_deliver {
    if (obj.hits > 0) { 
    	set resp.http.X-Cache = "cached";
	} else {
		set resp.http.x-Cache = "uncached";
	}
    # remove some headers added by varnish
    unset resp.http.Via;
    unset resp.http.X-Varnish;  # remove X-Varnish
    
    # Remove some headers: PHP version
    unset resp.http.X-Powered-By;
    
    # Remove some headers: Apache version & OS
    unset resp.http.Server;
    
    if(req.restarts > 0){
        std.log("Log: The URL " + req.url + " has been restarted " + req.restarts + " times");
    }
    if(req.http.x-no-content == "1"){
        if( std.integer(resp.http.Content-Length,0) > 50 ){
            std.log("Log: The URL " +  req.http.host + req.url + " was blank on first load, but now has a content length of " + resp.http.Content-Length);
            set req.http.x-cacheable = 1;
            return(restart);
        }
    
        if( std.integer(resp.http.Content-Length,0) < 50 ){
            std.log("Log: The URL " + req.http.host + req.url + " was blank on first load, and now is still blank " + resp.http.Content-Length);
        }
    }
    return (deliver);
}

# This function is used when a request is sent by our backend (Nginx server)
# cache responses with a cookie
sub vcl_backend_response {
    # Remove some headers we never want to see
	unset beresp.http.Server;
	unset beresp.http.X-Powered-By;
    
    # Varnish uses the max-age parameter in the Cache-Control HTTP header to establish how long the content is considered fresh before contacting the backend again. Varnish will use 120 seconds by default if this value is missing or is equal to zero. 
    if (beresp.ttl == 120s) {
        set beresp.ttl = 2h;
    }

	# For static content strip all backend cookies
	if (req.url ~ "\.(css|js|png|gif|jp(e?)g)|swf|ico") {
		unset beresp.http.cookie;
	}

	# Only allow cookies to be set if we're in admin area
	if (beresp.http.Set-Cookie && req.url !~ "^/wp-(login|admin)") {
        	unset beresp.http.Set-Cookie;
    	}

	# don't cache response to posted requests or those with basic auth
	if ( req.request == "POST" || req.http.Authorization ) {
        set beresp.uncacheable = true;      #v2
		#set beresp.ttl = 120s;     # varnish v3
		return (deliver);
    }
 
    	# don't cache search results
	if ( req.url ~ "\?s=" ){
		set beresp.uncacheable = true;
        set beresp.ttl = 120s;
        return (deliver);
	}
    
	# only cache status ok
	if ( beresp.status != 200 ) {
		set beresp.uncacheable = true;
        set beresp.ttl = 120s;
        return (deliver);
	}

	# A TTL of 24h
	set beresp.ttl = 24h;
	# Define the default grace period to serve cached content
	set beresp.grace = 30s;
	
	return (deliver);
}

# In the event of an error, show friendlier messages.
sub vcl_error {
    set obj.http.Content-Type = "text/html; charset=utf-8";
    synthetic {"
    <html>
    <head>
      <title>Pagina no disponible temporalmente</title>
      <style>
        body { background: #303030; text-align: center; color: white; }
        #page { border: 1px solid #CCC; width: 500px; margin: 100px auto 0;
    padding: 30px; background: #323232; }
        a, a:link, a:visited { color: #CCC; }
        .error { color: #222; }
      </style>
    </head>
    <body>
      <div id="page">
        <h1 class="title">Oops! Houston tenemos problemas!</h1>
        <p>La pagina que estas intentando ver por el momento no esta
    disponible..</p>
        <p>Intenta <a href="">recargando la pagina </a> o puedes visitar <a
    href="/">Nuestra pagina principal</a></p>
        <div class="error">(Error "} + obj.status + " " + obj.response +
    {")</div>
      </div>
    </body>
    </html>
    "};

    if (obj.status == 503) {
        # set obj.http.location = req.http.Location;
        set obj.status = 404;
        set obj.response = "Not Found";
        return (deliver);
    }
}
sub vcl_pipe {
    return (pipe);
}
sub vcl_pass {
    return (pass);
}

# The data on which the hashing will take place
# Routine used to determine the cache key if storing/retrieving a cached page.
sub vcl_hash {
    hash_data(req.url);
 	if (req.http.host) {
     	hash_data(req.http.host);
 	} else {
     	hash_data(server.ip);
 	}

	# If the client supports compression, keep that in a different cache
    	if (req.http.Accept-Encoding) {
        	hash_data(req.http.Accept-Encoding);
	}
    # Do NOT use this unless you want to store per-user caches.
    if (req.http.Cookie) {
        set req.hash += req.http.Cookie;
    }
  
	return (hash);
}
sub vcl_init {
    return (ok);
}

sub vcl_fini {
    return (ok);
}


# end Varnish 3