Monday, 22 June 2015

Running node.js application with Passenger and Nginx

We can use Phusion Passenger to deploy our node.js application on production, it takes out many complications that come while deploying or running Node.js application. Using Passenger is very easy and some of the benefits that we get from using Passenger are:
1) We have nginx to serve the static contents, so our app can concentrate of serving our main purpose.
2) Ngnix also protects our application from some kind of attacks.
3) Automatic restart of our application on system reboots.
4) We can run multiple Node.js applications on a single server easily.
5) Phusion Passenger can spawn more Node.js processes depending on the load etc.
6) Automatic starts a new process for a failed process.
First we are going to install node.js
Note: For this demo I used Ubuntu 14.04


Installing node.js

# curl -sL | sudo bash -
Now run apt-get to install node.js
# apt-get install nodejs



Installing Ngnix

# apt-get install ngnix



Installing Passenger

Install passenger PGP key.
# apt-key adv --keyserver --recv-keys 561F9B9CAC40B2F7
We need to add HTTPS support for apt as passenger apt repository is hosted on an HTTPS server.
# apt-get install apt-transport-https ca-certificates
Create a file /etc/apt/sources.list.d/passenger.list and insert the following line:
# Ubuntu 14.04
deb trusty main

Note: the above line is specifically for Ubuntu 14.04, if you are not using Ubuntu 14.04 then please refer Passenger document to get the URL for your distribution.
After adding the new apt source, run apt-get update followed by apt-get install
# apt-get update
# apt-get install nginx-extras passenger
Once passenger installation is done, edit /etc/nginx/nginx.conf and uncomment the following lines: 

passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
passenger_ruby /usr/bin/passenger_free_ruby;
You can verify the passenger root is correct or not by the command:
# /usr/bin/passenger-config --root
Installation part is over, not I am going to deploy one application to test the new setup.
For this demo I wrote a small app test.js

var http = require("http");
function onRequest(request, response){
var body = '<html>'+
'<meta http-equiv="Content-Type" content="text/html; '+
'charset=UTF-8" />'+
'Hi I am SuperMan'+
'<img src=monkey1.gif>'+
response.writeHead(200, {"Content-Type" : "text/html"});
console.log("Server has started.");
As suggested in the passenger documentation , I have created the application directory structure:
  +-- test.js
  +-- public/
  +-- tmp/
/apps is the root directory of my application

test.js file is the entry point of my application. Passenger will load test.js to start my application.
public : This directory contains static file, so files placed in this folder will directly serve by Nginx, request will not be forwarded to the application. I copied one image file monkey1.txt in this directory.
tmp : We can create restart.txt file in this directory to restart the application on next request. Also this directory can be used by the application also.    
In this example I am going to run my Node.js application as my default site. So I am editing the file /etc/nginx/sites-available/default and my file looks like:

server {
listen 80 default_server;
listen [::]:80 default_server;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
passenger_app_root /apps;
passenger_enabled on;
passenger_app_type node;
passenger_startup_file test.js;

#This is where my static files will go
root /apps/public;
All set, restart nginx and we are ready.
# service nginx restart

My superb website is up and running Smile Smile Smile