Come configurare NGINX per ottimizzare la velocità del sito web – Parte 2

Configurazione standard di NGINX per un sito web

Vediamo come configurare i blocchi principali di Nginx per mettere in linea il sito  www.dominiosito.it con un po’ di ottimizzazioni. Vogliamo avere performance per migliorare la considerazione da parte dei motori di ricerca e nel contempo sicurezza.

Parlando di sicurezza definiamo unicamente nginx per servire le pagine in SSL e in HTTP2 tralasciando l’ormai obsoleto http1.

server {
        listen 443 ssl http2;
        ssl on;
        server_name www.dominiosito.it;

Definiamo in quale directory mettere i log di errore ed accesso, che ci serviranno per debug e diagnosi di eventuali problemi. se il sito è uno solo possiamo usare semplicemente la directory di log di default di nginx:

        access_log /var/log/nginx/dominiosito.access.log;
        error_log /var/log/nginx/dominiosito.error.log;

e ovviamente dobbiamo dire a nginx dov’è la root directory che contiene il sito da servire:

        root /var/www/momit.eu;

Abbiamo detto che usiamo l’SSL e quindi tutte le richieste saranno in https. Perché la sicurezza sia davvero sicurezza e non solo l’icona del lucchetto nel browser è fondamentale che i certificati SSL siano usati nel modo corretto.  Non basta usare il file crt (certificato) e il file key (chiave privata), ma va strutturata la cosiddetta “chain” ovvero corretta catena di certificati.

In realtà noi vi sconsigliamo di usare i file crt e key, ma di creare un più completo pem con tutta la corretta sequenza di certificati. Un file pem con l’intera catena di certificati è composto dal certificato di RootCA concatenato alle IntermediateCA concatenato al Certificato del dominio.

# ssl_certificate /etc/ssl/certs/dominiosito.pem;
# ssl_certificate_key /etc/ssl/private/dominiosito.key;

Allo stesso modo va specificato di usare algoritmi di crittografia sicuri e non tutti quelli disponibili. Questo va a discapito di vecchi browser e potrebbe non rendere visualizzabile il sito su sistemi obsoleti (ad esempio un vecchio Netscape Navigator.. J ) ma ci rende la comunicazione sicura:

ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

Vanno eliminati SSL 2.0, SSL 3.0 , TLS 1.0 e TLS 1.1 che sono ormai sorpassati e insicuri. Attenzione però a specificare TLS 1.3, è supportato solo dalle versione di Nginx 1.13 o superiore, quindi assicuratevi prima di sapere che sia supportato, altrimenti usate solo TLS 1.2:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/dhparams.pem;

Implementiamo ora gli algoritmi per la cache…

ssl_session_cache shared:le_nginx_SSL:40m;
ssl_session_timeout 2h;
ssl_session_tickets off;

e diciamo che non deve inziare lo scambio di dati al client fintando che la connessione non è sicura:

add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload" always;

Ora mettiamo un po’ di performance; intanto applicchiamo la compressione dei dati ove possibile, in modo da ottimizzare e risparmiare traffico

gzip on;
gzip_vary on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
gzip_disable "MSIE [1-6]\.";

A questo punto possiamo procedere con le opzioni più standard, ovvero indicare di servire le pagine php o html a seconda di come è fatto il sito

location / {
index index.php index.html;
try_files $uri $uri/ /index.php?$args;
}

e nel caso di php chi è l’interprete per php. In questo esempio è riportato php-fpm per php 7.3, ma potrebbe essere un php-cgi server

location ~ \.php$ {
try_files                       $uri =404;
include                         /etc/nginx/fastcgi_params;
fastcgi_read_timeout            3600s;
fastcgi_buffer_size             128k;
fastcgi_buffers                 4 128k;
fastcgi_param                   SCRIPT_FILENAME document_root$fastcgi_script_name;
fastcgi_pass                    unix:/run/php/php7.3-fpm.sock;
fastcgi_index                   index.php;
}

di seguito alcune best practice per file particolari del sito, come ad esempio l’icona per il browser..

location = /favicon.ico {
access_log off;
log_not_found off;
expires max;
}

…o il file robot.txt che serve di supporto alla sitemap per i motori di ricerca:

location = /robots.txt {
try_files $uri $uri/ /index.php?$args;
access_log off;
log_not_found off;
}

C’è poi tutta una parte di file statici, che non cambiano nel tempo su cui possiamo attivare cache a lungo periodo, perché per  l’appunto non cambiano:

location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf)$ {
add_header "Access-Control-Allow-Origin" "*";
access_log off;
log_not_found off;
expires max;
}

e ci sono file e percorsi che invece servono al sistema ma è meglio che non siano accessibili, con l’eccezione di quello necessario all’URL di verifica SSL:

location ~ /\.well-known {
allow all;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}

Ovviamente non vogliamo nemmeno che siano accessibili i file di di log o di backup, nel caso fossimo su un hosting condiviso e usassimo un plugin o uno script per eseguire il backup del database nella root:

location ~* ^.+\.(bak|log|old|orig|original|php#|php~|php_bak|save|swo|swp|sql)$ {
deny all;
access_log off;
log_not_found off;
}

infine, giusto per i CMS (dato che nessuno si preoccupa mai della sicurezza) rendiamo inaccessibili i file di servizio.

if ($uri ~* "^.+(readme|license|example)\.(txt|html)$") {
return 403;
}
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}

Solo per wordpress possiamo inoltre aggiungere lo / alla richiesta di area amministrativa (dimenticanza comune) ma in generale con le regole di rewrite possiamo modificare o redirigere pagine e URL a nostro piacere

rewrite /wp-admin$ $scheme://$host$uri/ permanent;
}

E infine per tornare all’inzio, non dimentichiamoci che abbiamo configurato tutto in https, per cui una richiesta http in porta 80 restituirà errore. Per evitare questo indichiamo a nginx che tutto cosa arriva in http dovrà essere inoltrato allo stesso indirizzo ma https:

server {
        listen 80;
        server_name dominiosito.it;
        return 301 https://www.dominiosito.it$request_uri;
}

Bene, ora non resta che salvare il file ed eseguire il comando

# nginx –t

Per il test della configurazione e se non ci sono errori, puoi riavviare Nginx mettendola in atto. Ricorda che il sito oltre ad essere veloce deve essere sicuro !  Controlla il tuo rating su SSL Labs, il punteggio ottimale deve essere A+ come il nostro sito 


Vai alla PARTE 1 dell’articolo “Come configurare NGINX per ottimizzare la velocità del sito web”.

© 2015 - 2021 MOMIT
All Rights Reserved
Viale Enrico Forlanini, 23 20134 Milano
P.IVA / C.F IT07634600964
Tel. +39 02 87187306
Email: info@momit.it


Partner with Idoma