Sommario
< Home
Stampa

Deploy di applicazioni server NodeJs

Introduzione

Rendere pubblico il proprio software è quindi il punto di arrivo di qualsiasi sviluppo. Infatti, anche se è gratificante vedere funzionare la propria applicazione web Service NodeJs, metterla online è un’alra cosa. Significa dare visibilità pubblica e mostrare il proprio elaborato anche al mondo esterno. Cosa che per uno studente è un obiettivo molto gratificante, e da una dimostrazione concreta delle capacità raggiunte ad un pubblico esterno (anche come portfolio professionale).

Inoltre eseguire un deploy su un server reale è una competenza che oggi è necessario avere, con l’avvento delle metodologie agili e soprattutto di DevOps.

Obiettivi di questa lezione

In questa lezione andremo a vedere le attività di configurazione e gestione del deploy di una applicazione NodeJs e nello specifico un Web Server/Web service. L’obiettivo è di rendere disponibile l’applicazione su un proprio dominio a scelta, con i protocolli di sicurezza attivi, mediante un processo di deploy basato su DevOps.

Questa attività quindi prevede il costo dell’acquisto di un dominio e di una VPS (Virtual Private Server) con indirizzo IP pubblico con sistema operativo Linux (server), come vedremo esistono soluzioni dal costo irrisorio, del tutto adatte per progetti piccoli non commerciali.

Qui di seguito l’elenco degli argomenti, come recap iniziale.

  • prerequisiti
  • attività preliminari
  • accesso al server
  • installazione toolchain
  • deploy con git e configurazione
  • Esecuzione dell’applicazione lato server
  • Proxypass e HTTP
  • dominio di terzo livello
  • Server permanente
  • Ciclo di rilascio

Prerequisiti

I prerequisiti sono i seguenti:

  • avere installato nodeJs, npm e librerie relative;
  • utilizzo di VS Code come ambiente di sviluppo (non necessaria ma fortemente raccomandata);
  • applicazione NodeJs webService/webServer funzionante sul proprio pc;
  • l’applicazione deve essere presente su repository git pubblicamente raggiungibile (ad esempio su Github o Bitbucket o Gitlab); le configurazioni restano private.
  • sistema operativo Windows: accesso shell con git-bash (presente nel pacchetto di Git per Windows) oppure (meglio) tramite WSL (https://learn.microsoft.com/en-us/windows/wsl/install )
  • Sistema operativo Linux e Mac: nessun prerequisito ulteriore.

Attività preliminari

Per poter pubblicare su un server bisogna acquistare un server (anche VPS) con IP pubblico e relativo nome di dominio. Esistono numerosi servizi di costo irrisorio (ad oggi anche 1-2 euro / mese), il requisito della VPS è di avere 512MB di Ram e almeno 10GB di spazio disco (SSD). Se si intendono installare più applicazione sono raccomandati almeno 1-2 GB. Su questa macchina dovrà essere installata una distribuzione Linux, in questa guida useremo Ubuntu server, una delle più diffuse. Inoltre è necessario che il servizio acquistato renda disponibile l’accesso al pannello della modifica DNS (per i domini di terzo livello).

Le istruzioni per l’acquisto e la configurazione della macchina sono lasciate allo studente, di solito è una procedura web automatica, fare una ricerca su web o chiedere al docente per suggerimenti.

Al termine della procedura si dovranno avere a disposizione le seguenti informazioni:

  • nome dominio (useremo il nome fittizio mioserver.it)
  • indirizzo IP pubblico (useremo l’indirizzo fittizio 1.1.1.1)
  • accesso root e password per SSH.
  • url del pannello di controllo per il DNS (ad esempio Plesk o cPanel)
  • possibilità di generare una coppia di certificati (key/cer) riconosciuta dalle principali CA.

Normalmente il DNS del dominio acquistato ci mette qualche ora ad essere propagato, si può sempre usare l’indirizzo IP.

Accesso al server

Accedere al terminale del proprio computer (git-bash, bash o zsh) e digitare:

ssh root@1.1.1.1

Se tutte le procedure precedenti sono andate a buon fine, il sistema chiederà la password, e se corretta si entrerà via SSH al terminale sul server. Bene.

A questo punto è necessario sicurizzare l’accesso SSH. Il tipo di accesso che abbiamo fatto ora (chiamato interattivo) è poco sicuro ed è facilmente attaccabile da un bot che poi può prendere controllo del vostro server. Per impedirlo dobbiamo attivare l’accesso SSH mediante la creazione di una copia di chiavi RSA.

Uscire dal server remoto (exit) e digitare

cd ~
ssh-keygen

Premere sempre invio a tutte le domande. Al termine verrà creata una cartella .ssh (nella propria home). Dentro questa cartella saranno presenti due file (id_rsa e id_rsa.pub) chiave privata e pubblica (il principio di funzionamento della crittografia asimmetrica è fuori dall’ambito della presente lezione). A questo punto bisogna copiare la chiave sul server remoto:

ssh-copy-id root@1.1.1.1

digitare la password e la chiave è copiata.

Testiamo il funzionamento con

ssh root@1.1.1.1

Se non ci chiede la password, siamo entrati con la chiave RSA. Se non funziona, abbiamo sbagliato procedimento. Va ricordato che questa procedura va effettuata per ogni pc che si usa per accedere al server (è possibile registrare più chiavi pubbliche).

Ora dobbiamo eliminare l’accesso tramite password. Sempre sul server remoto digitare

nano /etc/ssh/sshd_config

Si aprirà la configurazione di SSH. Cercare la stringa “PasswordAuthentication” ed impostarla a NO.

PasswordAuthentication NO

salvare (ctr-x e poi y).

Eseguire

sshd restart

Adesso non si entra più sul server senza chiave RSA.

Facciamo attenzione a questo passaggio ed alle sue conseguenze: se perdiamo la coppia di chiavi RSA perdiamo l’accesso al server!

Installazione Toolchain sul server

Gli strumenti necessari per l’esecuzione lato server sono node, npm, git, pm2 (runtime per mantenere attivo il processo node), nginx (web server per la gestione del proxypass). Qui le istruzioni per installarli

apt update
apt install nodejs
apt install npm
apt install git
npm install pm2 -g
apt install nginx

Si ricorda che queste operazioni vanno effettuate con utenza root. Useremo questi tool nelle sezioni successive.

Deploy con git e configurazione

Prendiamo un progetto Web Application server NodeJs funzionante (ad esempio questo ) che avremo preventivamente salvato su un repository git pubblico (es. Github). Come accorgimento ricordiamoci di configurare per il server web una porta diversa dalla 80, in questo esempio useremo la 5050.

Effettuiamo un accesso al server e creiamo la nostra cartella di lavoro.

cd /var/www
mkdir node

A questo punto eseguiamo il clone del progetto:

git clone urlToMyProject myproject
cd myproject

Al termine del clone verrà creata la cartella myproject. Usciamo dal server (exit).

A questo punto è necessario predisporre le configurazioni necessarie per il funzionamento dell’applicazione sul server.

Il server è a tutti gli effetti un ambiente di produzione, che va quindi distinto dall’ambiente di sviluppo. Come abbiamo visto nella lezione sugli ambienti ogni ambiente di esecuzione ha una sua propria configurazione di esecuzione. Per fare questo creiamo nel nostro progetto locale una nuova configurazione che chiameremo prod.conf.json per distinguerla dalla configurazione locale (conf.json).

A seconda del progetto la configurazione di produzione potrebbe essere una copia di quella locale o potrebbe variare per alcune voci (ad esempio password di accesso, folder dove salvare i dati, o altro). In ogni caso è fondamentale avere due file distinti, anche se identici.

Una volta pronti avremo, ad esempio nella root di progetto, un file prod.conf.json.

A questo punto possiamo copiare il file col seguente comando:

scp prod.conf.json root@1.1.1.1:/var/www/node/myproject/conf.json

Come si può vedere il file viene copiato E rinominato in “conf.json”. L’applicazione in esecuzione sul server infatti si aspetta (e si deve aspettare) un file di configurazione “conf.json”.

Possiamo copiare questo comando in un comodo script:

echo "scp prod.conf.json root@1.1.1.1:/var/www/node/myproject/conf.json" > copyconf.sh
chmod +x copyconf.sh

Queste istruzioni creano uno shell script che eseguirà l’upload della configurazione ogni volta in cui sarà necessario.

Eseguirlo:

./copyconf.sh

Se è tutto corretto, il file verrà uploadato sul server.

Esecuzione del server

E arrivato il momento di cominciare a vedere se tutto funziona. Effettuiamo l’accesso con ssh al server e ci portiamo nella cartella del progetto e lo eseguiamo:

cd /var/www/node/mypproject
node server.js

Se ci portiamo poi col browser su http://mioserver.it:5050 tutto dovrebbe funzionare?

Probabilmente no. Dobbiamo fare i conti con le regole di sicurezza del firewall in generale sui server pubblici sono aperte solo alcune porte standard (21, 22, 80, 443) non qualsiasi porta. Ma se vogliamo fare un test andiamo nel pannello di controllo del servizio VPS (di solito Plesk o cPanel) ed apriamo la porta 5050 al traffico in ingresso.

Se tutto è configurato correttamente, complimenti, avete installato la vostra prima applicazione pubblica.

Bene, speriamo non abbiate giò aperto lo champagne. Questo era solo uno “smoke test”.

Ora potete richiudere la 5050 e passiamo alla fase successiva. Non chiudere il terminale con SSH ma aprirne un altro.

Proxypass e HTTPS

Il protocollo HTTPS è necessario per dare un server sicuro, affidabile e professionale agli utenti della nostra Web Application. I rischi di sicurezza, legati a phishing, malware ed intrusioni man-in-the midlle sono tali da rendere impraticabile una qualsiasi soluzione ad accesso pubblico senza HTTPS.

Questo protocollo attiva una connessione SSL/TLS criptata sopra la connessione HTTP, garantendo sia riservatezza (i dati sono criptati) che l’autenticazione del server (evitando quindi il problema del phishing).

La URL del server viene cioè validata dal browser che controlla che effettivamente la connessione SSL/TLS sia con un server effettivamente proprietario del dominio ed in possesso di un certificato valido tramite una CA riconosciuta dal browser. Senza un certificato valido il browser da un messaggio di Warning indicando che il “sito non è sicuro” e scoraggiando l’accesso se non a proprio rischio e pericolo.

E’ quindi necessario configurare una connessione HTTPS con un certificato valido ottenuto da una CA. Questo tipo di certificati si possono ottenere in due modi:

  • dal provider da cui si è acquistato il dominio (molti registrar offrono il servizio nel pacchetto acquistato) che provvede a fornire il certificato tramite una CA riconosciuta;
  • direttamente da una CA, che normalmente offre questo servizio a pagamento. Esiste ad oggi comunque una CA che offre certificati gratuitamente, si chiama Let’s Encrypt (https://letsencrypt.org/it/)

In questa lezione diamo per assodato che l’utente si sia quindi procurato il certificato, ovvero una coppia di file costituito da una chiave privata (file .key) ed una pubblica (file .cer oppure .pem). Nota bene: i certificati devono autenticare sia il dominio di secondo livello che quelli di terzo livello, ovvero devono certificare *.mioserver.it . Questi file vanno copiati in una cartella del progetto e considerati come deliverable di tipo “asset” (quindi non vanno messi su git). In questa lezione ipotizzeremo che i due files siano memorizzati così:

  • {projectroot)/assets/certificate.key
  • {projectroot)/assets/certificate.pem

I due files vanno copiati con scp come visto per le configurazioni:

scp certificate.key root@1.1.1.1:/var/www/node/myproject/assets/certificate.key
scp certificate.pem root@1.1.1.1:/var/www/node/myproject/assets/certificate.pem

A questo punto possiamo configurare il proxypass. Un proxy web è un tipo di server web che fa da intermediario tra le richieste del client e il server vero e proprio. Il client si connette al server proxy che a sua volta gira la richiesta (in base alla URL) al server web vero e proprio, che può trovarsi nella stessa macchina o in altra macchina, in modo invisibile per il client. I proxy sono alla base dei bilanciatori (visti nell’architettura 3-tiers vista qui, in questo caso il proxy invia le richieste ai server web del cluster in modo bilanciato dividendo il carico di lavoro tra più nodi), possono essere alla base delle cache frontend (quelle che memorizzano una copia della pagina richiesta in modo veloce) o possono anche gestire la sicurezza, come per esempio i certificati TLS.

Con l’ausilio di Nginx creeremo proprio un proxy di questo tipo, senza quindi doverci preoccupare di modificare l’applicazione NodeJs per gestire i certificati SSL/TLS (cosa che è possibile fare ma che rende inutilmente complicata la gestione del software che ricordiamo deve poter girare sia in ambienti https che http in locale). Con Nginx configuriamo un proxypass, ovvero un server proxy che svolge in modo del tutto trasparente le richieste-risposte verso il server Node. In sostanza l’architettura che andiamo a disegnare è questa:

Nginx è un web server engine che consente di creare più web server (per la precisione dei Virtual Host) tramite configurazione e può girare su Linux come servizio. E’ gestito tramite file di configurazione nella cartella /etc/nginx e prevede un file di configurazione principale (httpd.conf) e dei file secondari nella cartella /sites-enabled. E’ fuori dagli obiettivi di questa lezione spiegare come configurare nginx, ci limitiamo a utilizzare il file di configurazione di default creando i nostri Virtual Host proxypass.

Nota: siccome le porte 80 e 443 saranno utilizzate da Nginx, dobbiamo modificare (se non lo abbiamo già fatto) l’applicazione NodeJs perché eroghi il web server su una porta diversa (consigliato valore > 5000). Ipotizzeremo quindi di aver eseguito il deploy dell’applicazione Node e che questa sia in esecuzione sulla porta 5050.

La configurazione è realizzabile nel seguente modo. Accediamo in SSH al server e poi digitiamo:

cd /etc/nginx/sites-enabled
nano default

Ora che siamo nell’editor, cancelliamo il contenuto ed inseriamo il seguente testo:

server {
        listen 80;
        listen 443 ssl;
        server_name mioserver.it;
        ssl_certificate     /var/www/node/myproject/assets/certificate.pem;
        ssl_certificate_key /var/www/node/myproject/assets/certificate.key;

        location / {
                proxy_pass http://localhost:5050;
        }
}

Usciamo (ctr-x e poi y) e riavviamo il servizio nginx.

service nginx restart

Andiamo su https://mioserver.it e se funziona tutto, il proxy gira le chiamate a Node, e Node risponde al proxy che a sua volta risponde al client.

Adesso si che potete aprire lo champagne

DNS e domini di terzo livello

Se vogliamo dare una veste ancora più professionale è possibile creare un dominio di terzo livello (i domini di primo livello sono i .it, com, .net, ecc. i domini di secondo livello sono mioserver.it, google.com, ecc.). I domini di terzo livello sono sempre sottodomini di domini di secondo livello, nel nostro caso vogliamo creare il dominio todolist.mioserver.it e farlo puntare alla nostra applicazione.

Per aggiungere un dominio di terzo livello al DNS bisogna ancora una volta tornare al pannello di controllo della vostra VPS (di solito Plesk o cPanel) e accedere alla gestione DNS. Vedremo un elenco di configurazioni, dette record DNS, e per ognuna sono previsti 3 valori:

  • un nome di host (secondo o terzo livello)
  • un tipo di record (i valori possibili sono CNAME, TXT, A, SRV, MX, ecc.)
  • il valore a cui si riferisce (cioè a cui punta)

A noi interessa creare un nuovo dominio di tipo A, che connette un nome host ad un indirizzo IP.

Per fare questo aggiungeremo un record con queste caratteristiche:

  • Nome host: “todolist.cipiaceinfo.it”
  • Record: A
  • Valore: 1.1.1.1

(come sempre ricordarsi di mettere i valori reali)

Salvare ed aspettare che si propaghi su Internet.

A questo punto torniamo alla configurazione del virtual host nginx e la modifichiamo nel modo seguente:

server {
        listen 80;
        listen 443 ssl;
        server_name todolist.mioserver.it;
        ssl_certificate     /var/www/node/myproject/assets/certificate.pem;
        ssl_certificate_key /var/www/node/myproject/assets/certificate.key;

        location / {
                proxy_pass http://localhost:5050;
        }
}

Fatto.

Server permanente

Il server così creato non è permanente. L’applicazione Node si disattiva una volta che usciamo dal terminale SSH.

Per renderlo permanente usiamo l’applicazione pm2 che avevamo già installato.

Per rendere permanente l’esecuzione è sufficiente eseguire

pm2 start server.js

Ciclo di rilascio

Riassumiamo quindi le attività da svolgere per un rilascio successivo al primo.

  1. Eseguire commit e push.
  2. Fare accesso SSH al server e posizionarsi nella cartella del progetto.
  3. Stoppare l’applicazione node esistente
pm2 stop 1

(questa istruzione esegue lo stop dell’applicazione NodeJs, se ce n’è più di una attiva leggere la guida di pm2).

4. Eseguire pull con git

5. Modificare le configurazioni se necessario.

6. Rieseguire il server:

pm2 start server.js