Un server web con nginx
Modulo 7: Dominio, server web e https · Tempo di lettura: 12 minuti
Obiettivo della lezione: Dopo questa lezione sarà in grado di installare nginx, configurare un sito web e un reverse proxy con un server block, testare e ricaricare una configurazione in sicurezza e impostare correttamente i permessi della Sua webroot.
Concetti chiave: nginx, server block, sites-available e sites-enabled, conf.d, listen, server_name, root, index, try_files, default server, nginx -t, reload, reverse proxy, proxy_pass, Host, X-Forwarded-For, X-Forwarded-Proto, webroot, PHP-FPM
Che cosa fa un server web
Un server web resta in ascolto sulla porta 80 (http) e 443 (https), riceve le richieste dei browser e restituisce qualcosa: un file dal disco (un sito statico) oppure la risposta di un programma in esecuzione dietro di esso (PHP, un'app Node.js, un container). Nel secondo caso il server web si chiama reverse proxy: sta in prima linea, gestisce https e passa la richiesta all'applicazione, che resta in ascolto solo su 127.0.0.1.
Su Linux i server web più noti sono nginx e Apache, mentre Caddy (lezione 7.4) è un'alternativa moderna che gestisce da sé i certificati. Questa lezione usa nginx: è presente in ogni distribuzione, consuma poca memoria ed è lo standard in molte guide.
Installazione e primo sguardo
anna@web1:~$ sudo apt install nginx
anna@web1:~$ systemctl status nginx
anna@web1:~$ curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.26.3
Content-Type: text/html(Il numero di versione è un esempio.) Non dimentichi il firewall: le porte 80 e 443 devono essere aperte (lezione 5.2). Se ora apre http://192.0.2.10, vedrà la pagina di benvenuto di nginx.
La configurazione si trova in /etc/nginx/:
| Percorso | Contenuto |
|---|---|
nginx.conf | file principale; di solito non va toccato |
sites-available/ | un file per ogni sito (Debian e Ubuntu) |
sites-enabled/ | collegamenti (symlink) ai siti attivi |
conf.d/*.conf | impostazioni separate che vengono sempre caricate |
snippets/ | frammenti da riutilizzare in più siti |
sites-available e sites-enabled sono una convenzione di Debian e Ubuntu: così si attiva o disattiva un sito creando o rimuovendo un collegamento, senza eliminare il file.
Un primo sito
Crei una cartella per il sito e una pagina di prova:
anna@web1:~$ sudo mkdir -p /var/www/example.com
anna@web1:~$ echo '<h1>Het werkt</h1>' | sudo tee /var/www/example.com/index.htmlPoi crei un server block: la descrizione di un singolo sito.
# /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}Si legge così:
listen 80;elisten [::]:80;fanno sì che nginx ascolti sia su IPv4 sia su IPv6. Se dimentica la seconda riga, il Suo record AAAA non funziona (lezione 7.1).server_nameindica per quali nomi vale questo blocco. A ogni richiesta nginx guarda il nome richiesto dal browser (l'header Host) e sceglie il blocco corrispondente.rootè la cartella con i file,indexil file mostrato quando si richiede una cartella.try_filesprova il file richiesto, poi una cartella, e altrimenti restituisce un 404. Senza una riga del genere, una configurazione sbagliata può mostrare più di quanto vorrebbe.- File di log propri per ogni sito rendono le ricerche molto più semplici (lezione 6.2).
Attivi il sito, rimuova il sito predefinito, esegua il test e ricarichi:
anna@web1:~$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
anna@web1:~$ sudo rm /etc/nginx/sites-enabled/default
anna@web1:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
anna@web1:~$ sudo systemctl reload nginx
anna@web1:~$ curl -I http://example.com
HTTP/1.1 200 OKFaccia di nginx -t un'abitudine fissa prima di ogni reload. In caso di errore indica quale file e quale riga, e il sito in esecuzione resta intatto. Se riavvia senza testare, nginx con un errore non si avvia più e tutti i Suoi siti vanno offline (lezione 6.1).
Il default server: che cosa riceve un nome sconosciuto?
Che cosa succede se qualcuno interroga il Suo server con un nome che non compare in nessun server_name, o semplicemente con l'indirizzo IP? In quel caso nginx sceglie il default server: il blocco con default_server dopo listen, oppure il primo blocco che ha incontrato. Se non ci pensa, si tratta quindi di uno dei Suoi siti reali.
È più ordinato un blocco separato che rifiuta queste richieste:
# /etc/nginx/sites-available/000-default
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}444 è un codice speciale di nginx: la connessione viene chiusa senza risposta. Gli scanner che passano in rassegna gli indirizzi IP non vedono così nulla. Per https (porta 443) un default server funziona in modo un po' diverso, perché richiede un certificato; ci torneremo nella lezione 7.3.
nginx come reverse proxy
Se un'applicazione gira su 127.0.0.1:3000 (lezione 6.3) o un container su 127.0.0.1:3001 (lezione 9.3), nginx la rende accessibile dall'esterno:
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}Le quattro righe proxy_set_header sono importanti. Senza Host l'applicazione non sa con quale nome viene visitata. Senza X-Forwarded-For l'applicazione vede ogni visita provenire da 127.0.0.1 (il proxy) invece che dall'indirizzo reale del visitatore. Senza X-Forwarded-Proto l'applicazione pensa che tutto passi via http e a volte crea link o cookie per http, mentre il Suo sito funziona in https. Molte applicazioni hanno un'impostazione per fidarsi di questi header ("trusted proxy"); vi inserisca solo 127.0.0.1, altrimenti qualsiasi visitatore può inviare un indirizzo falso.
Le applicazioni che usano i websocket (aggiornamenti in tempo reale, come Uptime Kuma) hanno bisogno di altre due righe: proxy_http_version 1.1; e l'inoltro di Upgrade e Connection. La documentazione dell'applicazione di solito indica esattamente quali.
Permessi della webroot
Su Debian e Ubuntu nginx esegue i suoi processi di lavoro come utente www-data. Questo utente deve poter leggere i Suoi file, ma non deve poterli scrivere. Una buona impostazione (lezione 3.1):
anna@web1:~$ sudo chown -R anna:www-data /var/www/example.com
anna@web1:~$ sudo find /var/www/example.com -type d -exec chmod 750 {} \;
anna@web1:~$ sudo find /var/www/example.com -type f -exec chmod 640 {} \;Lei (anna) gestisce i file, il gruppo www-data può leggere, tutti gli altri nulla. Se il sito deve scrivere da qualche parte, ad esempio in una cartella per gli upload, dia i permessi di scrittura per www-data solo a quella cartella. Mai chmod 777 (lezione 10.2). Se riceve un 403 Forbidden, guardi nel log degli errori del sito: lì troverà permission denied con il percorso.
Alcune altre buone abitudini:
- Nessun segreto nella webroot. Backup (
site.zip), file.enve cartelle.gitnon devono trovarsi lì; se vi finiscono per errore, chiunque può scaricarli. Una rete di sicurezza in più:location ~ /\. { deny all; }blocca tutti i file che iniziano con un punto (tranne ciò che consente esplicitamente, come/.well-known/, vedere le lezioni 7.3 e 7.4). - Nascondere la versione.
server_tokens off;innginx.conftoglie il numero di versione dall'headerServere dalle pagine di errore. Non è una vera protezione, ma fornisce meno informazioni agli scanner.
PHP, in breve
Per i siti PHP (come WordPress) nginx comunica con PHP-FPM, un servizio separato. Su Debian installi php-fpm e nel server block inserisca un blocco location ~ \.php$ con include snippets/fastcgi-php.conf; e fastcgi_pass unix:/run/php/php8.4-fpm.sock; (il numero di versione varia a seconda della release). Il corso su WordPress approfondisce questo argomento.
Su AlmaLinux e Rocky Linux
Lì non esiste sites-available: ogni sito va in un file proprio in /etc/nginx/conf.d/<naam>.conf. nginx gira come utente nginx invece di www-data, e la webroot predefinita è /usr/share/nginx/html. Per impostazione predefinita SELinux non consente a nginx di connettersi a un'applicazione dietro proxy_pass; lo abiliti con setsebool -P httpd_can_network_connect 1. I file al di fuori delle cartelle consuete richiedono un'etichetta SELinux (semanage fcontext e restorecon).
Riepilogo
- nginx serve file oppure, come reverse proxy, inoltra le richieste a un'applicazione su
127.0.0.1. - Un server block per sito in
sites-available, da attivare con un collegamento insites-enabled; ascoltare sia su80sia su[::]:80. - Sempre
nginx -tprima disystemctl reload nginx. - Un default server proprio con
return 444evita che un nome sconosciuto o il semplice indirizzo IP mostri uno dei Suoi siti. - Come reverse proxy si inoltrano
Host,X-Forwarded-ForeX-Forwarded-Proto; la webroot è leggibile perwww-data, non scrivibile, e senza segreti.
Quiz
Esercizio
Esercizio O7.2: Il Suo primo sito. Installi nginx (oppure usi Caddy della lezione 7.4) e crei un server block per un (sotto)dominio che punta al Suo server, con listen per IPv4 e IPv6, file di log propri e un default server proprio. Esegua il test con nginx -t, ricarichi e verifichi con curl -I via IPv4 e IPv6. Imposti i permessi della webroot come nella lezione. Compili la checklist e incolli il Suo server block.
Esercizio O7.2: Il Suo primo sito
Questo esercizio lo svolge da sé; nessuno lo verifica. Spunti ciò che ha fatto e segni l'esercizio come completato.
Sull'IP nudo nulla (connessione chiusa) o una pagina neutra, mai il sito di un cliente. Solo una cartella di upload scrivibile da www-data, il resto in sola lettura. Dietro un proxy: Host, X-Real-IP, X-Forwarded-For e X-Forwarded-Proto.
Le Sue spunte e note restano solo in questo browser; non le inviamo da nessuna parte. Se ha effettuato l'accesso, conserviamo in I miei corsi solo il fatto che ha svolto l'esercizio.
Per approfondire
- Vietato (403): non ha i permessi per accedere a / su questo server
- Documentazione di nginx, How nginx processes a request (server_name e default server): https://nginx.org/en/docs/http/request_processing.html
- Documentazione di nginx, Beginner's Guide: https://nginx.org/en/docs/beginners_guide.html
- Documentazione di nginx,
ngx_http_proxy_module: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
