WordPress est aujourd’hui le CMS le plus utilisé en terme de part de marché, mais de nombreux sites actuellement en ligne ne sont pas optimisés. L’utilisation de thèmes non optimisés, de nombreux plugins et sur un hébergement de mauvaise qualité peut très fortement impacter les performances de votre site. C’est pourquoi nous utilisons des serveurs dédiés, que nous gérons de A à Z pour vous offrir un hébergement haute performance et sur une bande passante dédiée. Aujourd’hui nous aborderons l’optimisation de WordPress sur un serveur dédié avec Varnish.

varnish-604x270-1

La mise en cache avec Varnish

La mise en cache est l’un des piliers de l’optimisation des performances web, un ensemble de techniques qui visent à rendre le chargement de votre site plus rapide. Aucun site ne peut se dire optimisé sans utiliser un système de mise en cache.

Il existe différent type de mise en cache :

  • La mise en cache de page : se produit au niveau serveur / plugin et conserve en local sous forme de fichiers les pages HTML (ex: plugin WP-Rocket).
  • La mise en cache navigateur : conserve également en mémoire les pages HTML mais au niveau du navigateur de l’utilisateur
  • La mise en cache objet : consiste à mettre en mémoire les requêtes effectuées sur la base de données pour les appeler à nouveau plus vite
  • La mise en cache CDN : le Content Delivery Network stock tous les fichiers statiques de votre site, sur des serveurs dans le monde entier et permet de les fournir plus rapidement, en ciblant localement les visiteurs pour optimiser les livraisons.
  • La mise en cache reverse proxy : se produit au niveau du serveur et garde en mémoire toutes les requêtes des visiteurs sur les différentes pages.

De manière générale, un “proxy” est un serveur placé entre internet et un utilisateur. Le serveur proxy filtre les requêtes envoyées par l’utilisateur à une page web spécifique, en suivant une règle précise. C’est le cas pour Varnish, qui peut être utilisé comme serveur reverse Proxy de cache.

Varnish agit comme un cache de reverse proxy HTTP, et parfois il est décrit comme un accélérateur front-end. Ce n’est pas une solution indépendante car elle a besoin d’un serveur web dédié sur lequel se baser comme NGINX dans notre cas. Vous pouvez utiliser Varnish pour mettre en cache à la fois le contenu dynamique et statique : c’est une solution efficace pour améliorer non seulement la vitesse de votre site web, mais également vos performances serveur.

Le serveur cache distribue toutes les ressources qui changent rarement, comme les fichiers CSS et JavaScript. Cela réduit la charge du serveur d’origine, qui peut alors se concentrer sur un chargement plus rapide des pages , puisqu’il n’a pas à rendre le contenu statique à chaque nouveau chargement.

Cas pratique

Nous admettrons ici que vous avez déjà un serveur dédié installé et configuré avec Nginx + PHP-FPM. Nginx étant en écoute sur le port 8080 et le port 443 pour le SSL. Varnish viendra se mettre en place en front, en tant que Proxy sur le port 80.

Installation de Varnish

Pour installer varnish, rien de plus simple : utilisez le paquet disponible dans les dépôts officiels de votre distribution linux favorite, ou récupérez la clé et le dépôt officiel Varnish :

curl -L https://packagecloud.io/varnishcache/varnish41/gpgkey | sudo apt-key add -
touch /etc/apt/sources.list.d/varnish.list
echo "deb https://packagecloud.io/varnishcache/varnish41/ubuntu/ trusty main" > /etc/apt/source.list.d/varnish.list 
echo "deb-src https://packagecloud.io/varnishcache/varnish41/ubuntu/ trusty main" >> /etc/apt/source.list.d/varnish.list

Ensuite, mettez à jour les dépôts de du serveur :

apt-get update

Puis installez Varnish :

apt-get install varnish

Configuration du process Varnish

Ouvrez le fichier /etc/default/varnish et modifiez la ligne suivante en adaptant la quantité de mémoire allouée à Varnish :

DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,15G"

Dans notre cas, Varnish écoutera donc sur le port 80, sera administrable sur le port 6082 et nous allouons 15Go de mémoire RAM au process.

Configuration VCL de Varnish pour WordPress

Enfin, il ne vous reste plus qu’a sauvegarder le fichier /etc/varnish/default.vcl fourni par défaut et en créer un nouveau avec le contenu suivant, disponible sur PasteBin.

Les principales configuration importantes de ce code sont les suivantes

On bypass Varnish pour les requêtes sur l’administration WordPress et le cron

# Either the admin pages or the login
if (req.url ~ "/wp-(login|admin|cron)") {
# Don't cache, pass to backend
return (pass);
}

Redirection HTTP vers HTTPS avec Varnish

if ( req.http.X-Forwarded-Proto !~ "(?i)https" ) {
set req.http.Location = "https://" + req.http.host + req.url;
return(synth(750, ""));
}

Bypass des appels au challenge Let’s Encrypt

# LetsEncrypt Certbot passthrough
if (req.url ~ "^/\.well-known/acme-challenge/") {
return (pass);
}

Récupération de l’IP réelle du visiteur derrière Cloudflare

unset req.http.X-Forwarded-For;
if (req.http.cf-connecting-ip) {
set req.http.X-Forwarded-For = req.http.cf-connecting-ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}

Retrait des paramètres dans les URLs Google Analytics

# First remove the Google Analytics added parameters, useless for our backend
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
set req.url = regsub(req.url, "\?&", "?");
set req.url = regsub(req.url, "\?$", "");
}

Suppression des Cookies

# Remove the "has_js" cookie
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.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");

# Remove DoubleClick offensive cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");

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

# Remove the AddThis cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");

# 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=[^;]+(; )?", "");

# Remove a ";" prefix in the cookie if present
set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");

# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}

Bypass des URLs d’authentification

# 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_]+|woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_[a-zA-Z0-9]+)"
) {
return (pass);
}

Bypass des URLs spécifiques à WooCommerce

if(
req.url ~ "^/addons" ||
req.url ~ "^/administrator" ||
req.url ~ "^/cart" ||
req.url ~ "^/checkout" ||
req.url ~ "^/component/banners" ||
req.url ~ "^/component/socialconnect" ||
req.url ~ "^/component/users" ||
req.url ~ "^/connect" ||
req.url ~ "^/contact" ||
req.url ~ "^/connexion" ||
req.url ~ "^/login" ||
req.url ~ "^/panier" ||
req.url ~ "^/logout" ||
req.url ~ "^/lost-password" ||
req.url ~ "^/my-account" ||
req.url ~ "^/register" ||
req.url ~ "^/signin" ||
req.url ~ "^/signup" ||
req.url ~ "^/reserver" ||
req.url ~ "^/wc-api" ||
req.url ~ "^/wp-admin" ||
req.url ~ "^/wp-login.php" ||
req.url ~ "^\?add-to-cart=" ||
req.url ~ "^\?wc-api="
) {
return (pass);
}

Bypass des requêtes AJAX

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

Gestion des fichiers statiques

# 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);
}

Bypass des requêtes POST

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

BONUS : personnaliser les pages d’erreurs sur Varnish (404, 500, 503…)

sub vcl_backend_error { 
set beresp.http.Content-Type = "text/html; 
charset=utf-8"; 
## Page d'erreur personnalisée 
if(beresp.status == 404) { 
synthetic(std.fileread("/var/www/errors/404.html")); 
} else if (beresp.status == 503) { 
synthetic(std.fileread("/var/www/errors/503.html")); 
} else if (beresp.status == 401) { 
synthetic(std.fileread("/var/www/errors/401.html")); 
} else if (beresp.status == 502) { 
synthetic(std.fileread("/var/www/errors/502.html")); 
} else if (beresp.status == 403) { 
synthetic(std.fileread("/var/www/errors/403.html")); 
} else { synthetic(std.fileread("/var/www/errors/500.html")); 
} 
return (deliver); 
}

Comment vider le cache Varnish

Vider le cache varnish en ligne de commande avec varnishadm

Pour visualiser un changement, ou vider totalement le cache varnish pour un domaine, voici la commande à utiliser :

varnishadm -T 127.0.0.1:6082 -S /etc/varnish/secret ban "req.http.host == www.bldwebagency.fr"

Ou, pour purger une URL spécifique : 

varnishadm -T 127.0.0.1:6082 -S /etc/varnish/secret ban "req.http.host == www.bldwebagency.fr && req.url == /contact"

Vider le cache varnish avec cURL

curl -X PURGE https://www.bldwebagency.fr/actualites/