Astuces de Webmaster

7 octobre 2013

Varnish 3 basique : configurer Varnish sur le même serveur qu’Apache (débutants – exemple pour WordPress)

Architecture — Tags : Rom's @ 16:21

On va essayer de dédramatiser Varnish parce que c’est un outil qui fait peur et qui semble de prime abord très compliqué.

Ce qu’il faut savoir pour comprendre le fonctionnement : Varnish est un proxy qui se met entre la requête et la réponse pour éventuellement servir un cache.

Si on veut présenter de façon simpliste (sic) le fonctionnement, voici un schéma qui pourrait convenir
schema-varnish

Je vais ici vous initier à la configuration de Varnish qui offre de nombreuses possibilités, et notamment :

  • Exclure des domaines (pratique si plusieurs sites sur un même serveur)
  • Exclure des pages en fonction du contenu des URLs
  • Exclure des pages en fonction du protocole (POST est typiquement exclu par défaut)
  • Changer le temps par défaut de conservation en cache
  • Configurer le mode de purge (car on peut créer des scripts pour purger certaines URLs voulues)

1. Installation rapide de Varnish

 shell |  Copier le code |? 
1
2
sudo curl http://repo.varnish-cache.org/debian/GPG-key.txt | apt-key add -
3
sudo echo "deb http://repo.varnish-cache.org/debian/ $(lsb_release -s -c) varnish-2.1" >> /etc/apt/sources.list 
4
sudo apt-get update
5
sudo apt-get install varnish
6
apt-get install libapache2-mod-rpaf 
7

2. configuration basique pour Varnish

A mettre dans votre default.vcl

 shell |  Copier le code |? 
001
002
backend origin {
003
.host = "127.0.0.1";
004
.port = "8008";
005
.connect_timeout = 60s;
006
.first_byte_timeout = 60s;
007
.between_bytes_timeout = 60s;
008
}
009
#
010
sub vcl_recv {
011
# only using one backend
012
set req.backend = origin;
013
#
014
# set standard proxied ip header for getting original remote address
015
set req.http.X-Forwarded-For = client.ip;
016
#
017
# logged in users must always pass
018
if( req.url ~ "^/wp-(login|admin)" || req.http.Cookie ~ "wordpress_logged_in_" ){
019
return (pass);
020
}
021
# accept purges from w3tc and varnish http purge
022
if (req.request == "PURGE") {
023
return (lookup);
024
}
025
#
026
# don't cache search results
027
if( req.url ~ "\?s=" ){
028
return (pass);
029
}
030
#
031
# always pass through posted requests and those with basic auth
032
if ( req.request == "POST" || req.http.Authorization ) {
033
return (pass);
034
}
035
#
036
# else ok to fetch a cached page
037
unset req.http.Cookie;
038
return (lookup);
039
}
040
#
041
# accept purges from w3tc and varnish http purge
042
sub vcl_hit {
043
if (req.request == "PURGE") { purge; }
044
return (deliver);
045
}
046
#
047
# accept purges from w3tc and varnish http purge
048
sub vcl_miss {
049
if (req.request == "PURGE") { purge; }
050
return (fetch);
051
}
052
#
053
sub vcl_fetch {
054
#
055
# remove some headers we never want to see
056
unset beresp.http.Server;
057
unset beresp.http.X-Powered-By;
058
#
059
# only allow cookies to be set if we're in admin area - i.e. commenters stay logged out
060
if( beresp.http.Set-Cookie && req.url !~ "^/wp-(login|admin)" ){
061
unset beresp.http.Set-Cookie;
062
}
063
#
064
# don't cache response to posted requests or those with basic auth
065
if ( req.request == "POST" || req.http.Authorization ) {
066
return (hit_for_pass);
067
}
068
#
069
# only cache status ok
070
if ( beresp.status != 200 ) {
071
return (hit_for_pass);
072
}
073
#
074
# don't cache search results
075
if( req.url ~ "\?s=" ){
076
return (hit_for_pass);
077
}
078
#
079
# else ok to cache the response
080
set beresp.ttl = 24h;
081
return (deliver);
082
}
083
#
084
sub vcl_deliver {
085
# add debugging headers, so we can see what's cached
086
if (obj.hits > 0) {
087
set resp.http.X-Cache = "HIT";
088
}
089
else {
090
set resp.http.X-Cache = "MISS";
091
}
092
# remove some headers added by varnish
093
unset resp.http.Via;
094
unset resp.http.X-Varnish;
095
}
096
#
097
sub vcl_hash {
098
hash_data( req.url );
099
# altering hash so subdomains are ignored.
100
# don't do this if you actually run different sites on different subdomains
101
if ( req.http.host ) {
102
hash_data( regsub( req.http.host, "^([^\.]+\.)+([a-z]+)$", "\1\2" ) );
103
} else {
104
hash_data( server.ip );
105
}
106
# ensure separate cache for mobile clients (WPTouch workaround)
107
if( req.http.User-Agent ~ "(iPod|iPhone|incognito|webmate|dream|CUPCAKE|WebOS|blackberry9\d\d\d)" ){
108
hash_data("touch");
109
}
110
return (hash);
111
}
112

Après cela, redémarrez Varnish :

 shell |  Copier le code |? 
1
2
service varnish restart
3

Dans chacun de vos vhosts (sous Apache 2, ils sont dans /etc/apache2/sites-available), mettez l’écoute sur le port 8008 (dans le nom du vhost)
Ex :

Changez ensuite la configuration dans le dossier parent : /etc/apache2/ports.conf pour forcer Apache à écouter sur le port 8008 (j’utilise 8008, mais ça pourrait être n’importe quel port autre que 80 ; par convention, on utilise un nombre à quatre chiffres commençant par 80xx, 8080, 8000, 8008,..)

 shell |  Copier le code |? 
1
2
NameVirtualHost *:8008
3
Listen 8008
4

Redémarrez Apache

 shell |  Copier le code |? 
1
2
service apache2 restart
3

A ce niveau, votre site devrait fonctionner. Chargez une page en regardant son temps de chargement de code source HTML (via firebug, la première ressource chargée dans l’onglet « Réseau », par exemple), puis rechargez la page et comparez le temps de chargement. Via Firebug (et Chrome aussi), vous aurez sur cette ressource un onglet « cache » qui précise la date d’expiration, le nombre de fois où la ressource a été servie depuis qu’elle est en cache, etc.

cache-varnish

3. Les astuces / Aller plus loin

Condition sur le host

 shell |  Copier le code |? 
1
2
	if(req.http.host ~ "sampleOfSiteNotToCache\.com") {
3
		#do not cache post requests
4
		if(req.request=="POST") { 
5
			return(hit_for_pass); 
6
		}
7
	}
8

Exclure ressources statiques

 shell |  Copier le code |? 
01
02
    # If the request is static
03
    if (req.url ~ "\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)$") {
04
      # Cache it, and make it last 2 hours
05
      set beresp.ttl = 7200s;
06
      # Make the request static by removing any cookies set by those static files
07
      unset beresp.http.set-cookie;
08
      # Deliver the cached object
09
      return (deliver);
10
    }
11

Retirer les cookies sur les ressources statiques (dans vcl_recv)

 shell |  Copier le code |? 
1
2
if (req.url ~ "\.(png|gif|jpg|swf|css|js|mp3|flv)$") {
3
    unset req.http.cookie;
4
    return(lookup);
5
        }
6

Condition sur un cookie, notamment un cookie créé lorsqu’on se logge sur wordpress

 shell |  Copier le code |? 
01
02
    # If I am logged in to wordpress, I DO NOT WANT TO SEE cached pages
03
    if (req.http.cookie ~ "wordpress_logged_in") {
04
      return (pass);
05
    } else {
06
      # Cache anything for 2 minutes. When the cache expires it will be cached again and again, at the time of the request
07
      set beresp.ttl = 120s;
08
      return (deliver);
09
    }
10

Spécifier un TTL si pas déjà spécifié par le document renvoyé par le serveur Apache

 shell |  Copier le code |? 
01
02
    if (beresp.ttl <= 0s ||
03
        beresp.http.Set-Cookie ||
04
        beresp.http.Vary == "*") {
05
		/*
06
		 * Mark as "Hit-For-Pass" for the next 2 minutes
07
		 */
08
		/*set beresp.ttl = 120 s;*/
09
		set beresp.ttl = 1440m;
10
		return (hit_for_pass);
11
    }
12

Supprimer les entêtes créées automatiquement

 shell |  Copier le code |? 
01
02
sub vcl_deliver {
03
  # Secure the header
04
  /*remove resp.http.Via;
05
  remove resp.http.X-Varnish;
06
  remove resp.http.Server;
07
  remove resp.http.X-Powered-By;*/
08
    return (deliver);
09
}
10

Définir les IPs qui ont le droit de solliciter Varnish pour la purge (suppression de pages dans le cache pour forcer le rechargement)

 shell |  Copier le code |? 
1
2
# Hosts autorized to purge
3
acl purge {
4
        "localhost";
5
        "192.168.51.3"/32;
6
        "192.168.51.4"/32;
7
}
8

Définir un backend différent (un serveur à écouter différent) en fonction d’une condition

 shell |  Copier le code |? 
1
2
#    if (req.http.host ~ "^monsite\.com$" || req.http.host ~ "^www\.monsite\.com$"){
3
#        if ( req.url ~ "^/en" || req.url ~ "^/it" || req.url ~ "^/es" || req.url ~ "^/nl" || req.url ~ "^/de" || req.url ~ "^/on" || req.url ~ "^/kr" || req.url ~ "^/uk"){
4
#            set req.backend = demandware;
5
#            return(pass);
6
#        }
7
#    }
8

Ne pas s’occuper de certaines pages qui ne doivent pas être cachées (dans sub vcl_recv)

 shell |  Copier le code |? 
1
2
if (req.url ~ ".*identite.*" || req.url ~ ".*remboursement.*" || req.url ~ ".*adresse.*" || req.url ~ ".*favori.*" || req.url ~ ".*bons.*" ){
3
        return(pass);
4
    }
5

Spécifier une entête

 shell |  Copier le code |? 
1
2
  set req.http.X-Forwarded-For =
3
                "192.168.X.X, " + client.ip;
4

Supprimer les cookies google analytics et has_js

 shell |  Copier le code |? 
1
2
    // Remove has_js and Google Analytics __* cookies.
3
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
4
    // Remove a ";" prefix, if present.
5
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
6

Limiter l’espace disque dédié à Varnish

 shell |  Copier le code |? 
01
02
## Alternative 1, Minimal configuration, no VCL
03
#
04
# Listen on port 6081, administration on localhost:6082, and forward to
05
# content server on localhost:8080.  Use a 1GB fixed-size cache file.
06
#
07
# DAEMON_OPTS="-a :6081 \
08
#              -T localhost:6082 \
09
#          -b localhost:8080 \
10
#          -u varnish -g varnish \
11
#            -S /etc/varnish/secret \
12
#          -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"
13
14
15
## Alternative 2, Configuration with VCL
16
#
17
# Listen on port 6081, administration on localhost:6082, and forward to
18
# one content server selected by the vcl file, based on the request.  Use a 1GB
19
# fixed-size cache file.
20
#
21
#DAEMON_OPTS="-a :6081 \
22
#             -T localhost:6082 \
23
#             -f /etc/varnish/default.vcl \
24
#             -S /etc/varnish/secret \
25
#             -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"
26
27
28
## Alternative 3, Advanced configuration
29
#
30
# See varnishd(1) for more information.
31
#
32
# # Main configuration file. You probably want to change it :)
33
 VARNISH_VCL_CONF=/etc/varnish/default.vcl
34
#
35
# # Default address and port to bind to
36
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
37
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
38
 VARNISH_LISTEN_ADDRESS=
39
 VARNISH_LISTEN_PORT=80
40
#
41
# # Telnet admin interface listen address and port
42
 VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
43
 VARNISH_ADMIN_LISTEN_PORT=6082
44
#
45
# # The minimum number of worker threads to start
46
 VARNISH_MIN_THREADS=1
47
#
48
# # The Maximum number of worker threads to start
49
 VARNISH_MAX_THREADS=1000
50
#
51
# # Idle timeout for worker threads
52
 VARNISH_THREAD_TIMEOUT=120
53
#
54
# # Cache file location
55
 VARNISH_STORAGE_FILE=/var/lib/varnish/$INSTANCE/varnish_storage.bin
56
#
57
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
58
# # or in percentage of available disk space using the % suffix.
59
 VARNISH_STORAGE_SIZE=5G
60
#
61
# # File containing administration secret
62
 VARNISH_SECRET_FILE=/etc/varnish/secret
63
# 
64
# # Backend storage specification
65
# VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
66
 VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"
67
#
68
# # Default TTL used when the backend does not specify one
69
# VARNISH_TTL=120
70
 VARNISH_TTL=3600
71
#
72
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
73
# # sure you update this section, too.
74
 DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
75
              -f ${VARNISH_VCL_CONF} \
76
              -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
77
              -t ${VARNISH_TTL} \
78
              -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
79
            -S ${VARNISH_SECRET_FILE} \
80
              -s ${VARNISH_STORAGE}"
81
82
83
84
## Alternative 4, Do It Yourself
85
#
86
# DAEMON_OPTS=""
87

Petit bonus : un script PHP pour purger le cache d’une URL sur Varnish

 PHP |  Copier le code |? 
01
02
<?php
03
if(!isset($_GET['url'])) die('preciser \'url\' en mode relatif (ex: /fr/ma/page) svp');
04
header( 'Content-Type: text/plain' );
05
header( 'Cache-Control: max-age=0' );
06
$hostname = '192.168.51.1';
07
$port     = 80;
08
$URL      = $_GET['url'];
09
$debug    = true;
10
 
11
print "will delete URL in cache ...\n";
12
purgeURL( $hostname, $port, $URL, $debug );
13
 
14
 
15
function purgeURL( $hostname, $port, $purgeURL, $debug )
16
{
17
    $finalURL = sprintf(
18
        "http://%s:%d%s", $hostname, $port, $purgeURL
19
    );
20
 
21
    print( "Purging ${finalURL}\n" );
22
 
23
    $curlOptionList = array(
24
        CURLOPT_RETURNTRANSFER    => true,
25
        CURLOPT_CUSTOMREQUEST     => 'PURGE',
26
        CURLOPT_HEADER            => true ,
27
        CURLOPT_NOBODY            => true,
28
        CURLOPT_URL               => $finalURL,
29
        CURLOPT_CONNECTTIMEOUT_MS => 2000
30
    );
31
 
32
    $fd = false;
33
    if( $debug == true ) {
34
        print "\n---- Curl debug -----\n";
35
        $fd = fopen("php://output", 'w+');
36
        $curlOptionList[CURLOPT_VERBOSE] = true;
37
        $curlOptionList[CURLOPT_STDERR]  = $fd;
38
    }
39
 
40
    $curlHandler = curl_init();
41
    curl_setopt_array( $curlHandler, $curlOptionList );
42
    curl_exec( $curlHandler );
43
    curl_close( $curlHandler );
44
    if( $fd !== false ) {
45
        fclose( $fd );
46
    }
47
}
48
?>
49

Sources :
– http://www.howtoforge.com/putting-varnish-in-front-of-apache-on-ubuntu-debian
– https://gist.github.com/jeremyjbowers/1542949
– http://memo-linux.com/booster-votre-blog-wordpress-avec-varnish/
– http://toptenstuff.net/2013/09/how-to-configure-varnish-to-work-with-w3-total-cache/#

7 mai 2013

[OVH] Renouveler uniquement le nom de domaine quand on a un pack domaine+hébergement mutualisé

Architecture — Tags : , Rom's @ 19:53

Je me posais la question de s’il était possible de ne renouveler que le domaine et pas l’hébergement mutualisé chez OVH.

Dans le formulaire de renouvellement, on ne peut dissocier le nom de domaine de l’hébergement.

En farfouillant dans le manager, j’ai constaté qu’il y avait un formulaire à dispo pour résilier l’hébergement mutu seul. J’ai un peu pris peur.

En cherchant plus loin, j’ai trouvé la solution pour renouveler le domaine seul chez OVH, je partage car ça peut en aider certains à ne pas se faire « avoir »…

Connectez-vous au manager, puis retournez sur la page d’accueil d’OVH, saisissez votre nom de domaine comme si vous souhaitiez le commander. OVH vous proposera de le renouveler. Renouvelez-le, vous n’aurez à payer que la partie du nom de domaine si vous ne sélectionnez pas l’hébergement. L’hébergement expirera comme prévu et non le nom de domaine.
ovh-renew

CQFD

23 avril 2013

Récupérer des informations via l’API Google Analytics avec PHP (GAPI)

Voici un petit bout de code bien utile, basé sur l’API Google Analytics et sur la classe GAPI pour récupérer des données du célèbre outil de statistiques site-centric.

 PHP |  Copier le code |? 
01
02
<?php
03
require 'gapi.class.php';
04
$ga = new gapi('loginGoogleAnalytics','MotDePasseAnalytics');
05
// paramètres
06
$report_id		= 'XXXXXX'; // il s'agit de l'ID du profil, pas le UA, mais l'ID que l'admin peut trouver dans les paramètres du profil
07
$dimensions		= array('customVarValue1'); // on veut les variables du slot 1
08
$metrics		= array('visits','timeOnSite'); //  on veut récupérer le nombre de visites et la durée de connexion
09
$sort_metric		= 'customVarValue1'; // on trie par nom d'utilisateur croissant
10
$filter			= null;
11
$start_date		= '2012-03-15'; // pour la journée du 15 mars 2012
12
$end_date		= '2012-03-15';
13
$start_index	= 1;
14
$max_results	= 30;
15
 
16
$ga->requestReportData($report_id,$dimensions,$metrics,$sort_metric,$filter,$start_date,$end_date,$start_index,$max_results);
17
 
18
foreach($ga->getResults() as $result)
19
{
20
	echo $result .": \r\n";
21
	echo "\tVisits : ". $result->getVisits() . "\r\n";
22
	echo "\tTimeOnSite : ". $result->getTimeOnSite() . " secondes\r\n";
23
}
24
 
25

Source : Tracer le temps de connexion des utilisateurs via Google Analytics

Articles plus anciens »

Romain BOYER ©2014 - Contact : boyer Arobase romain Point biz - Profil sur LinkedIn - Profil sur Google+