Installare NGINX da sorgenti

Come ben sapete, il bello del software libero e open source è la possibilità di accedere al codice sorgente dei programmi per studiarli, analizzarli ed eventualmente modificarli per correggere errori, aggiungere nuove funzionalità o adattarli a piattaforme diverse da quelle previste. Un altro vantaggio è quello di poter installare questi programmi compilando il codice sorgente per personalizzarne l’installazione ed ottimizzarli per la propria piattaforma hardware. Nel caso dei sistemi operativi basati su Linux, tuttavia, grazie al gran lavoro svolto da chi mantiene le diverse distribuzioni, la maggior parte di tutto il software di cui potreste aver bisogno è già precompilato ed installabile tramite il gestore dei pacchetti tipico delle distribuzioni. Questi pacchetti sono compilati in maniera tale da poter funzionare indifferentemente su implementazioni diverse della stessa architettura hardware, ad esempio le architetture x86 ed x86_64.

Può capitare, tuttavia, che le versioni dei software precompilati inclusi in una distribuzione non siano particolarmente aggiornati, oppure che un particolare programma non venga incluso da una certa distribuzione Linux. In questi casi, piuttosto che affidarsi a repository di terze parti non sempre affidabili, una soluzione ottimale consiste nello scaricare il codice sorgente del software di interesse e compilarlo sul proprio sistema.

In questo articolo mostrerò come sia possibile compilare ed installare da sorgenti il server web NGINX. Questo software è generalmente incluso nei repository di tutte o quasi le maggiori distribuzioni Linux ma, talvolta, non è in linea con l’ultima versione rilasciata dagli sviluppatori. NGINX tuttavia mette a disposizione i suoi repository contenenti i pacchetti binari aggiornati, ma questi repository non sono disponibili per tutte le distribuzioni possibili e coprono solo le principali architetture hardware.

L’esempio su cui baso questo articolo è infatti relativo all’installazione di NGINX su un sistema Raspberry Pi OS (precedentemente noto come Raspbian) installato su un Raspberry Pi 3; questo sistema prevede nei suoi repository ufficiali la versione 1.14.2 di NGINX, mentre l’ultima release ufficiale del ramo “mainline” è, al momento in cui scrivo, la 1.19.1. Come prevedibile, i repository ufficiali di NGINX non offrono una versione precompilata per questo sistema, pertanto provvederemo ad installarla da sorgenti.

Preparazione

Per compilare NGINX da sorgenti abbiamo bisogno sostanzialmente di due cose: i sorgenti di NGINX, ovviamente, e l’occorrente per compilarli, ovvero un compilatore e le librerie di sviluppo su cui si appoggia NGINX. Per quanto riguarda i sorgenti, ci basta scaricare e scompattare nella nostra home directory (o dove preferite) l’archivio compresso direttamente dal sito web di NGINX.

wget https://nginx.org/download/nginx-1.19.1.tar.gz
tar xzvf nginx-1.19.1.tar.gz

Per quanto concerne compilatore e librerie, la cosa è un po’ meno banale, anche perché le librerie necessarie cambiano in funzione delle opzioni di compilazioni che vogliamo utilizzare, ad esempio per includere particolari moduli o attivare determinate feature del programma che andiamo a compilare. Il minimo indispensabile che ci occorre, su distribuzioni Debian-based come Raspbian, si può ottenere installando il metapacchetto build-essential, che è un pacchetto che dipende da tutti quei pacchetti necessari per “costruire” pacchetti Debian da sorgenti:

sudo apt-get install build-essential

Sul mio Raspberry Pi appena installato, tuttavia, questo pacchetto risulta già presente, quindi non c’è nulla da installare.

Per quanto concerne le dipendenze possiamo procedere col classico metodo trial and error, ovvero proviamo ad eseguire lo script di configurazione di NGINX e vediamo cosa ci manca in base agli errori segnalati.

cd nginx-1.19.1
./configure

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using –without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using –with-pcre= option.

Una prima cosa che manca, dunque, è la libreria PCRE necessaria al modulo HTTP rewrite. Potremmo anche farne a meno, specificando l’opzione --without-http_rewrite_module, ma questo modulo ci fa comodo, quindi installiamo questa libreria e riproviamo lo script di configurazione:

sudo apt install libpcre3 libpcre3-dev
./configure

Ora lo script dovrebbe andare a buon fine e permetterci di compilare NGINX con le impostazioni di default. Tuttavia l’output dello script configure ci mostra un configuration summary che dice:

Configuration summary
  + using system PCRE library
  + OpenSSL library is not used
  + using system zlib library

Questo riassunto ci informa che, procedendo con la compilazione, il nostro NGINX non farà uso della libreria SSL e quindi, banalmente, non potrà fornire contenuti su HTTPS. A noi questa funzione farebbe comodo, quindi dobbiamo specificare che vogliamo attivarla e quindi dovremo anche installare le corrispondenti librerie di sviluppo. Per avere un elenco di tutte le opzioni di configurazione che è possibile usare, è sufficiente passare il flag --help allo script di configurazione:

./configure --help

Per quel che riguarda ssl, l’opzione di nostro interesse è --with-http_ssl_module (enable ngx_http_ssl_module), ma se tentiamo di usarla senza aver installato le librerie necessarie otteniamo un errore:

./configure --with-http_ssl_module

./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using –with-openssl= option.

Correggiamo questo problema con:

sudo apt-get install libssl-dev

e riproviamo nuovamente la configurazione:

./configure --with-http_ssl_module

Ora la configurazione dovrebbe andare a buon fine e restituire il seguente summary:

Configuration summary
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

Compilazione

Oltre alle informazioni sulle librerie utilizzate, questo summary mostra altri dettagli di configurazione interessanti, che possiamo eventualmente modificare passando le opportune opzioni allo script di configurazione. La maggior parte di queste informazioni sono relative al posizionamento di alcuni file, ad esempio i file binari, i file di configurazione o i file di log. Questi valori sono accettabili nella maggior parte dei casi, ma potrebbe essere necessario modificarli per adattare l’installazione al proprio ambiente. Nel mio caso, ad esempio, voglio che NGINX venga eseguito con i privilegi di un utente e un gruppo particolari, ovvero www-data; questa opzione si imposta tramite i flag --user e --group. Un’altra opzione che voglio usare è quella che abilita il modulo http2, ovvero --with-http_v2_module. Tutte le opzioni di configurazioni e le informazioni sui vari moduli disponibili le trovate nella documentazione ufficiale di NGINX all’indirizzo https://nginx.org/en/docs/configure.html. Ricapitolando, il comando di configurazione che vado ad eseguire sul mio sistema sarà:

./configure --with-http_ssl_module --with-http_v2_module --user=www-data --group=www-data 

Va da sé, comunque, che in caso volessimo successivamente cambiare opzioni di compilazione la cosa è piuttosto semplice e si limita a ripetere lo script di configurazione prima di ricompilare nuovamente il software. Siamo ora pronti ad eseguire la compilazione vera e propria col comando make:

make

prendendo nota di eventuali errori di compilazione. La durata del processo di compilazione varierà in funzione della potenza del sistema sul quale la state eseguendo. Terminata la compilazione, installiamo il software sul sistema con il comando make install:

sudo make install

Verifichiamo che il comando binario funzioni correttamente:

/usr/local/nginx/sbin/nginx -V

nginx version: nginx/1.19.1
built by gcc 8.3.0 (Raspbian 8.3.0-6+rpi1)
built with OpenSSL 1.1.1d 10 Sep 2019
TLS SNI support enabled
configure arguments: –with-http_ssl_module –with-http_v2_module –user=www-data –group=www-data

Possiamo anche verificare la correttezza del file di configurazione di NGINX con:

sudo /usr/local/nginx/sbin/nginx -t

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

A questo punto possiamo avviare il server web e verificare che funzioni come atteso:

sudo /usr/local/nginx/sbin/nginx

Andando con un browser sull’ip del server su cui avete installato NGINX dovreste visualizzare la welcome page.

Se vogliamo arrestare il server, dobbiamo inviare il segnale di stop con il comando:

sudo /usr/local/nginx/sbin/nginx -s stop

Altri dettagli su come utilizzare il comando nginx li potete ottenere tramite l’opzione -h:

/usr/local/nginx/sbin/nginx -h

Unit systemd

Ora che il software è correttamente installato e funzionante con una configurazione di default, vogliamo fare in modo di controllarlo tramite il gestore dei servizi di sistema. Il service manager di default della maggioranza delle distribuzioni moderne è systemd, pertanto vediamo come configurare una service unit systemd per avviare, arrestare, riavviare o ricaricare la configurazione del servizio. Con systemd possiamo anche decidere se attivare il servizio all’avvio del sistema oppure no. Un esempio di service unit per NGINX la troviamo sul sito nginx.com (https://www.nginx.com/resources/wiki/start/topics/examples/systemd/):

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Ovviamente alcune delle opzioni sono state adattate alla nostra installazione. Salviamo questo file in /etc/systemd/system/nginx.service e poi eseguiamo:

sudo systemctl daemon-reload

A questo punto possiamo utilizzare questa service unit per controllare NGINX:

sudo systemctl start nginx.service
sudo systemctl status nginx.service
sudo systemctl reload nginx.service
sudo systemctl restart nginx.service
sudo systemctl stop nginx.service

Ad esempio, dopo aver avviato il servizio, se tutto è stato fatto correttamente, interrogandone lo stato dovremmo ottenere qualcosa del genere:

Output del comando “sudo systemctl status nginx.service”

Nella situazione attuale, all’avvio del server, il servizio non viene avviato automaticamente; per fare in modo che NGINX venga avviato all’avvio del sistema è sufficiente eseguire il comando:

sudo systemctl enable nginx.service

che restituirà la seguente informazione:

Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /etc/systemd/system/nginx.service.

Conclusioni

In questo articolo ho mostrato cosa serve per avere un server web NGINX funzionante e semplice da controllare tramite l’apposita service unit, ma la configurazione installata è molto limitata e non del tutto ottimizzata. Diciamo che è un buon punto di partenza. Dedicherò un articolo successivo a spiegare in che modo gestire la configurazione del servizio, in modo tale da servire contenuti su protocollo https, permettere l’esecuzione di più siti web sullo stesso server e per servire contenuti dinamici tramite php-fpm.

Leave a Reply

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.