Il mio processo per un setup WooCommerce Performance (LEMP)

Quando preparo un nuovo server per WooCommerce, seguo un processo distillato negli anni.
Non è una “ricetta magica”, ma un manuale operativo per trasformare una macchina cloud standard in un setup ottimizzato per l’e-commerce.

L’obiettivo è la stabilità e la velocità, che ottengo lavorando su tre fronti: I/O stabile, ottimizzazione della RAM per il database e una cache a tre livelli + CDN.

Stack di riferimento

  • Server: macchina cloud con vCPU dedicate per garantire I/O costante.
  • OS: Ubuntu 24.04 LTS.
  • Pannello: Virtualmin installato in modalità --minimal. Solo stack LEMP, senza servizi email o DNS locali.
  • Motori: Nginx e PHP-FPM dai repository ppa:ondrej, più Redis per la cache.
  • DNS & CDN: Cloudflare per la gestione DNS, la protezione DDoS e la cache di livello 1 (Edge Cache e proxy HTTPS).

Appena installato Virtualmin, il primo passo è la purga:
disabilito tutti i servizi non necessari (postfix, dovecot, bind9, proftpd, firewalld, spamassassin, clamav-daemon).

Messa a punto del server master (una tantum)

Dopo aver completato l’hardening del server — quindi la messa in sicurezza del sistema, la gestione degli accessi SSH, il blocco dei servizi inutili e l’applicazione dei limiti di rete — passo alla configurazione delle performance.

Queste sono le modifiche globali che applico al server una sola volta.

  1. Swap e Swappiness
    Creo un file di swap. La dimensione dipende dalla RAM, ma imposto sempre vm.swappiness = 10 in /etc/sysctl.conf, così il sistema usa lo swap solo quando strettamente necessario.  
  2. Tuning MariaDB
    Il database è il cuore di WooCommerce.
    In 50-server.cnf alloco una parte significativa della RAM all’innodb_buffer_pool_size (es. 8 GB su una macchina da 16 GB).
     Aggiungo:
    innodb_flush_method = O_DIRECT
    innodb_log_file_size = 1G
    innodb_buffer_pool_instances = 8
  3. Tuning Redis (Cache L3)
    Redis funge da Object Cache per WordPress.
    Imposto limiti precisi:
    maxmemory 1024mb
    maxmemory-policy allkeys-lru
    In questo modo Redis rimuove automaticamente le chiavi meno usate e mantiene costante il consumo di RAM.  
  4. Tuning Nginx (Cache L2 globale)
    Definisco il percorso della cache globale nel file nginx.conf (dentro http {}):
    fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=WORDPRESS:100m inactive=60m max_size=1g;
    Questo crea la cache condivisa che i vari siti potranno utilizzare.  
  5. Firewall e sicurezza base
    Abilito ufw solo sulle porte essenziali (22, 80, 443, 10000) e lascio la protezione avanzata a Cloudflare.  

Checklist per un nuovo sito WooCommerce

Per ogni nuovo dominio WooCommerce, seguo un flusso preciso e ripetibile.

  1. Creazione del sito
    Da Virtualmin creo un “Virtual Server”, disabilitando email e DNS locali.
    Il dominio principale usa Cloudflare, che gestisce il traffico e la cache di primo livello.  
  2. SSL e HTTP/2
    Richiedo il certificato Let’s Encrypt e abilito SSL + HTTP/2 dalle “Nginx Website Options”.
    Su Cloudflare, imposto modalità SSL “Full (Strict)” e attivo HTTP/3.
     
  3. Tuning PHP-FPM (per versione)
    Se è la prima volta che uso una certa versione di PHP sul server, ottimizzo il pool:  
    pm = ondemand
    pm.max_children = 75
    pm.process_idle_timeout = 10s
    memory_limit = 512M
    Per siti ad alto traffico, valuto pm = dynamic con limiti più alti.  
  4. Configurazione Nginx (per sito)
    Modifico il file di configurazione del dominio e aggiungo:
    fastcgi_cache WORDPRESS;
    fastcgi_cache_valid 200 60m;
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;
    Includo anche le regole di bypass per carrello, checkout e pagine utente.  
  5. Config Purge
    Aggiungo un blocco dedicato al purge:
    location ~ /purge(/.*) {
        allow 127.0.0.1;
        deny all;
        fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
    }
    Serve al plugin Nginx Helper per svuotare la cache L2 in modo selettivo.  
  6. Cron reale
    Disabilito il cron finto di WordPress aggiungendo in wp-config.php:
    define('DISABLE_WP_CRON', true);
    Poi imposto un cron vero da Webmin, che gira ogni 5 minuti come utente del sito:
    */5 * * * * php /home/utente/public_html/wp-cron.php > /dev/null 2>&1
  7. Plugin WordPress
    Dopo l’installazione, attivo:
    • Redis Object Cache – gestisce la cache L3 a livello di oggetti.
    • Nginx Helper – gestisce la cache L2 e le operazioni di purge.
    • Cloudflare (ufficiale) – integra la cache L1 edge e le funzioni di protezione (Firewall, DDoS, Bot Fight).
  8. Impostazioni Cloudflare consigliate
    • Modalità proxy attiva (nuvola arancione).
    • Page Rules o Cache Rules per cache “Cache Everything” sulle pagine pubbliche.
    • Firewall Rules per bloccare accessi diretti all’IP origin.
    • Browser Cache TTL = 1 giorno, Edge Cache TTL = 1 ora (bilanciato).
    • Always Use HTTPS e HTTP/3 abilitati.

Risultato finale

Con questo schema a quattro livelli di cache:

  1. L1 → Cloudflare (Edge Cache + DNS + Protezione)
  2. L2 → Nginx FastCGI Cache
  3. L3 → Redis Object Cache
  4. L4 → Query cache di MariaDB (buffer pool ottimizzato)

ottengo un’infrastruttura WooCommerce veloce, sicura e replicabile,
con tempi di risposta medi sotto i 100 ms per le pagine cached e un backend stabile anche con carichi elevati.