Indice dei contenuti dell'articolo:
Chi mette Varnish davanti a un sito Joomla si aspetta di vedere crollare i tempi di risposta. Spesso succede il contrario: il server lavora come prima, il database macina le stesse query e nei log di Varnish compaiono quasi solo MISS e PASS. La conclusione frettolosa è che “Varnish con Joomla non funziona”. In realtà Varnish funziona benissimo: è Joomla, in configurazione standard, che gli impedisce di fare il suo lavoro.
In questo articolo spiego perché succede, come si risolve con una configurazione VCL fatta su misura e quali sono le due trappole che rompono il sito se la cache viene attivata senza criterio: gli utenti loggati e i token di sicurezza dei form.
Il problema: un cookie di sessione anche per chi non ha fatto login
Varnish, per prudenza, non mette in cache le richieste che arrivano con un cookie e le risposte che ne impostano uno. È una scelta sensata: un cookie può identificare un utente e una pagina personale non deve mai essere servita a qualcun altro.
Joomla, in configurazione standard, avvia una sessione per ogni visitatore, anche per chi non ha mai fatto login, e invia il relativo cookie di sessione già alla prima pagina. Da quel momento ogni richiesta di quel visitatore porta con sé il cookie. Il risultato è che Varnish tratta ogni visitatore anonimo come un utente potenzialmente personale e manda tutto a PHP. La cache c’è, ma non viene quasi mai usata.
C’è un secondo dettaglio che completa il quadro: Joomla risponde con intestazioni che vietano la cache (Cache-Control: no-cache e una data di scadenza nel passato). Anche togliendo il cookie, Varnish riceverebbe una risposta che dichiara di non poter essere conservata.

Quanto vale davvero la cache
Per dare un ordine di grandezza ho misurato dall’esterno il nostro sito, che è un WordPress dietro Varnish, sulla stessa pagina e dalla stessa connessione. Senza cache la pagina arriva in 0,63-0,69 secondi; servita da Varnish arriva in 0,10-0,12 secondi, di cui 0,07 sono solo il tempo di connessione e di negoziazione TLS dalla mia postazione. Al netto della rete, significa 30-50 millisecondi contro oltre mezzo secondo di elaborazione.
Su Joomla il rapporto è lo stesso, spesso anche più marcato su siti con molti moduli ed estensioni. Ma il guadagno dipende interamente da una cosa: quante richieste diventano HIT. Con il cookie di sessione attivo per tutti, quella percentuale è vicina a zero.

La soluzione: tre regole da rispettare
La strategia corretta si riassume in tre regole:
- i visitatori anonimi ricevono pagine dalla cache, e per loro Varnish ignora il cookie di sessione;
- gli utenti autenticati non passano mai dalla cache, perché vedono pagine personali;
- le pagine con form, l’area amministrativa, il login, il carrello e il checkout sono sempre escluse.
Il problema è distinguere un anonimo da un utente loggato, visto che entrambi hanno un cookie di sessione dal nome indistinguibile. Joomla non fornisce un indicatore pensato per un reverse proxy, quindi lo creiamo noi: un piccolo plugin di sistema che al login imposta un cookie dedicato, per esempio ms_loggato=1, e al logout lo cancella. Joomla 4 e 5 mettono a disposizione gli eventi giusti (onUserAfterLogin e onUserLogout) e il plugin si scrive in poche righe. Lo stesso plugin può inviare Cache-Control: private agli utenti autenticati, così nessuna cache intermedia conserva le loro pagine.
La configurazione VCL
Ecco una base per Varnish 6 o 7, da adattare al singolo sito:
vcl 4.1;
sub vcl_recv {
# Solo GET e HEAD possono finire in cache
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Area amministrativa, utenti, form e percorsi dinamici
if (req.url ~ "^/administrator" ||
req.url ~ "option=com_users" ||
req.url ~ "[?&]task=" ||
req.url ~ "^/(login|accedi|registrazione|carrello|checkout)") {
return (pass);
}
# Utente autenticato o con "ricordami": niente cache
if (req.http.Cookie ~ "ms_loggato=1" ||
req.http.Cookie ~ "joomla_remember_me_") {
return (pass);
}
# Parametri di tracciamento: non cambiano la pagina
if (req.url ~ "[?&](utm_[a-z]+|gclid|fbclid|msclkid)=") {
set req.url = regsuball(req.url, "(utm_[a-z]+|gclid|fbclid|msclkid)=[^&]*&?", "");
set req.url = regsub(req.url, "[?&]+$", "");
}
# Visitatore anonimo: il cookie di sessione non serve
unset req.http.Cookie;
return (hash);
}
sub vcl_backend_response {
if (bereq.uncacheable) {
return (deliver);
}
# Joomla invia un cookie di sessione e "no-cache" anche agli ospiti
unset beresp.http.Set-Cookie;
unset beresp.http.Cache-Control;
unset beresp.http.Expires;
unset beresp.http.Pragma;
set beresp.ttl = 10m;
set beresp.grace = 6h;
return (deliver);
}
Alcune note su queste regole. I percorsi esclusi vanno adattati agli alias di menu reali del sito: se la pagina di login si chiama /area-riservata, è quella che va esclusa. Il cookie joomla_remember_me_ serve a non “dimenticare” gli utenti che hanno scelto di restare collegati: senza quella regola, Varnish toglierebbe il cookie e Joomla non potrebbe riconoscerli. Il grace di sei ore permette a Varnish di servire una copia appena scaduta mentre ne prepara una nuova, evitando che un picco di traffico arrivi tutto insieme su PHP proprio allo scadere della cache.
La trappola dei token di sicurezza
Joomla protegge i form con un token CSRF: un codice inserito nell’HTML che deve corrispondere alla sessione di chi invia il form. Se una pagina che contiene un form finisce in cache, tutti i visitatori ricevono lo stesso token, che non corrisponde a nessuna delle loro sessioni. Il risultato è il classico errore sul token non valido al momento dell’invio.
Il caso più frequente è il modulo di login mostrato in tutte le pagine, magari nella barra laterale o nell’intestazione. Con la cache attiva diventa inutilizzabile. Le soluzioni pulite sono due: mostrare il form di login solo nella pagina di login, che è esclusa dalla cache, oppure sostituirlo con un semplice link a quella pagina. Lo stesso vale per i moduli di contatto e per qualsiasi form inserito in pagine pubbliche: o vivono in pagine escluse, o vengono caricati separatamente.
La cache di Joomla serve ancora?
Joomla ha un proprio sistema di cache: la cache di sistema (conservativa o progressiva) e il plugin “System – Page Cache”, che conserva le pagine intere per i visitatori ospiti. Con Varnish davanti, la cache di pagina di Joomla diventa in gran parte ridondante: Varnish risponde prima ancora che PHP venga avviato, quindi le pagine intere conservate da Joomla vengono raramente richieste.
La cache conservativa dei moduli, invece, resta utile: rende più veloce la generazione delle pagine quando Varnish deve chiederle a PHP, cioè sui MISS e per gli utenti autenticati. È la combinazione che consigliamo: Varnish per le pagine intere, cache conservativa di Joomla per i pezzi.
Aggiornare la cache quando si pubblica
Joomla non ha un’integrazione nativa con Varnish per svuotare le pagine modificate. Con un TTL di dieci minuti il problema è contenuto: un articolo modificato appare aggiornato entro pochi minuti. Quando servono aggiornamenti immediati, lo stesso plugin di sistema può intercettare il salvataggio dei contenuti (evento onContentAfterSave) e chiedere a Varnish di invalidare la pagina dell’articolo, la sua categoria e la home, con una richiesta autorizzata solo dal server stesso. In questo modo si può allungare il TTL e aumentare ancora la percentuale di HIT.
Come verificare che funzioni
Tre controlli bastano:
- da visitatore anonimo, ricaricando una pagina due volte, la seconda risposta deve arrivare da Varnish (l’intestazione
Agediventa maggiore di zero); - da utente loggato, le pagine devono mostrare il proprio nome e il proprio menu, mai quelli di altri;
- i form (login, contatti, registrazione) devono funzionare al primo invio, senza errori sul token.
Su un sito in produzione conviene poi guardare per qualche giorno il rapporto tra HIT e MISS con varnishstat: è il numero che dice se la configurazione sta davvero alleggerendo il server.
Conclusioni
Varnish e Joomla funzionano molto bene insieme, a patto di conoscere il punto in cui si scontrano: il cookie di sessione assegnato a tutti. Togliendolo agli anonimi, riconoscendo gli utenti autenticati con un cookie dedicato e tenendo fuori dalla cache form e aree riservate, si passa da una cache inutilizzata a tempi di risposta di poche decine di millisecondi per la grande maggioranza delle visite.
Se il tuo sito Joomla è lento o se hai già provato Varnish senza risultati, sul nostro hosting Joomla configuriamo cache, plugin ed esclusioni su misura del sito, e con il servizio di assistenza Varnish Cache interveniamo anche su infrastrutture esistenti.
