In questo articolo vedremo il procedimento passo passo per fare il deploy di un'app Nodejs su un server, renderla sicura con un certificato SSL gratuito e infine punteremo un dominio alla nostra app.
In questo esempio utilizzerò un server Digital Ocean, ma sono presenti molti servizi simili come Vultr o Linode che sono ugualmente validi.
Dato che nel server è presente un utente root - che ha potere di vita e di morte all'interno del server stesso - è buona regola disabilitare l'accesso a questo utente; dobbiamo quindi precedere alla creazione di un nuovo utente che ci permetta di eseguire le operazioni di cui abbiamo necessità.
Il primo passo è quello di collegartci via SSH al server:
ssh root@indirizzo_server
Una volta all'interno del server possiamo procedere alla creazione del nuovo utente con il comando:
# Inserire un nome a scelta per lo user
adduser fabio
Verrà richiesta una password, assicuriamoci di ricordala in quanto ci servirà in seguito e alcuni dati opzionali. A questo punto possiamo assicurarci che l'utente sia stato effettivamente creato utilizzando il comando id, da cui otterremo un risultato simile a questo:
root@Ubuntu22:~# id fabio
uid=1001(fabio) gid=1001(fabio) groups=1001(fabio)
Ora possiamo procedere ad inserire l'utente appena creato nel gruppo sudo
usermod -aG sudo fabio
Il passo successivo è l'aggiunta della chiave SSH per il nuovo utente che ci permetterà di eseguire l'accesso senza l'utilizzo della password
# Diventa il nuovo utente
su - fabio
# Crea una nuova directory
mkdir ~/.ssh
# Imposta i permessi di accesso alla cartella
chmod 700 ~/.ssh
# Crea un file per le chiavi SSH e apre l’editor nano
nano ~/.ssh/authorized_keys
All'interno del file andiamo ad inserire la nostra chiave pubblica e salviamo premendo control+x seguito da y e dal tasto invio.
# Imposta i permessi di accesso al solo utente
chmod 600 ~/.ssh/authorized_keys
# Torna ad essere utente root
exit
Dal passaggio precedente dovremmo essere loggati nel server come utente root, testiamo che il nuovo utente possa accedere al server:
# Usciamo dal server
exit
# Logghiamoci come nuovo utente
ssh fabio@indirizzo_server
Nota: Se la chiave SSH del nostro PC non si trova nel percorso di default (~/.ssh ) o se ha un nome diverso da id_rsa, dobbiamo specificare sia il percorso che il nome della chiave privata affinchè il collegamento funzioni
ssh -i ~/percorso/nome_file_chiave_privata fabio@indirizzo_server
Possiamo ora procedere a disabilitare il login come root e l'accesso con la password:
sudo nano /etc/ssh/sshd_config
All'interno di questo file cerchiamo le voci PermitRootLogin, PubkeyAuthentication e PasswordAuthentication e assicuriamoci di decommentarle nel caso avessero davanti il simbolo # e impostiamole come segue:
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
Salviamo il file come fatto precedentemente con contro+x, y ed invio e riavviamo il servizio SSH
# Ricarica la configurazione appena modificata
sudo systemctl reload sshd
Procediamo a questo punto a verificare che tutto funzioni; apriamo una nuova finestra del terminale e entriamo con l'utente appena creato
Non chiudere la finestra del terminale precedente o effettuare il logout. Se qualcosa non dovesse funzionare a dovere non potremmo più accedere al server.
Se ci loghiamo con il nuovo utente tutto funziona come previsto, ma se proviamo ad accedere come utente root riceviamo un messaggio di errore.
Passiamo a configurare un semplice firewall che ci consenta di permettere il traffico sulle porte HTTP (80) , HTTPS (443), permetta la connessione SSH e blocchi il resto del traffico, lanciando questa serie di comandi dalla shell:
# Abilita le connessioni OpenSSH
sudo ufw allow OpenSSH
# Abilita il traffico HTTP
sudo ufw allow http
# Abilita il traffico HTTP
sudo ufw allow https
# Attiva il firewall
sudo ufw enable
Una volta abilitato il firewall riceviamo un avviso che questo potrebbe impedirci la connessione, possiamo non preoccuparcene avendo abilitato le connessioni SSH. Possiamo ora controllare lo stato del firewall con il comando
sudo ufw status
Proseguiamo con un primo passaggio opzionale, ovvero l'installazione di htop; htop è un process viewer che una volta installato ci permette di monitorare i processi fornendoci maggiori informazioni e opzioni come la possibilità di filtrarli o di ordinarli.
sudo apt install htop
htop
Passiamo ora all'installazione di nginx lanciando i seguenti comandi:
# Aggiorna i repository dei pacchetti
sudo apt update
#Installa nginx
sudo apt install nginx
#Verifica che nginx sia attivo
service nginx status
Possiamo verificare che l'installazione sia andata a buon fine andando con il browser all'indirizzo IP del nostro server dove vedremo questa pagina:
Continuiamo andando ad installare il DBMS, nel nostro caso si tratta di MongoDB; l'installazione è molto semplice e avviene lanciando un solo comando:
sudo apt install mongodb
Una volta terminata l'installazione possiamo verificare che il servizio sia attivo
service mongodb status
Un passaggio importante è quello di verificare, lanciando il comando mongo
, che il server stia girando sulla porta 27017 con indirizzo 127.0.0.1 e assicurarci che non sia accessibile da browser all'indirizzo IP_server:27017.
A questo punto possiamo passare all'installazione di Nodejs
#Installa npm e node
sudo apt install npm
#Installa il gestore di versione di node
sudo npm i -g n
#Installa la versione 18.x di node
sudo n 18
Per prima cosa assicuriamoci che git sia installato
git --version
Nel caso non lo fosse possiamo installarlo con il comando sudo apt install git
.
Per clonare il progetto abbiamo bisogno di generare sul server le chiavi SSH; per fare questo loghiamoci diventiamo utente root e procediamo come segue:
#Diventa utente root
fabio@prova:~$ su
#Genera le chiavi SSH
root@prova:/home/fabio# ssh-keygen
#Stampa a video il contenuto del file
root@prova:/home/fabio# cat ~/.ssh/id_rsa.pub
Copiamo la chiave e aggiungiamola alle chiavi SSH di github.
Ora dobbiamo spostarci nella cartella /var/www dive andremo ad inserire il nostro progetto
root@prova:~/.ssh# cd /var/www
#Clona il progetto
root@prova:/var/www# git clone git@github.com:nome_utente/nome_progetto.git
#Entra nella cartella del progetto
root@prova:/var/www# cd nome_progetto/
#Installa le dipendenze
root@prova:/var/www/nome_progetto# npm i
#Torna utente normale
root@prova:/var/www/nome_progetto# exit
A questo punto possiamo testare che la nostra app funzioni; spostiamoci nella cartella del progetto e avviamo l'applicazione
cd /var/www/nome_progetto/
node app.js
Nel nostro esempio l'applicazione è in ascolto sulla porta 3000, apriamo quindi una nuova finestra del terminale, loghiamoci e lanciamo una request curl all'app
fabio@prova:~$ curl http://127.0.0.1:3000/
<!DOCTYPE html>
<html lang="en"> git
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
Una volta effettuata la verifica possiamo uscire da questa sessione del terminale e fermare l'applicazione con contrl+c.
Un problema in cui si può incorrere è quello nel caso in cui il server venisse riavviato, in questo caso dovremmo entrare nel server e riavviare manualmente la nostra applicazione; PM2 è un pacchetto che ci solleva da questa incombenza riavviando automaticamente l'app alla ripartenza del server.
sudo npm install -g pm2
Dalla cartella del progetto lanciamo il comando
fabio@prova:/var/www/nome_progetto$ pm2 start app.js
Per assicuraci che PM2 riavvi la nostra app il comando è
pm2 startup
che ci restituisce questo messaggio:
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u fabio --hp /home/fabio
Lanciamo il comando richiesto e salviamo
sudo env PATH=$PATH:/usr/local/bin /usr/ local/lib/node_modules/pm2/bin/pm2 startup systemd -u fabio --hp /home/fabio
pm2 save
Ora riavviando il server e lanciando nuovamente una richiesta curl vedremo che l'applicazione è stata riavviata in automatico.
Occupiamoci ora di puntare i record dns del dominio al server, per questo esempio userò un dominio acquistato su namecheap ma la stessa operazione può essere effettuata con praticamente ogni servizio che vi permetta di registrare un dominio.
Rechiamoci nella sezione dei record dns e inseriamo questi due record:
Possiamo verificare che tutto funzioni con il comando
dig +short dominio.ext
che deve restituirci l'indirizzo IP del server e
dig +short www.dominio.ext
che oltre all'indirizzo IP ci restituisce il nome dominio senza www
Adesso per rendere accessibile l'applicazione andiamo a modificare un file di nginx
sudo nano /etc/nginx/sites-available/default
Qui andiamo ad aggiungere il seguente codice nella sezione location
server_name dominio.ext www.dominio.ext;
location / {
proxy_pass http://127.0.0.1:3000; #Inserire la porta usata nell’app
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
Salviamo il file e controlliamo che non ci siano errori al suo interno
sudo nginx -t
Riavviamo infine il servizio nginx
sudo systemctl reload nginx
Ora possiamo visualizzare l'applicazione dal browser inserendo il nome dominio sia con www che senza.
L'ultimo passaggio è quello di installare il certificato SSL, per questo utilizzeremo let's encrypt che è una Certification Authority che rilascia gratuitamente certificati della durata di 90 giorni.
Per prima cosa installiamo Certbot
#Installa snapd
sudo snap install core
#Controlla che snapd sia aggiornato
sudo snap refresh core
#Rimuove certbot-auto ed ogni pacchetto certbot
sudo apt-get remove certbot
#Installa certbot con snap
sudo snap install --classic certbot
#Crea un link a certbot in usr/bin
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Installiamo ora il certificato inserendo il nome dominio e un indirizzo email valido
sudo certbot --nginx --redirect -d example.com -d www.example.com -m admin@example.it --agree-tos
Abilitiamo infine il rinnovo automatico alla scadenza del certificato
#Verifica che il timer sia attivo
systemctl list-timers | grep 'certbot\|ACTIVATES'
#Verifica che il processo di rinnovo funzioni
sudo certbot renew --dry-run
Ora la nostra app è pubblicata ed accessibile con il protocollo HTTPS.
© 2023 Fabio Angelici
P.I. 03929520124
Privacy policy Cookie policy