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”.