POSTS

Running a NodeJs app on nginx (1/2)

##Introduction In the previous post we did setup a nginx web server for serving static pages. In this post, we will host a NodeJs application and make sure it will survice application crashes.

##The sample NodeJs application We’ll focus on how nginx handles NodeJs, so we just need a dummy app but we want that the app logs both normal and failure behavior. So, let’s create a NodeJs application under /usr/share/nginx/app1. We’ll create the app today directy on our server. It’s a good habit to first create a package.json file by typing in the app1 folder:

This will guide you through a kind of wizard resulting in a package.json file:

Note that we slightly adapted the package.json in such way there is an npm start verb. We did this by adding under “scripts”: “start”: “node index”.

var http = require('http');
http.createServer(function (req, res) {
    var input = req.url.toString();
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('thanks for ' + input + ' on ' + new Date().toISOString() + '\n');
    if(input=='/warning'){
        console.info("a warning occured on " + new Date().toISOString());
    }
    if (input=='/crash'){
        console.error("a crash occured on " + new Date().toISOString());
        throw "serious error";
    }
}).listen(1337, '127.0.0.1');

console.log('Server running at http://127.0.0.1:1337/' + ' ' + new Date().toISOString());

As you can see, not really a large scale business application. The app simply logs the incoming url and covers 2 specific cases:

  • when the url matches exactly ‘/warning’ a specific logging occurs and
  • when the url matches exactly ‘/crash’, we raise an error and make an logging in the error log.

This provides us immediately two important scenarios:

  • we are making use of the relative url in this app (the input variable). So, when the user provides as url: app1.opinionatedapps.com/mytext, the input variable will be ‘mytext”. But what happens when we deploy our application not directly on a subdomain but in a subfolder. Well, a requirement will be that the application should not be aware of that. So, our nginx configuration should make sure that demosite1.opinionatedapps.com/app1/mytext gives as url also “mytext” and not “/app1/mytext”.
  • when the app crashes, we need something to restart and recover automatically. Nginx will not do this for us. That’s a big difference with a web server like IIS running Asp.Net apps. In the IIS scenario, both the runtime (Asp.Net) and the server (IIS) are quite intimitely integrated. That’s not the case with nginx which doesn’t know anything at all about about NodeJs. At first glance, this feels like a step backwards when it comes to comfort but in a way it’s a much cleaner seperation of concerns and it reflex the Unix philosophy of components doing simply one thing but doing it really good. Ok, let’s first test if the app runs by typing :

You should see now in the console something like : Server running at http://127 … Obviously, so far our app runs also as a backend process on our server, we need to configure nginx to expose the application behind port 80. That’s what we’ll do next.

configure nginx for the NodeJs app

We’ll need to update the file demosite1.opinionatedapps.com inside the /etc/nginx/sites-enabled folder as follows:

The above assures that nginx acts as kind of reverse proxy and forwards all requests to /app1 to port 1337 where nodeJs is running our app1. Let’s try now from the browser:

http://demosite1.opinionatedapps.com/app1/HiThere which gives as output:

and that’s not what we want. We don’t want to see ‘app1’ in the url, but we want a path relative to the application root inside the app1 folder ! We can accomplish this by adding following line inside the location block of app1:

##Force an app crash now http://demosite1.opinionatedapps.com/app1/warning is triggering a warning message, which we can see in the output window of the NodeJs app. That’s good. But what happens if we trigger an app crash by browsing to:

That’s all as expected, but we have a serious problem now, the app stopped completely. We’ll cover that scenario in the next episode.

comments powered by Disqus