Varnish, Apache et PHP : configurer un cache moderne

Installer APC et Varnish devant Apache était une très bonne idée il y a quelques années. À l’époque, APC servait à la fois de cache opcode PHP et de cache utilisateur. Varnish, lui, permettait déjà de placer un reverse proxy HTTP très rapide devant Apache pour servir les pages les plus demandées sans réveiller toute la pile PHP/MySQL.

Aujourd’hui, l’objectif reste valable : réduire la charge, accélérer les réponses et absorber plus de trafic. En revanche, la stack a changé. On ne doit plus installer l’ancien APC. On utilise OPcache pour le bytecode PHP, APCu seulement si l’application en a besoin, et Varnish comme cache HTTP devant Apache lorsque le contexte s’y prête.

Ce guide modernise donc l’approche : diagnostic, OPcache, APCu, Varnish, Apache en backend, vraie IP visiteur, configuration VCL prudente, purge du cache, WordPress, WooCommerce et dépannage.

APC, APCu, OPcache : ne mélangeons pas tout

Commençons par la mise au point importante : APC est obsolète pour les versions modernes de PHP.

L’ancien APC faisait deux choses :

  • cache opcode PHP ;
  • cache utilisateur en mémoire.

Depuis PHP 5.5, PHP inclut son propre cache opcode : OPcache. L’ancien rôle opcode d’APC n’a donc plus lieu d’être. APCu, de son côté, garde uniquement la partie cache utilisateur : une petite base clé/valeur en mémoire accessible depuis PHP.

La bonne lecture actuelle est donc simple :

OutilRôleÀ utiliser aujourd’hui ?
APCAncien cache opcode + cache utilisateurNon
OPcacheCache opcode PHPOui, presque toujours
APCuCache utilisateur local en mémoireOui, si l’application l’utilise
VarnishReverse proxy cache HTTPOui, dans les bons scénarios
RedisObject cache réseau/persistantSouvent préférable pour WordPress

En clair : OPcache accélère PHP, APCu peut accélérer certaines valeurs applicatives, Varnish évite de toucher PHP quand une page entière est déjà cachée. Ce sont trois niveaux différents. Les confondre, c’est comme mettre un turbo sur une cafetière et se demander pourquoi le café sort en HTTP 503.

Quand Varnish est une bonne idée

Varnish est un reverse proxy cache HTTP. Il se place devant votre serveur web d’origine, reçoit les requêtes, décide si une réponse peut être servie depuis le cache, et ne contacte Apache que lorsque c’est nécessaire.

Il est particulièrement utile pour :

  • sites éditoriaux très consultés ;
  • pages publiques majoritairement anonymes ;
  • pics de trafic prévisibles ;
  • sites WordPress avec peu de personnalisation par utilisateur ;
  • applications qui envoient de bons en-têtes de cache ;
  • architectures où Apache reste le backend applicatif ;
  • serveurs qui doivent continuer à répondre même si le backend ralentit.

Varnish brille quand il peut répondre à la place de l’application. Il devient beaucoup moins intéressant si presque toutes les pages dépendent d’une session, d’un cookie, d’un panier, d’un compte client, d’un prix dynamique ou d’une personnalisation utilisateur.

Kinsta: Premium Managed WordPress hosting

Quand Varnish est une mauvaise idée

Varnish n’est pas magique. Il peut même devenir dangereux si vous cachez des pages privées ou personnalisées.

Soyez prudent avec :

  • WooCommerce ;
  • Easy Digital Downloads ;
  • sites membres ;
  • LMS ;
  • forums ;
  • intranets ;
  • espaces clients ;
  • pages avec panier ou checkout ;
  • prix personnalisés ;
  • contenu différent selon l’utilisateur ;
  • géolocalisation ;
  • A/B testing côté serveur.

Sur ce type de site, Varnish peut rester utile pour les pages publiques, mais il faut des exclusions strictes. Le panier d’un client servi à un autre client, c’est le genre d’optimisation qui raccourcit une carrière.

Architecture recommandée avec Varnish et Apache

L’architecture classique ressemble à ceci :

Visiteur
   ↓
Varnish :80
   ↓
Apache :8080
   ↓
PHP-FPM / application
   ↓
MySQL / MariaDB / Redis

Varnish écoute sur le port 80. Apache écoute localement sur le port 8080. Varnish contacte Apache uniquement en backend.

Pour HTTPS, il faut retenir un point crucial : Varnish open source a longtemps été utilisé uniquement en HTTP, derrière une terminaison TLS séparée. Selon votre version et votre packaging, vous utiliserez généralement une terminaison TLS devant Varnish, par exemple Nginx, HAProxy, Hitch ou votre CDN.

Architecture courante avec HTTPS :

Visiteur HTTPS
   ↓
Nginx / HAProxy / CDN :443
   ↓
Varnish :80
   ↓
Apache :8080
   ↓
PHP-FPM / application

Si votre site passe déjà par Cloudflare, le rôle de Varnish doit être réfléchi. Vous pouvez avoir Cloudflare en cache périphérique et Varnish en cache local, mais les règles doivent rester cohérentes. Sinon, vous empilez les caches comme des assiettes sales.

Kinsta: Premium Managed WordPress hosting

Avant d’installer : mesurer le serveur

Avant d’ajouter Varnish, vérifiez que votre problème est bien un problème de cache HTTP.

Temps de réponse simple :

curl -o /dev/null -s -w "ttfb=%{time_starttransfer}s total=%{time_total}s\n" https://www.example.com/Langage du code : JavaScript (javascript)

En-têtes de cache :

curl -I https://www.example.com/Langage du code : JavaScript (javascript)

Charge serveur :

uptime
free -m
top

Connexions HTTP :

ss -tan | awk 'NR > 1 {print $1}' | sort | uniq -c | sort -nrLangage du code : JavaScript (javascript)

Si les pages sont lentes à cause de requêtes SQL, de PHP-FPM saturé, d’un plugin WordPress lourd, d’images énormes ou d’APIs externes lentes, Varnish peut masquer une partie du problème. Il ne le corrige pas toujours. Le cache accélère ce qu’il peut servir. Il ne rend pas une application cassée soudainement brillante.

Installer et configurer OPcache

OPcache doit être actif sur presque tous les serveurs PHP modernes. Il évite à PHP de recompiler les scripts à chaque requête.

Sur Ubuntu ou Debian avec PHP 8.3 :

sudo apt update
sudo apt install php8.3-opcacheLangage du code : CSS (css)

Vérifiez que l’extension est chargée :

php -m | grep -i opcache

Créez ou modifiez la configuration OPcache, selon votre distribution :

sudo nano /etc/php/8.3/fpm/conf.d/10-opcache.ini

Base raisonnable pour un serveur WordPress ou PHP classique :

opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=100000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.save_comments=1
opcache.jit=0

Rechargez PHP-FPM :

sudo systemctl reload php8.3-fpmLangage du code : CSS (css)

Sur un serveur de production avec déploiement contrôlé, vous pouvez envisager opcache.validate_timestamps=0, mais uniquement si votre déploiement vide ou réinitialise OPcache après chaque mise en production. Sur WordPress classique, gardez plutôt la validation active. C’est moins agressif et nettement moins piégeux.

Kinsta: Premium Managed WordPress hosting

Installer APCu seulement si nécessaire

APCu n’est pas obligatoire. Il sert uniquement si votre application l’utilise explicitement. Pour WordPress, Redis ou Memcached sont souvent plus adaptés comme object cache persistant, surtout sur plusieurs workers PHP ou plusieurs serveurs.

Installez APCu si vous avez un besoin précis :

sudo apt update
sudo apt install php8.3-apcuLangage du code : CSS (css)

Vérifiez le chargement :

php -m | grep -i apcu

Configuration simple :

sudo nano /etc/php/8.3/fpm/conf.d/20-apcu.ini
apc.enabled=1
apc.shm_size=128M
apc.ttl=7200
apc.gc_ttl=3600
apc.enable_cli=0

Rechargez PHP-FPM :

sudo systemctl reload php8.3-fpmLangage du code : CSS (css)

Encore une fois : APCu n’est pas le remplaçant universel d’APC. OPcache gère les opcodes. APCu gère un cache utilisateur local. Si votre application ne l’appelle jamais, il ne sert presque à rien.

Installer Varnish sur Ubuntu ou Debian

Varnish peut être installé depuis les dépôts de la distribution, mais la version peut être plus ancienne. Pour une production sérieuse, utilisez la documentation officielle de Varnish afin d’installer une version maintenue adaptée à votre distribution.

Installation simple depuis les dépôts Ubuntu/Debian :

sudo apt update
sudo apt install varnish

Vérifiez la version :

varnishd -V

Vérifiez le service :

systemctl status varnish --no-pager

Par défaut, Varnish écoute souvent sur le port 6081. Nous allons ensuite le placer sur le port 80, puis déplacer Apache sur le port 8080.

Déplacer Apache sur le port 8080

Apache ne doit plus écouter publiquement sur le port 80 si Varnish prend sa place. Modifiez le fichier des ports Apache :

sudo nano /etc/apache2/ports.conf

Remplacez :

Listen 80

par :

Listen 127.0.0.1:8080Langage du code : CSS (css)

Ensuite, modifiez vos VirtualHosts HTTP :

sudo grep -R "<VirtualHost .*:80" -n /etc/apache2/sites-available/Langage du code : JavaScript (javascript)

Remplacez par exemple :

<VirtualHost *:80>Langage du code : HTML, XML (xml)

par :

<VirtualHost 127.0.0.1:8080>Langage du code : CSS (css)

Vérifiez Apache :

sudo apachectl configtest

Rechargez Apache :

sudo systemctl reload apache2

Testez le backend local :

curl -I http://127.0.0.1:8080/Langage du code : JavaScript (javascript)

Si vous hébergez plusieurs sites, testez avec l’en-tête Host :

curl -I -H "Host: www.example.com" http://127.0.0.1:8080/Langage du code : JavaScript (javascript)

Configurer Varnish pour écouter sur le port 80

Selon votre distribution, les paramètres systemd de Varnish peuvent se trouver dans un fichier d’environnement ou dans l’unité systemd. La méthode propre consiste à créer un override systemd.

sudo systemctl edit varnish

Ajoutez :

[Service]
ExecStart=
ExecStart=/usr/sbin/varnishd \
  -j unix,user=vcache \
  -F \
  -a :80 \
  -T localhost:6082 \
  -f /etc/varnish/default.vcl \
  -s malloc,512mLangage du code : JavaScript (javascript)

Adaptez l’utilisateur vcache si votre paquet utilise un autre utilisateur. Vérifiez l’unité actuelle avec :

systemctl cat varnish

Rechargez systemd et redémarrez Varnish :

sudo systemctl daemon-reload
sudo systemctl restart varnish

Vérifiez l’écoute réseau :

ss -tlnp | grep -E ':80|:8080|:6082'Langage du code : JavaScript (javascript)

Vous devriez voir Varnish sur le port 80 et Apache sur 127.0.0.1:8080.

Créer une configuration VCL de base

Varnish se configure avec VCL, pour Varnish Configuration Language. Le fichier principal est souvent :

/etc/varnish/default.vclLangage du code : JavaScript (javascript)

Créez une base claire :

sudo nano /etc/varnish/default.vclLangage du code : JavaScript (javascript)
vcl 4.1;

backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .connect_timeout = 5s;
    .first_byte_timeout = 60s;
    .between_bytes_timeout = 30s;
}

sub vcl_recv {
    # Preserve the original host.
    set req.http.X-Forwarded-Host = req.http.host;

    # Append the client IP to X-Forwarded-For.
    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;
    }

    # Only cache safe methods.
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    # Do not cache WordPress admin, login, cron or REST write endpoints.
    if (req.url ~ "^/wp-admin" ||
        req.url ~ "^/wp-login\.php" ||
        req.url ~ "^/wp-cron\.php" ||
        req.url ~ "^/xmlrpc\.php") {
        return (pass);
    }

    # Do not cache common WooCommerce dynamic pages.
    if (req.url ~ "^/(cart|checkout|my-account)(/|$)" ||
        req.url ~ "add-to-cart=" ||
        req.url ~ "wc-ajax=") {
        return (pass);
    }

    # Do not cache authenticated or session-based requests.
    if (req.http.Cookie ~ "wordpress_logged_in_" ||
        req.http.Cookie ~ "wp-postpass_" ||
        req.http.Cookie ~ "comment_author_" ||
        req.http.Cookie ~ "woocommerce_items_in_cart" ||
        req.http.Cookie ~ "wp_woocommerce_session_" ||
        req.http.Cookie ~ "woocommerce_cart_hash") {
        return (pass);
    }

    # Remove tracking parameters from the cache key.
    if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_term|utm_content|gclid|fbclid)=") {
        set req.url = regsuball(req.url, "(utm_source|utm_medium|utm_campaign|utm_term|utm_content|gclid|fbclid)=[^&]+&?", "");
        set req.url = regsub(req.url, "[?&]+$", "");
    }

    # Remove cookies for anonymous cacheable requests.
    unset req.http.Cookie;

    return (hash);
}

sub vcl_backend_response {
    # Cache successful public responses for 10 minutes by default.
    if (beresp.status == 200 && bereq.method == "GET") {
        set beresp.ttl = 10m;
        set beresp.grace = 1h;
    }

    # Do not cache responses that explicitly set cookies.
    if (beresp.http.Set-Cookie) {
        set beresp.uncacheable = true;
        return (deliver);
    }

    # Do not cache private/no-store responses.
    if (beresp.http.Cache-Control ~ "private" ||
        beresp.http.Cache-Control ~ "no-store") {
        set beresp.uncacheable = true;
        return (deliver);
    }

    return (deliver);
}

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

    set resp.http.X-Cache-Hits = obj.hits;

    # Optional: hide internal Varnish information.
    unset resp.http.Via;
    unset resp.http.X-Varnish;
}Langage du code : PHP (php)

Testez la configuration VCL :

sudo varnishd -C -f /etc/varnish/default.vcl > /dev/nullLangage du code : JavaScript (javascript)

Redémarrez Varnish :

sudo systemctl restart varnish

Cette configuration est volontairement prudente. Elle cache les pages anonymes, mais évite les zones sensibles de WordPress et WooCommerce. Le cache agressif, c’est pour les benchmarks. La production préfère les nuits calmes.

Restaurer la vraie IP visiteur dans Apache

Quand Apache est derrière Varnish, il voit par défaut l’IP de Varnish, souvent 127.0.0.1. Pour récupérer la vraie IP visiteur, utilisez mod_remoteip.

sudo a2enmod remoteip

Créez une configuration :

sudo nano /etc/apache2/conf-available/remoteip.conf
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1
RemoteIPTrustedProxy ::1Langage du code : CSS (css)

Activez-la :

sudo a2enconf remoteip
sudo apachectl configtest
sudo systemctl reload apache2

Adaptez ensuite votre format de logs Apache si nécessaire, afin d’utiliser l’IP restaurée. Sur une architecture avec Cloudflare devant Varnish, il faudra aussi faire confiance uniquement aux IP Cloudflare et traiter CF-Connecting-IP ou X-Forwarded-For avec prudence.

Tester si Varnish fonctionne

Faites une première requête :

curl -I http://www.example.com/Langage du code : JavaScript (javascript)

Vous devriez voir :

X-Cache: MISSLangage du code : HTTP (http)

Relancez la même requête :

curl -I http://www.example.com/Langage du code : JavaScript (javascript)

Cette fois, vous devriez obtenir :

X-Cache: HITLangage du code : HTTP (http)

Mesurez le temps de réponse :

curl -o /dev/null -s -w "ttfb=%{time_starttransfer}s total=%{time_total}s\n" http://www.example.com/Langage du code : JavaScript (javascript)

Sur un vrai hit Varnish, le TTFB doit chuter fortement. Si vous restez toujours en MISS, regardez les cookies, les en-têtes Cache-Control, les règles VCL et les réponses Set-Cookie.

Observer Varnish en temps réel

Varnish fournit plusieurs outils de diagnostic très utiles.

Statistiques globales :

varnishstat

Logs en temps réel :

varnishlog

Requêtes de type MISS :

varnishlog -g request -q 'VCL_call eq MISS'Langage du code : JavaScript (javascript)

Requêtes passées au backend :

varnishlog -g request -q 'VCL_return eq pass'Langage du code : JavaScript (javascript)

Journal synthétique façon access log :

varnishncsa

Ces outils évitent de deviner. Et dans le monde du cache, deviner finit souvent par servir la page d’accueil à quelqu’un qui voulait son panier.

Gérer la purge du cache Varnish

Un cache HTTP doit pouvoir être purgé. Sinon, vous allez publier une correction et regarder Varnish servir l’ancienne page avec un aplomb presque philosophique.

Ajoutez une ACL de purge dans /etc/varnish/default.vcl :

acl purge {
    "localhost";
    "127.0.0.1";
    "::1";
}

sub vcl_recv {
    if (req.method == "PURGE") {
        if (!client.ip ~ purge) {
            return (synth(405, "Not allowed"));
        }

        return (purge);
    }

    # Le reste de votre vcl_recv continue ici.
}Langage du code : PHP (php)

Testez la configuration :

sudo varnishd -C -f /etc/varnish/default.vcl > /dev/null
sudo systemctl reload varnishLangage du code : JavaScript (javascript)

Pour purger une URL depuis le serveur :

curl -X PURGE http://www.example.com/Langage du code : JavaScript (javascript)

Ne laissez jamais la purge ouverte à Internet. Une purge publique transforme votre cache en passoire avec une interface HTTP. Très pratique pour vos ennemis imaginaires, et parfois les vrais.

WordPress et Varnish : règles essentielles

WordPress peut très bien fonctionner derrière Varnish, mais il faut respecter quelques règles.

  • Ne jamais cacher /wp-admin/.
  • Ne jamais cacher /wp-login.php.
  • Ne jamais cacher les pages avec cookie de connexion.
  • Ne pas cacher les requêtes POST.
  • Ne pas cacher les previews.
  • Ne pas cacher les pages protégées par mot de passe.
  • Purger la page d’accueil, les archives et les URLs modifiées après publication.
  • Respecter les en-têtes Cache-Control quand ils sont volontairement envoyés.

Si votre site est un blog, un magazine ou un site vitrine, Varnish peut être très efficace. Si votre site est très personnalisé par utilisateur, un bon cache page WordPress ou un cache serveur Nginx peut être plus simple à maintenir.

WooCommerce et Varnish : prudence maximale

WooCommerce ajoute des contraintes fortes : panier, checkout, compte client, session, cookies, fragments, prix, stock, coupons, géolocalisation, moyens de paiement et webhooks.

À exclure absolument du cache :

  • /cart/
  • /checkout/
  • /my-account/
  • ?add-to-cart=
  • ?wc-ajax=
  • requêtes POST
  • utilisateurs connectés
  • cookies WooCommerce de session ou panier

Sur une boutique, testez chaque scénario avant d’activer le cache largement :

  • ajout au panier ;
  • mise à jour du panier ;
  • checkout ;
  • connexion client ;
  • création de compte ;
  • paiement ;
  • webhooks ;
  • prix dynamiques ;
  • produits variables ;
  • stock ;
  • coupons ;
  • mini-panier.

En WooCommerce, le cache le plus rapide est inutile s’il affiche une mauvaise information. La performance doit rester correcte, mais le panier doit rester sacré.

HTTPS : où terminer TLS ?

Si votre site est en HTTPS, vous devez décider où se termine TLS.

Options courantes :

  • Cloudflare termine TLS, puis contacte votre serveur ;
  • Nginx termine TLS devant Varnish ;
  • HAProxy termine TLS devant Varnish ;
  • Hitch termine TLS devant Varnish ;
  • Apache garde TLS et Varnish ne sert que certains flux HTTP internes.

Une architecture simple avec Nginx devant Varnish :

server {
    listen 443 ssl http2;
    server_name www.example.com;

    ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:80;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}Langage du code : PHP (php)

Dans cette configuration, Nginx écoute en HTTPS, transmet à Varnish en HTTP local, puis Varnish transmet à Apache sur 127.0.0.1:8080. C’est une architecture classique, mais elle ajoute une couche. Documentez-la, sinon votre futur vous viendra se plaindre.

Headers utiles pour savoir ce qui se passe

Ajoutez des en-têtes de debug uniquement si vous assumez de les exposer. Pour une première phase de test, ils sont très utiles.

Dans vcl_deliver :

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

    set resp.http.X-Cache-Hits = obj.hits;
    set resp.http.X-Served-By = "Varnish";

    unset resp.http.X-Varnish;
    unset resp.http.Via;
}Langage du code : PHP (php)

Testez ensuite :

curl -I http://www.example.com/Langage du code : JavaScript (javascript)

Quand tout fonctionne, vous pouvez garder X-Cache si vous aimez diagnostiquer rapidement, ou le retirer si vous préférez exposer moins d’informations.

Gérer les cookies proprement

Les cookies sont souvent la raison numéro un d’un cache Varnish qui ne hit jamais. Beaucoup d’applications envoient des cookies même sur des pages publiques. Varnish devient alors prudent et passe la requête au backend.

La logique recommandée :

  • passer au backend si cookie de connexion ;
  • passer au backend si cookie WooCommerce panier/session ;
  • supprimer les cookies de tracking pour les pages publiques ;
  • ne pas cacher les réponses qui envoient Set-Cookie ;
  • tester avec varnishlog pourquoi une requête est passée.

Pour tester sans cookies :

curl -I http://www.example.com/Langage du code : JavaScript (javascript)

Pour tester avec un cookie simulé :

curl -I -H "Cookie: wordpress_logged_in_test=1" http://www.example.com/Langage du code : JavaScript (javascript)

Ce test doit passer au backend, pas servir un HIT public.

Grace mode : servir du contenu stale quand le backend ralentit

Le grace mode permet à Varnish de servir un objet expiré pendant qu’il récupère une version fraîche auprès du backend. C’est très utile si Apache ou PHP-FPM ralentit ponctuellement.

Dans la configuration plus haut, nous avons déjà défini :

set beresp.grace = 1h;Langage du code : JavaScript (javascript)

Vous pouvez ensuite affiner le comportement dans vcl_hit :

sub vcl_hit {
    if (obj.ttl >= 0s) {
        return (deliver);
    }

    if (obj.ttl + obj.grace > 0s) {
        return (deliver);
    }

    return (restart);
}Langage du code : JavaScript (javascript)

Le grace mode ne doit pas remplacer un backend stable. Mais il peut éviter qu’un pic de trafic transforme une expiration de cache en cohue générale devant PHP-FPM.

Dépannage : Varnish renvoie toujours MISS

Si Varnish reste toujours en MISS, vérifiez :

  • la réponse envoie-t-elle Set-Cookie ?
  • la réponse contient-elle Cache-Control: private ?
  • la réponse contient-elle Cache-Control: no-store ?
  • la requête contient-elle un cookie WordPress ou WooCommerce ?
  • l’URL contient-elle une query string non ignorée ?
  • la méthode est-elle bien GET ou HEAD ?
  • la VCL force-t-elle return (pass) ?
  • le backend renvoie-t-il un code différent de 200 ?

Utilisez :

varnishlog -g request -q 'ReqUrl eq "/"'Langage du code : JavaScript (javascript)

Ou inspectez une requête passée :

varnishlog -g request -q 'VCL_return eq pass'Langage du code : JavaScript (javascript)

Dépannage : erreur 503 Backend fetch failed

Une erreur 503 Backend fetch failed signifie que Varnish n’a pas pu récupérer la réponse auprès d’Apache.

Vérifiez Apache :

systemctl status apache2 --no-pager
curl -I -H "Host: www.example.com" http://127.0.0.1:8080/Langage du code : JavaScript (javascript)

Vérifiez les logs :

sudo tail -f /var/log/apache2/error.log
sudo journalctl -u varnish -fLangage du code : JavaScript (javascript)

Causes fréquentes :

  • Apache n’écoute pas sur le port 8080 ;
  • mauvais Host ;
  • VirtualHost incorrect ;
  • timeout backend trop court ;
  • PHP-FPM saturé ;
  • erreur applicative ;
  • pare-feu local ;
  • VCL backend mal configuré.

Dépannage : les utilisateurs connectés voient une page publique

Si un utilisateur connecté voit une page qui ne correspond pas à son état, désactivez immédiatement le cache sur les zones concernées et vérifiez les cookies.

Testez avec :

curl -I -H "Cookie: wordpress_logged_in_test=1" http://www.example.com/Langage du code : JavaScript (javascript)

La réponse ne doit pas être un cache HIT public.

Si vous avez WooCommerce, testez aussi :

curl -I -H "Cookie: woocommerce_items_in_cart=1" http://www.example.com/cart/Langage du code : JavaScript (javascript)

Le panier, le checkout et le compte doivent toujours contourner le cache.

Faut-il préférer Nginx FastCGI cache à Varnish ?

Sur beaucoup de serveurs WordPress modernes, Nginx FastCGI cache est plus simple que Varnish. Il y a moins de couches, moins de ports, moins de headers à faire circuler, et l’intégration avec PHP-FPM est directe.

Varnish garde de solides avantages :

  • VCL très puissant ;
  • diagnostic avancé ;
  • grace mode ;
  • cache HTTP indépendant de l’origine ;
  • scénarios multi-backends ;
  • purge fine ;
  • architecture reverse proxy robuste.

Mais pour un petit site WordPress, un bon cache page applicatif, OPcache, Redis et un CDN peuvent suffire. Pour un site éditorial très chargé ou une architecture serveur avancée, Varnish mérite le test.

Checklist de mise en production

  • OPcache actif et dimensionné.
  • APCu installé seulement si nécessaire.
  • Apache fonctionnel sur 127.0.0.1:8080.
  • Varnish fonctionnel sur le port 80.
  • HTTPS terminé proprement devant Varnish si nécessaire.
  • Vraie IP restaurée avec mod_remoteip.
  • Admin WordPress exclu du cache.
  • Utilisateurs connectés exclus du cache.
  • WooCommerce cart, checkout et account exclus du cache.
  • Requêtes POST exclues.
  • Purge Varnish sécurisée.
  • Headers X-Cache testés.
  • varnishlog et varnishstat disponibles.
  • Plan de rollback prêt.

Plan de rollback rapide

Avant de basculer Varnish en production, prévoyez le retour arrière.

Pour remettre Apache sur le port 80 :

sudo systemctl stop varnish
sudo nano /etc/apache2/ports.conf

Remettez :

Listen 80

Remettez vos VirtualHosts sur :

<VirtualHost *:80>Langage du code : HTML, XML (xml)

Puis :

sudo apachectl configtest
sudo systemctl reload apache2

Un rollback simple change tout : on ose tester, parce qu’on sait revenir en arrière. C’est la différence entre l’administration système et la roulette russe en SSH.

FAQ

Faut-il encore installer APC pour accélérer PHP ?

Non. L’ancien APC est obsolète. Utilisez OPcache pour le cache opcode PHP. Installez APCu seulement si votre application utilise explicitement un cache utilisateur local.

Varnish remplace-t-il OPcache ?

Non. Varnish cache des réponses HTTP complètes devant Apache. OPcache cache le bytecode PHP à l’intérieur de PHP. Les deux outils agissent à des niveaux différents.

Varnish fonctionne-t-il avec HTTPS ?

Oui, mais l’architecture dépend de votre version et de votre stack. Dans beaucoup de configurations, TLS est terminé par Nginx, HAProxy, Hitch ou un CDN devant Varnish, puis Varnish parle en HTTP local avec Apache.

Peut-on utiliser Varnish avec WooCommerce ?

Oui, mais avec prudence. Il faut exclure panier, checkout, compte client, sessions, utilisateurs connectés, requêtes POST et cookies WooCommerce. Testez tous les scénarios d’achat avant mise en production.

Pourquoi Varnish renvoie-t-il toujours MISS ?

La cause vient souvent des cookies, des en-têtes Set-Cookie, de Cache-Control: private, d’une règle VCL en pass, d’une query string ou d’une page dynamique non cacheable.

Varnish est-il meilleur qu’un plugin de cache WordPress ?

Pas toujours. Varnish est plus puissant côté infrastructure, mais plus complexe. Pour un petit site, un plugin de cache bien configuré, OPcache, Redis et un CDN peuvent suffire. Pour un site très chargé, Varnish peut faire une grosse différence.

Conclusion

L’ancien couple APC + Varnish + Apache doit être modernisé. Aujourd’hui, on utilise OPcache pour accélérer PHP, APCu seulement pour le cache utilisateur local, et Varnish comme reverse proxy HTTP lorsque le site peut réellement bénéficier d’un cache pleine page.

Pour WordPress, Varnish peut être excellent sur un site éditorial anonyme. Pour WooCommerce ou les sites membres, il faut des exclusions strictes et beaucoup de tests. Le cache doit accélérer le site, pas inventer une expérience client façon loterie.

La bonne stratégie reste simple : mesurer, activer OPcache, configurer Varnish prudemment, exclure le dynamique, tester les headers, surveiller les logs et garder un rollback prêt. C’est moins spectaculaire qu’un vieux tutoriel “copiez-collez ces lignes”, mais nettement plus professionnel.

Besoin d’aide pour accélérer un serveur WordPress ou WooCommerce ?

Si votre serveur Apache, Nginx, PHP-FPM ou WooCommerce ralentit sous charge, je peux vous aider à identifier le vrai goulot d’étranglement avant d’empiler des couches de cache au hasard.

J’interviens comme développeur WordPress et WooCommerce pour auditer les performances, optimiser PHP, OPcache, Redis, Varnish, Nginx, Apache, MySQL, les plugins lourds et les règles de cache sans casser les pages dynamiques.

  • Audit des performances WordPress, WooCommerce, PHP-FPM, Apache, Nginx et MySQL.
  • Configuration OPcache, Redis, cache page, reverse proxy, Varnish ou CDN.
  • Exclusions de cache pour panier, checkout, compte client, webhooks et utilisateurs connectés.
  • Analyse des headers, cookies, HIT/MISS, TTFB, logs serveur et requêtes lentes.
  • Intervention documentée, mesurée et réversible, sans optimisation kamikaze en production.

Vous voulez accélérer votre site sans transformer le cache en machine à bugs intermittents ? Contactez-moi. Je vous dirai ce qui doit être caché, ce qui ne doit jamais l’être, et ce qui ralentit réellement votre serveur.

À lire aussi sur SkyMinds

Sources

Demandez à l'IA son opinion
Gravatar for Matt Biscay

Je suis Matt Biscay, développeur WordPress & WooCommerce certifié chez Codeable, administrateur système et enseignant.

J’aide les entreprises à créer, optimiser et fiabiliser leurs sites WordPress avec une approche technique propre : performance, sécurité, maintenance, développement sur mesure et résolution de problèmes complexes.

Sur Skyminds, je partage des tutoriels WordPress, WooCommerce, Linux et administration système, avec des solutions testées sur des cas réels et pensées pour durer.

Découvrez mes services WordPress et WooCommerce.

20 réflexions au sujet de “Varnish, Apache et PHP : configurer un cache moderne”

  1. Bonjour,

    Merci pour tes tutos ils me sont très utiles pour la mise en place d’un serveur dédie

    J’ai mis en place mod-security pour sécuriser plusieurs sites en drupal, mais du aux nombres de requêtes a analysées, je l’ai supprime, je perdais trop de performances.

    A propos de varnish, j’ai deux petites questions

    1/ Lorsque varnish fonctionne, les logs d’apache ont comme adresse ip 127.0.0.1, y a t-il moyen de retrouver l’adresse réel du client ?

    2/ Seconde question, comment peut on voir ce que varnish a en cache ? pour apc il existe une page apc.php qui se trouve dans /usr/share/doc/php-apc/ mais pour varnish ?

    Il y a bien varnishtop mais c’est pas super compréhensible

    Merci

    Répondre
    • Bonjour salcin,

      J’ai aussi désactivé pas mal de modules pour mod-security qui ralentissait le site. Je referai une liste plus propre.

      Pour l’IP en 127.0.0.1 dans les logs, il faut installer le mod_rpaf pour Apache. J’ai gardé ça pour le prochain tuto qui sera mis en ligne dans quelques jours :

      aptitude install libapache2-mod-rpaf

      En ce qui concerne le cache de Varnish, on ne peut pas voir vraiment les pages en cache mais si tu tapes :

      varnishstat

      tu peux avoir pas mal d’informations en temps réel : request rate, mémoire utilisée, thread usage, uptime…

      Répondre
  2. Bonjour,

    Merci pour ces super tuto.

    Je rencontre un soucis pour mettre en place varnish avec la boutique prestashop.

    Le cache est affiché constament sur la boutique du coup on ne voit pas les modification faite.

    le problème est présent dans le back office /front

    J’ai cherché un peu comment faire tout ca mais ne maitrisant pas du tout le language vcl, ca vas être dur. Apparament il y a un histoire de purge a faire mais je ne trouve pas.

    cheers

    Répondre
    • Bonjour Majeri,

      Si tu veux ajouter la fonction PURGE, ajoute ceci dans ton fichier .vcl :

      # Purge ACL
      acl purge {
      # Only localhost can purge my cache
      "127.0.0.1";
      "localhost";
      }

      et dans vcl_recv, ajoute :

      # Allow purging from ACL
      if (req.request == "PURGE") {
      # If not allowed then a error 405 is returned
      if (!client.ip ~ purge) {
      error 405 "This IP is not allowed to send PURGE requests.";
      }
      # If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
      return (lookup);
      }

      Si tu veux exclure une zone de ton site du cache (backoffice ou flux RSS par exemple), tu peux utiliser ce type de code dans vcl_recv :

          # Example : do not cache the RSS feed
          if (req.url ~ "/feed") {
              return (pass);
          }
      Répondre
      • Merci Matt.

        Entre temps je me suis renseigné et j’ai trouvé les même commande que ce que tu m’as donnée.

        Par contre apres faut que je trouve une solution simple pour mettre a jour mes page web en faisant un purge.

        Comment tu fais toi pour par exemple mettre a jour le cache des page qui ont un subie une modification de ta part ou tout simplement des pages ou de nouveau commentaire on été posté.

        Tu utilise le plugin wordpress pour varnish je suppose ?

        cheers

  3. Merci,

    Apres quelques tatonement, beacoup de lecture et une nuit blanche, j’ai reussi a faire tourner comme je le souhaite varsnih avec mon prestashop.

    Aussi j’ai rajouter qq ligne pour la sécurité du serveur:

    Au choix: Cela trompera l’attaquant en lui indiquant un mauvais serveur web a rajouter dans le vcl_fetch:

    unset beresp.http.Server;
    set beresp.http.Server = « Lighthttpd Server »;

    Ou encore plus radical: (même si apache sera la cible de choix)

    sub vcl_deliver {
    # Secure the header
    remove resp.http.Via;
    remove resp.http.X-Varnish;
    remove resp.http.Server;
    remove resp.http.X-Powered-By;
    }

    ++

    Répondre
  4. Finalement comment as tu réussi a configurer varnish avec Prestashop?

    Pour moi ca me parait impossible car même en « bypassant » varnish via un return(pass); juste pour les sites prestashop j’ai toujours une erreur 503 Guru Meditation lorsque je filtre mes resultat dans la partie administration.

    Répondre
    • Finalement j’ai le même problème que toi rc183, quand je filtre une page d’administration dans le catalogue, j’ai la meme erreur :une erreur 503

      POur le moment j’ai toujours pas trouvé une solution.

      De plus j’ai toujours un problème pour que mes pages se purge quand il y a une mise a jour de prix par exemple.

      Certaine page sont mise a jour, d’autre pas.

      Répondre
  5. Salut Matt
    j’ai suivi le tuto (sans tout comprendre je reconnais :( )
    aucun soucis à l’install apc. Par contre à la derniere étape de restart varnish j’ai une erreur

    
    Stopping HTTP accelerator: varnishd failed!
    Starting HTTP accelerator: varnishd failed!
    storage_file: filename: /var/lib/varnish/ksxxxxx.kimsufi.com/varnish_storage.bin size 1024 MB.
    Message from VCC-compiler:
    Unused backend default, defined:
    (input Line 89 Pos 9)
    backend default {
    --------#######--
    Running VCC-compiler failed, exit 1
    VCL compilation failed
    

    et mon serveur est complètement down …
    Une idée de solution ? je ne comprends pas du tout le message d’erreur.

    Répondre
  6. Bonjour,

    j’ai suivi votre excellent tutoriel pour l’installation de Varnish. Mais je rencontre une erreur 503 sur toutes les pages, qu’elles soient en html ou en php. Je n’ai pourtant rien de spécial dans mes codes de page. Celles-ci sont très longues à charger et au bout d’un certain temps, apparait une erreur 503.

    Savez-vous comment il est possible de diagnostiquer le problème ?

    Merci,

    Répondre
  7. Je m’auto réponds. En fait, pour chaque domaine, dans la config de Varnish, il faut utiliser un backend différent ? Car j’ai configuré un backend « nomdusite » en modifiant la requête http.host et les pages fonctionnent comme il faut maintenant.

    Répondre
  8. Bonjour,
    « PHP Warning: Module ‘apc’ already loaded in Unknown on line 0
    PHP Warning: PHP Startup: apc.shm_size now uses M/G suffixes, please update your ini files in Unknown on line 0 »

    Pouvez-vous mettre à jour votre tuto – excellent au passage – pour les prochains visiteurs ?

    Infos : Debian 6, dédié, apache2, mysql, php5.

    Répondre
      • Right, j’avais même pas fait attention au second article.

        Merci de votre réactivité ( et du tuto :) ), PunKeel.

        PS: je n’ai pas « vu » de config pour fonctionner avec CloudFlare (ouaip, une idée de mise à jour du tuto :D)

        Comme ils le signalent sur leur site : sub vcl_recv {
        # Remove has_js and CloudFlare/Google Analytics __* cookies.
        set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
        # Remove a ";" prefix, if present.
        set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");

        et
        remove 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;
        }

        Cordialement, bis.

  9. Bonjour,

    merci pour ce tuto.

    une petite question me tarrode concernant la configuration d’APC.

    Pourquoi mettre apc.ttl=7200 au lieu de apc.ttl=0 qui ne va définir de temps.

    Répondre
    • Bonjour Djib’s,

      apc.ttl et apc.user_ttl définissent le temps (en secondes) pendant lequel un fichier reste dans le cache.

      Avec 7200 secondes, les fichiers sont mis en cache pendant 2 heures, ce qui est adapté à ma configuration. On pourrait mettre une expiration beaucoup plus longue si la taille du segment (apc.shm_size) était plus importante.

      Répondre

Laisser un commentaire