Ottimizzazione e Hardening di Nginx per WordPress su Ubuntu

Gestire un portale WordPress su un VPS Linux significa avere il controllo totale delle performance e della sicurezza. Spesso ci si affida a plugin pesanti per la protezione o per la compressione, dimenticando che gran parte del lavoro può essere fatto direttamente a monte, a livello di server web con Nginx.

In questa guida vediamo come configurare Nginx per migliorare le performance di WordPress e proteggere i punti critici contro gli attacchi più comuni.


1. Ottimizzazione dei Buffer e dei Parametri di Rete

Il primo passo consiste nell’assicurarsi che Nginx gestisca correttamente le richieste HTTP e i caricamenti pesanti (come l’upload di immagini o plugin) senza andare in errore o sprecare risorse.

Apri il file di configurazione principale (solitamente /etc/nginx/nginx.conf) e verifica o aggiungi, all’interno del blocco http { ... } già esistente, questi parametri (non sostituire il blocco, aggiungi o modifica solo le righe):

http {
    # Limite massimo per l'upload di file (es. 64MB)
    client_max_body_size 64M;

    # Timeout per mantenere le connessioni aperte e ridurre l'overhead TCP
    keepalive_timeout 65;
    keepalive_requests 100;

    # Dimensione della tabella hash dei tipi MIME
    types_hash_max_size 2048;
    server_tokens off; # Nasconde la versione di Nginx per sicurezza

    # Buffer tuning
    client_body_buffer_size 128k;
    large_client_header_buffers 4 16k;
}
  • server_tokens off;: evita che Nginx mostri la versione esatta del software nelle pagine di errore o negli header HTTP, riducendo le informazioni utili a eventuali bot malevoli.
  • client_max_body_size: va alzato rispetto al default di 1MB, altrimenti il caricamento di temi, plugin o file pesanti dalla dashboard di WordPress fallisce con errore 413.

Attenzione: il limite di Nginx da solo non basta. Anche PHP ha i suoi limiti, e vince il più basso. Nel file php.ini (ad esempio /etc/php/8.3/fpm/php.ini, adatta la versione alla tua) imposta valori coerenti:

upload_max_filesize = 64M
post_max_size = 64M

Poi riavvia PHP-FPM, ad esempio con sudo systemctl restart php8.3-fpm.


2. Abilitare la Compressione Gzip

Ridurre la quantità di dati scambiati tra il VPS e il browser degli utenti velocizza sensibilmente il caricamento delle pagine. Nginx integra un modulo Gzip nativo molto efficiente.

Sempre all’interno del blocco http { ... } del file nginx.conf, puoi configurare la compressione in questo modo:

    # Compressione Gzip
    gzip on;
    gzip_vary on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/json
        application/xml
        application/rss+xml
        application/manifest+json
        image/svg+xml
        font/ttf
        font/otf
        application/vnd.ms-fontobject;
  • gzip_comp_level 5: il default è 1, che comprime poco. I livelli 4-6 sono un buon compromesso tra CPU e dimensione; oltre il 6 il guadagno è minimo e il costo in CPU cresce.
  • gzip_proxied any: comprime le risposte anche quando la richiesta arriva tramite proxy (utile se davanti a Nginx c’è Cloudflare o un altro reverse proxy).
  • Cosa non includere: text/html viene sempre compresso, mentre JPG, PNG, WebP e WOFF2 sono già compressi e non traggono beneficio da Gzip.

Se nginx -t segnala che la direttiva gzip è duplicata, significa che è già attiva in un altro file (ad esempio in conf.d/): tienila in un solo posto.


3. Hardening di Nginx: Proteggere WordPress

WordPress è uno dei CMS più bersagliati al mondo da tentativi di forza bruta e script automatici. Possiamo sfruttare il blocco server { ... } del sito per chiudere l’accesso alle aree più sensibili.

All’interno del file di configurazione del tuo virtual host (es. /etc/nginx/sites-available/rfnode.net), inserisci queste direttive. Importante: le location con espressioni regolari vengono valutate nell’ordine in cui compaiono, quindi queste regole vanno scritte prima del blocco location ~ \.php$ che passa il codice a PHP-FPM, altrimenti verrebbero ignorate.

# Redirect da HTTP a HTTPS
server {
    listen 80;
    server_name rfnode.net www.rfnode.net;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;   # da Nginx 1.25.1; nelle versioni precedenti: listen 443 ssl http2;
    server_name rfnode.net www.rfnode.net;
    # ... configurazioni root, certificati SSL, ecc. ...

    # 1. Protezione dei file di configurazione e di sistema
    location ~* /(wp-config\.php|readme\.html|license\.txt|install\.php) {
        deny all;
    }

    # 2. Impedisce l'esecuzione di script PHP nella cartella uploads
    location ~* /wp-content/uploads/.*\.php$ {
        deny all;
    }

    # 3. Bloccare XML-RPC (spesso usato per attacchi DDoS e brute-force)
    location = /xmlrpc.php {
        deny all;
        # Se ti serve per IP specifici, 'allow' va messo PRIMA di 'deny all':
        # allow 123.45.67.89;
        # deny all;
    }

    # 4. Bloccare i file nascosti (.git, .env, .htaccess), ma non .well-known
    #    che serve a Let's Encrypt per il rinnovo dei certificati
    location ~ /\.(?!well-known) {
        deny all;
        access_log off;
        log_not_found off;
    }

    # ... qui sotto, location / e location ~ \.php$ ...
}

Cosa fanno queste regole?

  • Bloccano wp-config.php: impediscono la lettura via web del file che contiene le credenziali del database, nel caso in cui PHP smetta di interpretarlo per un errore di configurazione.
  • Blindano gli upload: se un utente malintenzionato riuscisse a caricare uno script PHP nella cartella delle immagini, Nginx risponde con un 403 senza passare il file a PHP-FPM.
  • Bloccano XML-RPC: a meno che tu non usi app particolari, riduce drasticamente i tentativi di login automatici. Attenzione: Jetpack e l’app mobile di WordPress usano XML-RPC, quindi con il blocco totale potrebbero smettere di funzionare.
  • Proteggono i file nascosti, lasciando però accessibile /.well-known/ per il rinnovo automatico dei certificati SSL.

4. Test della Configurazione e Riavvio

Prima di applicare le modifiche in produzione, verifica sempre che la sintassi di Nginx sia corretta:

sudo nginx -t

Se l’output restituisce syntax is ok e test is successful, puoi ricaricare il demone senza interrompere le connessioni attive:

sudo systemctl reload nginx

Per verificare che la compressione funzioni:

curl -s -I -H "Accept-Encoding: gzip" https://rfnode.net/wp-content/themes/tuotema/style.css | grep -i content-encoding

Deve comparire content-encoding: gzip. Per controllare il blocco di XML-RPC, curl -I https://rfnode.net/xmlrpc.php deve restituire 403.


Conclusione

Con poche righe aggiunte alle configurazioni di Nginx hai alleggerito il carico sul server, ridotto la banda consumata grazie alla compressione e chiuso la porta ai tentativi di intrusione più comuni su WordPress. Una buona base sistemistica per mantenere il tuo VPS veloce e sicuro.

[post-views]

Di Corrado