Varnish Cache per WordPress: Setup e Invalidazione

22 agosto 20267 minGuide
In breveAI

Guida completa per configurare Varnish come full page cache per WordPress: VCL ottimizzata, strategie di invalidazione automatica e purge selettivo per massimizzare performance.

Perché Varnish per WordPress

Varnish è un HTTP accelerator che si posiziona davanti al web server (Nginx o Apache) e serve contenuti cachati direttamente dalla RAM. A differenza di soluzioni PHP-based come WP Super Cache o W3 Total Cache, Varnish intercetta le richieste prima che raggiungano il web server, riducendo drasticamente il carico sul backend.

In deployment reali con traffico medio-alto (50.000+ pageviews/giorno), Varnish può ridurre il Time to First Byte da 200-400ms a 5-20ms, con hit rate superiori al 95% se configurato correttamente. Il problema è che WordPress genera contenuti dinamici e richiede una strategia di invalidazione precisa per evitare di servire contenuti obsoleti.

Architettura e flusso delle richieste

La stack tipica con Varnish è la seguente:

  • Client → Varnish (porta 80/443) → Nginx/Apache (porta 8080) → PHP-FPM → WordPress
  • Varnish gestisce SSL tramite Hitch o delegando a Nginx in reverse proxy
  • Le richieste autenticate (logged-in users) bypassano Varnish usando cookie detection
  • I purge vengono inviati da WordPress a Varnish via HTTP PURGE method

Il vantaggio principale: Varnish serve contenuti statici a velocità di rete senza toccare PHP. Lo svantaggio: configurazione più complessa e necessità di gestire l’invalidazione cache a livello applicativo.

Installazione e configurazione base

Su Ubuntu 22.04/24.04, l’installazione è diretta:

apt update
apt install varnish
systemctl enable varnish

Modifica /etc/default/varnish per impostare la porta di ascolto:

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

Configurazione chiave:

  • -a :80: Varnish ascolta sulla porta 80 (HTTP pubblico)
  • -T localhost:6082: interfaccia admin per varnishadm
  • -s malloc,2G: alloca 2GB di RAM per la cache (adatta in base al server)
  • -f default.vcl: file di configurazione principale

Sposta Nginx/Apache sulla porta 8080 modificando la configurazione del virtual host, poi riavvia entrambi i servizi.

VCL personalizzata per WordPress

Il file /etc/varnish/default.vcl definisce la logica di caching. Configurazione base ottimizzata per WordPress:

vcl 4.1;

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

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

sub vcl_recv {
    # Rimuovi parametri analytics
    if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|gclid|fbclid)=") {
        set req.url = regsub(req.url, "&(utm_source|utm_medium|utm_campaign|gclid|fbclid)=([A-z0-9_\-\.\%25]+)", "");
        set req.url = regsub(req.url, "\?(utm_source|utm_medium|utm_campaign|gclid|fbclid)=([A-z0-9_\-\.\%25]+)", "?");
        set req.url = regsub(req.url, "\?&", "?");
        set req.url = regsub(req.url, "\?$", "");
    }

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

    # Bypass per utenti loggati
    if (req.http.Cookie ~ "wordpress_logged_in|wp-postpass|comment_author") {
        return(pass);
    }

    # Bypass per admin e login
    if (req.url ~ "^/wp-(admin|login|cron)") {
        return(pass);
    }

    # Rimuovi cookie non necessari
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
    set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
    
    if (req.http.Cookie == "") {
        unset req.http.Cookie;
    }
}

sub vcl_backend_response {
    # Cache per 24 ore di default
    set beresp.ttl = 24h;
    set beresp.grace = 1h;
    
    # Non cachare errori
    if (beresp.status >= 500) {
        set beresp.ttl = 0s;
    }
}

sub vcl_deliver {
    # Header di debug
    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;
}

Elementi critici della configurazione:

  1. Normalizzazione URL: rimuove parametri tracciamento per aumentare hit rate
  2. Cookie detection: bypass automatico per utenti autenticati
  3. ACL purge: solo localhost può inviare richieste PURGE
  4. Grace mode: serve contenuti stale se backend è down

Plugin WordPress per invalidazione automatica

WordPress necessita di un plugin per comunicare con Varnish e invalidare la cache quando i contenuti cambiano. Le opzioni principali sono:

Varnish HTTP Purge (ufficiale)

Plugin leggero sviluppato dal team WordPress.com VIP. Supporta purge automatico su:

  • Pubblicazione/aggiornamento post
  • Nuovi commenti approvati
  • Aggiornamenti temi e plugin
  • Cambio impostazioni permalink

Configurazione in wp-config.php:

define('VHP_VARNISH_IP', '127.0.0.1');

Il plugin invia richieste PURGE all’IP specificato. Per installazioni multi-server, configura array di IP Varnish.

Proxy Cache Purge

Alternativa più configurabile, supporta patterns di purge personalizzati e wildcard. Utile per architetture complesse con più layer di cache.

Strategie di invalidazione avanzate

Per siti complessi, il purge totale ad ogni modifica non è efficiente. Strategie granulari:

Purge selettivo per taxonomy

Quando aggiorni un post nella categoria “Guide”, invalida solo:

  • URL del singolo post
  • Pagina archivio categoria
  • Homepage (se mostra post recenti)
  • Feed RSS

Implementazione custom con hook WordPress:

add_action('save_post', function($post_id) {
    $post = get_post($post_id);
    $urls = [
        get_permalink($post_id),
        home_url('/'),
    ];
    
    $categories = get_the_category($post_id);
    foreach ($categories as $cat) {
        $urls[] = get_category_link($cat->term_id);
    }
    
    foreach ($urls as $url) {
        wp_remote_request($url, [
            'method' => 'PURGE',
            'headers' => ['Host' => parse_url($url, PHP_URL_HOST)]
        ]);
    }
});

Cache tagging (Varnish Plus)

Varnish Plus (versione commerciale) supporta surrogate keys per invalidazione basata su tag. WordPress può aggiungere header Surrogate-Key con ID post, categorie, autori, e Varnish invalida tutte le pagine con quel tag.

Monitoraggio e debugging

Strumenti essenziali per verificare il corretto funzionamento:

varnishstat

Statistiche real-time sul hit rate:

varnishstat -1 | grep cache_hit

Target: cache_hit rate > 90% per siti con traffico consolidato.

varnishlog

Log dettagliato delle richieste:

varnishlog -q "ReqURL ~ '^/blog/'"

Filtra per specifici pattern URL per debug mirato.

Header HTTP

Verifica gli header di risposta con curl:

curl -I https://tuosito.it | grep X-Cache

Risposta attesa: X-Cache: HIT per contenuti cachati.

Problemi comuni e soluzioni

Scenari tipici in deployment reali:

  • Hit rate basso (<70%): verifica normalizzazione cookie e URL. Spesso causato da query string dinamiche o cookie di terze parti (analytics, chat widget)
  • Contenuti stale dopo update: controlla che il plugin purge sia attivo e che l’IP Varnish sia corretto. Verifica ACL purge in VCL
  • Problemi con SSL: Varnish non gestisce nativamente HTTPS. Usa Nginx come SSL terminator davanti a Varnish o configura Hitch
  • Cache di pagine 404: aggiungi check su beresp.status in vcl_backend_response per non cachare errori

Per siti ecommerce WooCommerce, bypassa completamente cart, checkout e my-account aggiungendo in vcl_recv:

if (req.url ~ "^/(cart|checkout|my-account)") {
    return(pass);
}

Performance reali: case study

Dati da deployment AgencyPilot su client medio (WordPress + WooCommerce, 80.000 pageviews/mese):

  • Prima di Varnish: TTFB medio 340ms, server load 2.8, 4GB RAM utilizzata
  • Dopo Varnish: TTFB medio 18ms (cached), server load 0.6, 2.5GB RAM utilizzata (+ 2GB Varnish)
  • Hit rate stabile: 94.3% dopo ottimizzazione VCL e normalizzazione cookie

ROI significativo per siti con traffico >30.000 pageviews/mese. Sotto quella soglia, soluzioni più semplici come Redis Object Cache o FastCGI Cache possono essere sufficienti.

FAQ

Varnish è compatibile con tutti i plugin WordPress?

La maggior parte sì, ma plugin che richiedono contenuti sempre freschi (forum real-time, live chat, countdown dinamici) possono avere problemi. Soluzione: usa AJAX per caricare quei componenti client-side, bypassando la cache. Per ecommerce, configura bypass esplicito per cart e checkout come mostrato nella guida.

Quanto RAM devo allocare a Varnish?

Dipende dal numero di pagine uniche e dalla dimensione media. Formula approssimativa: (pagine uniche × 50KB) × 1.5 di overhead. Per un blog con 1000 pagine indicizzate: ~75MB teorici, ma alloca almeno 512MB-1GB per buffering. Siti con molte immagini inline o CSS/JS pesanti: 2-4GB. Monitora con varnishstat il valore n_lru_nuked (oggetti rimossi per mancanza spazio): se cresce rapidamente, aumenta la RAM.

Come gestisco ambienti staging con Varnish?

Configura virtual host separati in VCL usando req.http.host. Esempio per staging su sottodominio:

if (req.http.host ~ "staging\.tuosito\.it") {
    set req.backend_hint = staging_backend;
    return(pass); # Bypass cache su staging
}

Alternativa: usa Varnish solo in produzione e FastCGI cache su staging per semplificare il workflow di test.

Posso usare Varnish con managed hosting WordPress?

Dipende dal provider. Kinsta, WP Engine e Flywheel usano soluzioni proprietarie (edge cache, EverCache) e non permettono Varnish custom. Su VPS gestiti (Cloudways, SpinupWP) o server dedicati hai controllo completo. Se usi managed hosting, valuta se la loro cache integrata è sufficiente prima di migrare su infrastruttura custom.

Varnish sostituisce CDN come Cloudflare?

No, sono complementari. Varnish cacha a livello server origin, CDN distribuisce contenuti su edge location globali. Stack ideale: Cloudflare (edge cache + DDoS protection) → Varnish (full page cache origin) → Nginx → WordPress. Cloudflare serve asset statici (immagini, CSS, JS) e prima richiesta HTML, Varnish cacha la generazione dinamica lato server. Disattiva HTML caching su Cloudflare se usi Varnish per evitare doppia cache e problemi di invalidazione.

Gestisci i siti WordPress dei tuoi clienti?

AgencyPilot ti dà report AI, uptime monitoring, backup e portale clienti in un’unica dashboard. Gratis per 3 siti.

Prova gratis
Leggi anche
Tutti gli articoli
Tutti gli articoli