Los que alguna vez hayáis trasteado con NodeJS para realizar una aplicación web os habréis fijado en que hay que declarar un puerto de escucha y que para acceder a nuestra aplicación hay que usar el nombre de dominio o IP más el puerto como url en el navegador, algo así: http://127.0.0.1:3000.
Esto no pasa solo con NodeJS, sino también con otros frameworks de desarrollo web, pero como me siento cómodo usando node y no he trabajado con otros frameworks webs que no sean basados en javascript o php no puedo generalizar, así que usaré node como ejemplo, dejando claro que estas pautas pueden servir para cualquier aplicación web que nos permita manejar el puerto de escucha.

Por norma general el puerto por defecto para las aplicaciones web suele ser el puerto 80, supongamos entonces que tenemos una aplicación ocupando el puerto 80 bajo el dominio localhost, al entrar en http://localhost/ nos mostraría nuestra aplicación, pero si queremos usar el mismo servidor con otra aplicación simultáneamente deberemos de elegir otro puerto de escucha, el 3000 por ejemplo, en ese caso al entrar en http://localhost/ veremos la aplicación en el puerto 80, y al entrar en* http://localhost:3000/* veremos la otra.

No es muy bonito ¿no?, no me veo a una empresa dando su web en plan “http://pincelesybrochasmanolo.com:3000”. Entonces, ¿que hacemos?. Necesitamos un servidor que gestione las redirecciones de manera interna, de forma que al facilitarle una ruta en concreto el nos muestre la aplicación que definamos de una manera limpia para el usuario final dando igual el puerto que sea. Así podríamos tener un “hola mundo” en el puerto 3000, un chat en el 4000, y un blog en el 4500 de forma que usando rutas tipo http://localhost/chat/, http://localhost/hola/ o http://localhost/blog/ nos mostrara las aplicaciones correspondientes.

Tomando como sistema operativo ubuntu, voy a ir realizando los pasos necesarios para lograr esto, para ello solo necesitamos 4 cosas, NodeJS, NPM, Nginx y Screen.

Lo primero es instalar la ultima versión de NodeJS y NPM; abrimos un terminal y tecleamos:

sudo apt-get install python-software-properties 
sudo add-apt-repository ppa:chris-lea/node.js 
sudo apt-get update 
sudo apt-get install nodejs

Este repositorio nos facilita la ultima versión de node y de npm solo instalando el paquete nodejs, si estás exceptico y quieres comprobar que npm también se ha instalado solo tienes que realizar un npm -v en la terminal.

Si ahora creáramos dos aplicaciones que nos mostrara Hola mundo en la pantalla bajo diferentes puertos, y quisiéramos abrir ambas nos encontraríamos en que hemos de cerrar una para poder abrir otra, o abrir varias terminales, por lo que no es muy útil si tengo que tener abierta indefinidamente una sesión ssh con cada una de las aplicaciones. Para solucionar esto usaremos Screen.

sudo apt-get install screen

Screen es un emulador de terminales virtuales, viene a ser la soluciones perfecta a nuestro problema, puesto que nos permite abrir terminales para ejecutar nuestras aplicaciones y abandonar la sesión sin cerrar la terminal (virtual), dejándola en un segundo plano trabajando.
Su uso es realmente muy sencillo, con el comando “screen” en una terminal abriremos una nueva terminal virtual, trabajamos con ella de manera normal y cuando queramos dejarla en segundo plano pulsaremos la combinación de teclas control + A, y a continuación la tecla D en solitario, esto nos devolverá a la terminal inicial relegando la virtual a un segundo plano. Ahora podemos abandonar la sesión ssh sin miedo a cerrar la aplicación que tenemos en funcionamiento. Para recuperar está terminal virtual basta con teclear screen -r, si queremos cerrarla totalmente simplemente tecleamos exit en ésta y se cerrará. Si tenemos más de una terminal virtual abierta y usamos el comando screen -r nos informará de que hay varias terminales en segundo plano, y facilitándonos el numero de identificación de cada una, debemos usar screen -r [numero] para ver una en concreto. Podéis encontrar más información sobre los comandos de screen aquí http://www.guia-ubuntu.com/index.php?title=Screen.

Ahora que tenemos NodeJS, NPM, y Screen instalado queda el tema de redireccionar las rutas a puertos concretos de nuestro servidor.

Nginx será el encargado de ésta tarea. En resumen se trata de un servidor web/proxy, lo mejor para entender su potencial es dirigirnos a la información que nos facilita la wikipedia sobre el: http://es.wikipedia.org/wiki/Nginx.

Para instalarlo en nuestro Ubuntu introducimos lo siguiente en una terminal:

sudo add-apt-repository ppa:nginx/stable 
sudo apt-get update 
sudo apt-get install nginx

Una vez se ha instalado en nuestro sistema procedemos a configurarlo. Una buena idea es redireccionar los acceso al dominio sin www al que si las tiene, o viceversa, podemos hacerlo desde su fichero de configuración, para acceder a el:

sudo nano /etc/ngnix/ngnix.conf

Como verás al abrirlo la configuración esta organizada en un formato similar a JSON, buscamos en este http {} y añadimos lo siguiente:

server { 
    listen 80; 
    server_name midominiosinwww.com;
    return 301 $scheme://www.midominioconwww.com$uri; 
}

De está forma estamos indicando a los navegadores y bots que accedan a nuestro dominio (puerto 80 por defecto) que se ha redirigido de manera permanente al indicado en la linea return. Esto es cuestión de gustos, quizás no quieras la redirección, o quizás te guste más sin www o al revés, personaliza las lineas de forma que se adapten a lo que buscas.

Lo siguiente es indicar el fichero por defecto que se ha de mostrar al entrar a la raíz del dominio, para eso añadimos esto a nuesta configuración dentro de http {}:

server { 
    listen 80; 
    server_name www.midominioconwww.com;
    location / { 
        root /home/midominio;
        index index.html;
    }
}

Le estamos indicando que al entrar un usuario le sirva el fichero index.html que se encuentra en el directorio /home/midominio/ de nuestro servidor, esta podría ser nuestra Landing Page, seguimos con la redirección a nuestras aplicaciones NodeJS que están funcionando en segundo plano gracias a screen.

Añadimos dentro de esta configuración de server lo siguiente:

location /hola/ { 
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host; 
    proxy_set_header X-NginX-Proxy true; 
    proxy_pass http://localhost:3000/; 
    proxy_redirect off; 
}

Así por cada ruta que necesitemos, cambiando ésta en la linea location e indicando la dirección de la aplicación que ha de servir en la linea proxy_pass, la configuración final podría ser algo parecida a esto:

server { 
    listen 80; 
    server_name www.midominioconwww.com; 
    location /hola/ { 
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true; 
        proxy_pass http://localhost:3000/;
        proxy_redirect off;
    } 
    location /chat/ { 
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true; 
        proxy_pass http://localhost:4000/;
        proxy_redirect off; 
    } 
    location /blog/ { 
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true; 
        proxy_pass http://localhost:4050/;
        proxy_redirect off; 
    } 
    location / { 
        root /home/midominio index index.html; 
    } 
} 
server { 
    listen 80; 
    server_name midominiosinwww.com; 
    return 301 $scheme://www.midominioconwww.com$uri; 
}

Guardamos el documento y reinciamos nginx mediante:

sudo service nginx restart

Ya podemos acceder mediante las urls que tengamos definidas a nuestras aplicaciones Node (u otras) de una manera limpia de cara al usuario.

No busco profundizar mucho en nginx porque de momento no se mucho más de lo que he puesto aquí, si quieres seguir profundizando en su configuración (que es muy versatil) puedes echarle un ojo aquí: http://wiki.nginx.org/Configuration