Installare e proteggere un server Nginx su Ubuntu

Guida completa all'installazione e alla messa in sicurezza di Nginx su Ubuntu: virtual host, firewall UFW, HTTPS con Certbot, permessi, header di sicurezza, aggiornamenti, log e controlli finali.

Installare e proteggere un server Nginx su Ubuntu

Nginx è uno dei web server più utilizzati per pubblicare siti, applicazioni e API oppure per agire da reverse proxy. Installarlo su Ubuntu richiede pochi comandi, ma una configurazione realmente adatta a Internet deve considerare firewall, HTTPS, permessi, aggiornamenti e monitoraggio. Questa guida mostra un percorso prudente e ripetibile, adatto a Ubuntu Server 24.04 LTS e alle versioni supportate più recenti.

Prima di iniziare

Servono un server Ubuntu aggiornato, un account con privilegi sudo e, per HTTPS, un dominio il cui record DNS punti all'indirizzo pubblico del server. Se lavori a distanza, mantieni aperta una seconda sessione SSH e assicurati di autorizzare SSH nel firewall prima di abilitarlo.

Negli esempi useremo il dominio example.com. Sostituiscilo sempre con il tuo dominio reale. Verifica il DNS con:

dig +short example.com A
dig +short example.com AAAA

Il record A deve restituire l'indirizzo IPv4 corretto. Se pubblichi anche un record AAAA, il server deve essere effettivamente raggiungibile e protetto anche tramite IPv6.

1. Aggiornare Ubuntu e installare Nginx

sudo apt update
sudo apt upgrade
sudo apt install nginx

Il pacchetto Ubuntu installa Nginx e avvia il servizio. Controlla versione e stato:

nginx -v
sudo systemctl status nginx --no-pager
sudo systemctl is-enabled nginx

Il servizio dovrebbe risultare active (running) e abilitato all'avvio. Se necessario:

sudo systemctl enable --now nginx

Verifica localmente la risposta HTTP:

curl -I http://127.0.0.1

Una risposta come HTTP/1.1 200 OK conferma che Nginx è in ascolto. Puoi controllare le porte con:

sudo ss -lntp | grep nginx

2. Configurare UFW senza perdere SSH

Prima di abilitare il firewall autorizza la porta SSH effettiva. Se usi la porta standard e il profilo è presente:

sudo ufw allow OpenSSH comment 'Accesso amministrativo'
sudo ufw allow 'Nginx Full' comment 'HTTP e HTTPS'
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
sudo ufw status verbose

Il profilo Nginx Full consente TCP 80 e 443. La porta 80 resta necessaria per il reindirizzamento HTTP verso HTTPS e per alcune procedure di convalida dei certificati. Se SSH ascolta su una porta personalizzata, autorizza prima quella porta con sudo ufw allow NUMERO/tcp.

Dopo l'attivazione prova una nuova connessione SSH da un secondo terminale. Non chiudere la sessione esistente finché il test non è riuscito.

3. Creare una directory web con permessi controllati

Separare i contenuti per dominio rende più semplice amministrare più siti:

sudo mkdir -p /var/www/example.com/public
sudo chown -R $USER:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 750 {} \;
sudo find /var/www/example.com -type f -exec chmod 640 {} \;

Crea una pagina di prova:

nano /var/www/example.com/public/index.html

Inserisci un documento HTML minimo e salva. Evita di assegnare permessi 777: consentire scrittura indiscriminata non risolve i problemi di proprietà e aumenta il danno possibile in caso di compromissione. Le applicazioni dinamiche dovrebbero avere scrittura soltanto sulle directory che ne hanno realmente bisogno, come cache o upload.

4. Creare il server block

Su Ubuntu i siti vengono normalmente definiti in /etc/nginx/sites-available e attivati tramite collegamento in sites-enabled. Crea il file:

sudo nano /etc/nginx/sites-available/example.com

Configurazione HTTP iniziale:

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;
    root /var/www/example.com/public;
    index index.html;

    access_log /var/log/nginx/example.com.access.log;
    error_log  /var/log/nginx/example.com.error.log;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ /\. {
        deny all;
    }
}

La direttiva server_name associa le richieste al sito corretto; root indica la directory pubblica. try_files evita che richieste inesistenti vengano inoltrate implicitamente altrove. La regola sui file nascosti impedisce l'accesso a elementi come .env o metadati di versionamento. Quando userai Certbot, l'eccezione necessaria per /.well-known/acme-challenge/ verrà gestita dalla procedura di convalida.

Attiva il sito e disabilita quello predefinito:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo rm -f /etc/nginx/sites-enabled/default

5. Testare sempre prima del reload

Ogni modifica deve essere verificata prima di ricaricare il servizio:

sudo nginx -t
sudo systemctl reload nginx

nginx -t controlla sintassi e riferimenti ai file. Il reload applica la configurazione in modo ordinato: i worker esistenti terminano le richieste già accettate mentre i nuovi usano la configurazione aggiornata. Se il test fallisce, non eseguire il reload; correggi il file indicato nel messaggio.

Controlla il virtual host senza attendere la propagazione DNS:

curl -I -H 'Host: example.com' http://127.0.0.1

6. Attivare HTTPS con Certbot

Prima di richiedere il certificato verifica che il dominio sia raggiungibile pubblicamente sulla porta 80. Le istruzioni ufficiali di Certbot raccomandano l'installazione tramite snap:

sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot

Se il collegamento esiste già, il relativo comando può essere omesso. Richiedi quindi il certificato e lascia che Certbot aggiorni Nginx:

sudo certbot --nginx -d example.com -d www.example.com

Scegli il reindirizzamento verso HTTPS quando proposto. Poi esegui:

sudo nginx -t
sudo systemctl reload nginx
curl -I https://example.com

I certificati Let's Encrypt hanno durata limitata, ma Certbot configura il rinnovo automatico. Verificalo senza emettere un nuovo certificato:

sudo certbot renew --dry-run
systemctl list-timers | grep certbot

Un certificato valido non garantisce da solo la sicurezza del sito: protegge il traffico durante il trasporto, mentre applicazione, account e sistema operativo devono essere protetti separatamente.

7. Applicare impostazioni di sicurezza ragionevoli

Nascondi la versione precisa di Nginx nelle pagine di errore e nell'header Server. In /etc/nginx/nginx.conf, dentro il blocco http, imposta:

server_tokens off;

Nel server block HTTPS puoi aggiungere header generali:

add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
add_header X-Frame-Options SAMEORIGIN always;

X-Frame-Options SAMEORIGIN non è adatto se il sito deve essere incorporato legittimamente in iframe di domini esterni. Una Content Security Policy può offrire una protezione più completa, ma deve essere costruita in base alle risorse effettivamente usate dall'applicazione: copiarne una troppo restrittiva può bloccare script, stili, immagini o servizi indispensabili.

HSTS comunica ai browser di usare soltanto HTTPS. Aggiungilo solo dopo aver verificato certificato, redirect e tutti i sottodomini interessati:

add_header Strict-Transport-Security 'max-age=31536000' always;

Non includere subito includeSubDomains o la richiesta di preload se non sei certo che ogni sottodominio supporti permanentemente HTTPS. Un'impostazione HSTS errata può rendere il sito irraggiungibile dal browser per molto tempo.

8. Limitare richieste e upload

Se il sito non richiede file molto grandi, stabilisci un limite esplicito nel server block:

client_max_body_size 8m;

Nginx rifiuterà richieste superiori con errore 413. Per applicazioni PHP, il valore deve essere coerente anche con upload_max_filesize e post_max_size. Un limite riduce abusi e consumo accidentale di risorse, ma non sostituisce controlli sul tipo reale del file e sul nome assegnato dall'applicazione.

Per endpoint sensibili è possibile configurare limit_req, ma soglie arbitrarie possono bloccare utenti legittimi dietro NAT. Misura prima il traffico e adatta la regola al servizio.

9. Configurare un reverse proxy in modo corretto

Se Nginx pubblica un'applicazione locale sulla porta 8080, usa un blocco simile:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

L'applicazione a monte dovrebbe ascoltare soltanto su 127.0.0.1, quando non deve essere raggiunta direttamente. Non fidarti automaticamente degli header inoltrati se Nginx non è l'unico punto d'ingresso e non esporre al pubblico porte amministrative o di debug.

10. Aggiornamenti automatici e riduzione della superficie

Installa gli aggiornamenti regolarmente e valuta gli aggiornamenti di sicurezza automatici:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades

Controlla i pacchetti aggiornabili con apt list --upgradable. Rimuovi moduli e servizi inutilizzati, limita gli account con accesso amministrativo e preferisci chiavi SSH alle password. Nginx è soltanto uno degli elementi della catena: PHP, runtime applicativi, database e librerie devono seguire lo stesso ciclo di manutenzione.

11. Log, diagnostica e monitoraggio

I log principali su Ubuntu sono:

/var/log/nginx/access.log
/var/log/nginx/error.log

Nel nostro server block abbiamo creato file distinti per il dominio. Per seguire gli errori:

sudo tail -f /var/log/nginx/example.com.error.log

Per consultare il servizio:

sudo journalctl -u nginx --since '1 hour ago'
sudo systemctl status nginx --no-pager

Ubuntu configura normalmente la rotazione dei log tramite logrotate. Controlla comunque spazio libero e dimensioni:

df -h
sudo du -sh /var/log/nginx

Errori frequenti includono: 403 per permessi o indice assente; 404 per root o location errati; 502 quando il servizio a monte non risponde; loop di redirect quando applicazione e proxy interpretano diversamente HTTPS.

12. Checklist finale

  • Nginx è attivo e abilitato all'avvio;
  • SSH è consentito prima dell'attivazione di UFW;
  • soltanto le porte 80 e 443 sono pubbliche per il web;
  • il sito predefinito è disabilitato;
  • document root e permessi seguono il principio del minimo privilegio;
  • nginx -t viene eseguito prima di ogni reload;
  • HTTPS e rinnovo Certbot sono stati provati;
  • header e limiti sono compatibili con l'applicazione;
  • log, spazio disco e aggiornamenti vengono monitorati;
  • eventuali backend ascoltano solo sulle interfacce necessarie.

Conclusione

Un server Nginx sicuro nasce da una configurazione semplice, verificabile e mantenuta nel tempo. Installazione dai repository Ubuntu, server block separati, test prima del reload, firewall, HTTPS automatico e permessi minimi costituiscono una base solida. A questa base vanno aggiunti controlli specifici per l'applicazione, monitoraggio e aggiornamenti regolari: la sicurezza non è un comando isolato, ma un processo continuo.

Share

What's Your Reaction?

Like Like 0
Cancella like Cancella like 0
Amore Amore 0
Buffo Buffo 0
arrabbiato arrabbiato 0
Sad Sad 0
Wow Wow 0