itaeng

Effettuare il deploy di un'applicazione Meteor.JS sul proprio server

Ho scoperto Meteor da poco e già me ne sono innamorato. Un'occhiata alla documentazione ed alle funzionalità penso sia sufficiente per capire le potenzialità di questa piattaforma quindi non intendo dilungarmi oltre. Passerò direttamente ad un aspetto successivo, cioè la pubblicazione di un'applicazione già fatta su un server raggiungibile dall'esterno, con un proprio indirizzo web (requisito necessario è avere accesso root SSH al sistema). Esistono due modi:

Metodo 1

Il primo metodo, quello più semplice e veloce, consiste nello sfruttare quello che meteor mette a disposizione cioè un hosting gratuito sui loro server, che può essere sfruttato utilizzando un sottodominio (es. ilmiosito.meteor.com) oppure, impostando i corretti parametri nel pannello di controllo del proprio hosting, con un dominio personale. Per caricare il sito è sufficiente posizionarsi nella directory di lavoro ed impartire questo comando:

meteor deploy ilmiosito.meteor.com

Et voilà. Nel giro di qualche secondo il sito è già online e funzionante a quell'indirizzo. Peccato che quell'hosting, per quanto comodo e gratuito, non sia proprio il massimo della velocità... ma niente paura c'è il

Metodo 2

Il secondo metodo consiste nell'ospitare l'applicazione su un proprio server (configurato con node.js e mongodb naturalmente). In questo caso il deploy è un decisamente più delicato e complesso, ma dopo aver sbattuto la testa in diversi modi credo di aver trovato la procedura corretta. Eccola:

Prima di tutto è necessario (o conveniente, giudicate voi in base al vostro grado di fiducia nel genere umano) configurare mongodb per non accettare le connessioni anonime. Procediamo quindi con la creazione di un utente di amministrazione su mongo:

$ mongo
MongoDB shell version: 2.6.5
​connecting to: test

> use admin
> db.createUser(
  {
    user: "amministratore",
    pwd: "password",
    roles:
    [
      {
        role: "userAdminAnyDatabase",
        db: "admin"
      }
    ]
  }
)

Fatto. Successivamente è necessario modificare il file /etc/mongodb.conf, decommentando la stringa auth=true per fare in modo che le connessioni a mongo non possano più avvenire in modo anonimo.

Fatto questo ci si ricollega a mongo con le credenziali appena inserite per creare il nuovo db:

$ mongo -u amministratore -p password --authenticationDatabase admin
> use ilmiodatabase
> db.createUser("ilmioutente", "lamiapassword")

Ok, anche questa è fatta. Abbiamo appena creato un nuovo database "ilmiodatabase" ed il relativo utente con accesso in lettura e scrittura. 

Dopodiché vorremo importare il database che usavamo nella piattaforma di sviluppo, giusto? Per fare questo è sufficiente impartire questo comando (meteor deve essere avviato):

mongodump -h 127.0.0.1 --port 3001 -d meteor

Questo creerà una directory dump/meteor che contiene i files del database. Carichiamoli sul server tramite FTP o lo strumento preferito, e poi importiamoli:

mongorestore -h localhost --port 27017 -u ilmioutente -p lamiapassword -d ilmiodatabase cartella/dei/dump

Fatto? Bene, ormai ci siamo quasi. Ora passiamo ai files. Prima di tutto dobbiamo fare il build del sistema, quindi ci posizioniamo nella directory di sviluppo e diamo:

meteor build build

Questo comando creerà un pacchetto minifizzato, concatenato e quant'altro del nostro sito, mettendolo in formato compresso con tar.gz dentro la cartella "build". Ora possiamo prendere questo file, caricarlo sul server e scompattarlo. Fatto questo, è necessario installare le dipendenze di npm:

(cd programs/server && npm install)

A questo punto possiamo finalmente far partire il sito! Scherzavo :). Prima bisogna specificare i parametri di connessione. Questo passaggio è necessario ogni volta che si fa partire il server, ovviamente è possibile creare uno script di avvio per velocizzare questo passaggio:

export MONGO_URL='mongodb://ilmioutente:lamiapassword@localhost:27017/ilmiodatabase'
export ROOT_URL='http://www.ilmiositoweb.ext'
export PORT=3100

Ed infine...

node main.js

Et voilà! Il sito è ora raggiungibile all'indirizzo http://www.ilmiositoweb.ext:3100. Comodo vero? In effetti non molto, ma una volta capiti i passaggi non è poi una questione così complicata :)

Un'ultima cosa: probabilmente non è la scelta più comune quella di avere un dominio raggiungibile sulla porta 3100, ma è naturalmente possibile far girare il sito sulla normale porta 80 con alcuni trucchetti. Nel mio caso, avendo apache che occupa la porta 80 ho dovuto configurare un reverse proxy.

AGGIORNAMENTO

Siccome configurare un reverse proxy può non essere banale, aggiungo i passaggi che ho seguito per attivarlo (questo è molto utile in particolare se si vuole sfruttare la tecnologia del WebSocket, che con meteor è attiva di default).

Prima di tutto è necessario installare alcuni moduli di apache:

sudo a2enmod proxy proxy_http proxy_wstunnel

Poi bisogna creare un VirtualHost un po' personalizzato, che contiene la porta su cui risponde il server node ed il WebSocket:

<VirtualHost *:80 >
  ServerAdmin postmaster@ilmiositoweb.ext
  ServerName ilmiositoweb.ext
  ServerAlias *.test.local
  ServerSignature Off

  ProxyRequests off
  
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>

  <Location />
    ProxyPass http://localhost:3101/
    ProxyPassReverse http://localhost:3101/
  </Location>

  <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
    RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
    RewriteRule .* ws://localhost:3101%{REQUEST_URI} [P]
  </IfModule>

</VirtualHost>

Et voilà... con un riavvio del server apache dovrebbe essere tutto a posto!

AGGIORNAMENTO 2

Piccola precisazione: il metodo sopra indicato per attivare il websocket tramite proxy di apache funziona esclusivamente su apache 2.4 e successive versioni, mentre non è disponibile su apache 2.2 o precedenti. Nel caso in cui non sia possibile attivare websocket ma sia comunque necessario utilizzare il proxy potrebbe essere conveniente disattivare WS esportando questa regola prima di lanciare node:

export DISABLE_WEBSOCKETS=true