By Van Coding


2011-02-15 20:49:02 8 Comments

I've set up Node.js and Nginx on my server. Now I want to use it, but, before I start there are 2 questions:

  1. How should they work together? How should I handle the requests?
  2. There are 2 concepts for a Node.js server, which one is better:

    a. Create a separate HTTP server for each website that needs it. Then load all JavaScript code at the start of the program, so the code is interpreted once.

    b. Create one single Node.js server which handles all Node.js requests. This reads the requested files and evals their contents. So the files are interpreted on each request, but the server logic is much simpler.

It's not clear for me how to use Node.js correctly.

11 comments

@Vkreddy Komatireddy 2017-09-27 08:07:40

Nginx can act as a reverse proxy server which works just like a project manager. When it gets a request it analyses it and forwards the request to upstream(project members) or handles itself. Nginx has two ways of handling a request based on how its configured.

  • serve the request
  • forward the request to another server

    server{
     server_name mydomain.com sub.mydomain.com;
    
     location /{ 
      proxy_pass http://127.0.0.1:8000;  
      proxy_set_header Host $host;
      proxy_pass_request_headers on;  
     }
    
     location /static/{
       alias /my/static/files/path;
     }
    

    }

Server the request

With this configuration, when the request url is mydomain.com/static/myjs.js it returns the myjs.js file in /my/static/files/path folder. When you configure nginx to serve static files, it handles the request itself.

forward the request to another server

When the request url is mydomain.com/dothis nginx will forwards the request to http://127.0.0.1:8000. The service which is running on the localhost 8000 port will receive the request and returns the response to nginx and nginx returns the response to the client.

When you run node.js server on the port 8000 nginx will forward the request to node.js. Write node.js logic and handle the request. That's it you have your nodejs server running behind the nginx server.

If you wish to run any other services other than nodejs just run another service like Django, flask, php on different ports and config it in nginx.

@gokul kandasamy 2018-07-06 12:01:59

You can run nodejs using pm2 if you want to manage each microservice means and run it. Node will be running in a port right just configure that port in nginx(/etc/nginx/sites-enabled/domain.com)

server{
    listen 80;
    server_name domain.com www.domain.com;

  location / {
     return 403;
  }
    location /url {
        proxy_pass http://localhost:51967/info;
    }
}

Check whether localhost is running or not by using ping.

And

Create one single Node.js server which handles all Node.js requests. This reads the requested files and evals their contents. So the files are interpreted on each request, but the server logic is much simpler.

This is best and as you said easier too

@svnm 2015-03-18 10:24:18

I made a repository in Github which you can clone, vagrant-node-nginx-boilerplate

basically the node.js app at /var/www/nodeapp is

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(4570, '127.0.0.1');

console.log('Node Server running at 127.0.0.1:4570/');

and the nginx config at /etc/nginx/sites-available/ is

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/nodeapp;
        index index.html index.htm;

        server_name localhost;

        location / {
          proxy_pass http://127.0.0.1:4570;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
        }
}

@aquadir 2014-03-17 12:24:35

Node.js with Nginx configuration.

$ sudo nano /etc/nginx/sites-available/subdomain.your_domain.com

add the following configuration so that Nginx acting as a proxy redirect to port 3000 traffic from the server when we come from “subdomain.your_domain.com”

upstream subdomain.your_domain.com {
  server 127.0.0.1:3000;
}
server {
  listen 80;
  listen [::]:80;
  server_name subdomain.your_domain.com;
  access_log /var/log/nginx/subdomain.your_domain.access.log;
  error_log /var/log/nginx/subdomain.your_domain.error.log debug;
  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://subdomain.your_domain.com;
    proxy_redirect off;
  }
}

@skovalyov 2012-07-13 07:53:54

I proxy independent Node Express applications through Nginx.

Thus new applications can be easily mounted and I can also run other stuff on the same server at different locations.

Here are more details on my setup with Nginx configuration example:

Deploy multiple Node applications on one web server in subfolders with Nginx

Things get tricky with Node when you need to move your application from from localhost to the internet.

There is no common approach for Node deployment.

Google can find tons of articles on this topic, but I was struggling to find the proper solution for the setup I need.

Basically, I have a web server and I want Node applications to be mounted to subfolders (i.e. http://myhost/demo/pet-project/) without introducing any configuration dependency to the application code.

At the same time I want other stuff like blog to run on the same web server.

Sounds simple huh? Apparently not.

In many examples on the web Node applications either run on port 80 or proxied by Nginx to the root.

Even though both approaches are valid for certain use cases, they do not meet my simple yet a little bit exotic criteria.

That is why I created my own Nginx configuration and here is an extract:

upstream pet_project {
  server localhost:3000;
}

server {
  listen 80;
  listen [::]:80;
  server_name frontend;

  location /demo/pet-project {
    alias /opt/demo/pet-project/public/;
    try_files $uri $uri/ @pet-project;
  }

  location @pet-project {
    rewrite /demo/pet-project(.*) $1 break;

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $proxy_host;
    proxy_set_header X-NginX-Proxy true;

    proxy_pass http://pet_project;
    proxy_redirect http://pet_project/ /demo/pet-project/;
  }
}

From this example you can notice that I mount my Pet Project Node application running on port 3000 to http://myhost/demo/pet-project.

First Nginx checks if whether the requested resource is a static file available at /opt/demo/pet-project/public/ and if so it serves it as is that is highly efficient, so we do not need to have a redundant layer like Connect static middleware.

Then all other requests are overwritten and proxied to Pet Project Node application, so the Node application does not need to know where it is actually mounted and thus can be moved anywhere purely by configuration.

proxy_redirect is a must to handle Location header properly. This is extremely important if you use res.redirect() in your Node application.

You can easily replicate this setup for multiple Node applications running on different ports and add more location handlers for other purposes.

From: http://skovalyov.blogspot.dk/2012/07/deploy-multiple-node-applications-on.html

@skovalyov 2012-10-23 09:57:04

Why and how you should do it in subdomains instead: skovalyov.blogspot.dk/2012/10/…

@kaiser 2016-03-14 14:59:31

Link only answer … can you please summarize the relevant parts in your answer in case you blog is gone?

@skovalyov 2016-03-15 21:10:28

@kaiser updated with the content of the article.

@0x8BADF00D 2015-03-31 17:31:30

You can also have different urls for apps in one server configuration:

In /etc/nginx/sites-enabled/yourdomain:

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com;

    location ^~ /app1/{
        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://127.0.0.1:3000/;
    }

    location ^~ /app2/{
        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://127.0.0.1:4000/;
    }
}

Restart nginx:

sudo service nginx restart

Starting applications.

node app1.js

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from app1!\n');
}).listen(3000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

node app2.js

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from app2!\n');
}).listen(4000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:4000/');

@Asiri Liyana Arachchi 2016-09-07 08:37:31

nginx is not free right?

@0x8BADF00D 2016-09-07 19:34:36

Open source community version is free but they have version with other features which are not free. nginx.com/products/feature-matrix

@Mauro Aguilar 2017-06-29 21:28:40

Sorry for my ignorance. What is the purpose, benefits of serving it this way? do you have any example or case of use? Thanks in advance.

@0x8BADF00D 2017-06-29 21:34:13

@MauroAguilar If you need 2 node.js app on one server you can serve them using suggested way (using different ports). In my cases it were two different test apps.

@Mauro Aguilar 2017-06-29 21:50:29

Ok, but what's the difference between running 2 apps and a single one? I mean, what are the benefits if they were intended for the same purpose?

@0x8BADF00D 2017-06-29 21:54:06

@MauroAguilar, you can run them in single one and there is no benefit if it could be part of one project and has same purpose. But if you need to run 2 different projects with different purposes and with different configurations on one server then you have benefit to use this config.

@250R 2012-05-02 11:38:05

You can also setup multiple domain with nginx, forwarding to multiple node.js processes.

For example to achieve these:

/etc/nginx/sites-enabled/domain1

server {
    listen 80;
    listen [::]:80;
    server_name domain1.com;
    access_log /var/log/nginx/domain1.access.log;
    location / {
        proxy_pass    http://127.0.0.1:4000/;
    }
}

In /etc/nginx/sites-enabled/domain2

server {
    listen 80;
    listen [::]:80;
    server_name domain2.com;
    access_log /var/log/nginx/domain2.access.log;
    location / {
        proxy_pass    http://127.0.0.1:5000/;
    }
}

@Kristian 2015-11-13 08:00:57

I am using your method of proxy_pass, but for some reason http://example.com gets automatically 302'd to http://www.example.com. Why is that?

@ozzieisaacs 2018-06-18 21:46:36

Do you have Cloudflare or something similar? The configuration above shouldn't redirect at all.

@Ivan Shatsky 2018-11-30 21:01:50

@Kristian You'll need to add proxy_set_header Host $host to avoid HTTP 302 redirection.

@151291 2019-04-01 10:49:55

@IvanShatsky - Can you provide any help how to configure multiple ports with multiple sub domain and prevent other ports running in another domain?nginx v 1.14.1

@Joao Da Silva 2011-02-16 10:20:53

Nginx works as a front end server, which in this case proxies the requests to a node.js server. Therefore you need to setup an nginx config file for node.

This is what I have done in my Ubuntu box:

Create the file yourdomain.com at /etc/nginx/sites-available/:

vim /etc/nginx/sites-available/yourdomain.com

In it you should have something like:

# the IP(s) on which your node server is running. I chose port 3000.
upstream app_yourdomain {
    server 127.0.0.1:3000;
    keepalive 8;
}

# the nginx server instance
server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com www.yourdomain.com;
    access_log /var/log/nginx/yourdomain.com.log;

    # pass the request to the node.js server with the correct headers
    # and much more can be added, see nginx config options
    location / {
      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://app_yourdomain/;
      proxy_redirect off;
    }
 }

If you want nginx (>= 1.3.13) to handle websocket requests as well, add the following lines in the location / section:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Once you have this setup you must enable the site defined in the config file above:

cd /etc/nginx/sites-enabled/ 
ln -s /etc/nginx/sites-available/yourdomain.com yourdomain.com

Create your node server app at /var/www/yourdomain/app.js and run it at localhost:3000

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(3000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

Test for syntax mistakes:

nginx -t

Restart nginx:

sudo /etc/init.d/nginx restart

Lastly start the node server:

cd /var/www/yourdomain/ && node app.js

Now you should see "Hello World" at yourdomain.com

One last note with regards to starting the node server: you should use some kind of monitoring system for the node daemon. There is an awesome tutorial on node with upstart and monit.

@Lime 2011-07-19 19:31:00

Thanks for the post, will nginx cache node.js responses for the server above, or rerun them each time.

@Robin Winslow 2011-11-20 23:59:55

Is there any reason why you can't just do location / { proxy_pass http://127.0.0.1:3000; }? Why do you need the whole upstream config bit?

@Elisée 2012-02-02 19:56:49

the upstream block is just for organizing / factoring stuff out, you're not forced to use it.

@Paul d'Aoust 2012-03-06 17:52:01

+1, Very straightforward and simple answer to a common question; great for people who want to set up virtual hosts using node and nginx. The only thing I think you missed is a qualitative answer to why nginx-in-front-of-node is best for serving multiple vhosts (asker's second question).

@Joao Da Silva 2012-08-16 10:53:17

@Robin Winslow in case you want to add more servers for servers for load balancing.

@Totty.js 2012-10-09 15:27:55

Well I've managed somehow to make it work with nginx (I can stop and restart and the website only works when is running, so it's not managed by another app) but even if I delete the file you said "yourdomain at /etc/nginx/sites-available/" and even don't do the symbolic link still works. But if I change the IP in the node.js to 127.0.0.2 it will not work: 502 Bad Gateway nginx/1.1.19. So what exacly it's my problem? it seems to me that by default the nginx is set to "serve" the 127.0.0.1:3000 so no config is needed at all, but I cannot change it to 127.0.0.2 for example..

@meetamit 2012-10-18 11:35:51

It should be noted that this (very helpful) answer refers to one flavor of nginx that, by default, comes with sites-enabled and sites-available directories inside /etc/nginx. If your version came without these two directories, it likely has a single conf.d directory instead. In that case, following these instructions would have no effect, UNLESS you modify the include statement inside the file nginx.conf to point to sites-enabled instead of the default conf.d. Hope that makes sense. It should become self explanatory once you see the said include statement inside nginx.conf.

@Joao Da Silva 2012-12-17 09:10:50

@peshohristov by defualt on ubuntu nginx reads the files located at /etc/nginx/sites-enabled. so on this setup as posted above you symlink the config file created from sites-available to sites-enabled.

@Nek 2013-11-03 21:04:20

And if you don't have upstart github.com/nicokaiser/node-monit

@JosFabre 2014-02-26 10:32:22

Only thing I don't get at this point: Is nginx now just a proxy? Will there be caching?

@Erik Aybar 2014-03-21 20:51:34

*Note to the frustrated developer! Great answer. Pointed me in the right direction for solving my problem. Turns out the issue I was having was stemming from an outdated nginx install. Before you get too deep, run nginx -v to see which version you are running. Once I did this the answer above worked like clockwork for serving my SailsJS Application on :1337 and port forwarding :80 for a subdomain alongside numerous other node.js/laravel/php applications (You have to love Digital Ocean) ;)

@mungojerie 2014-05-04 03:48:33

I also had to remove default from the nginx/sites-available directory. Unsure why, but my requests were not routing to my app until I did this.

@vaske 2014-08-26 12:50:05

I just follow this procedure but have strange issue, if I open in browser localhost:5000 I see app, if I try 127.0.0.1 I see nginx welcome screen but 127.0.0.1:5000 or mydomain.com:5000 leads me to server not found error, I had been removed default form site available as well but that dind't helped, any idea what might be the issues?

@Jack Tuck 2014-09-17 20:44:02

I'm using this configuration, but I'm getting a 502, I have made a post on serverfault serverfault.com/questions/629318/…

@kharandziuk 2015-06-15 12:31:14

It looks like you forget to remove default symlink in sites-enabled directory

@wdanxna 2015-08-28 06:57:05

I got a question, why we need an nginx as 'front end server'? why don't we just use node server directly?

@Jake Zieve 2015-10-11 16:29:06

@wdanxa nginx is more efficient, more secure, better at dealing with permissions (i.e. stackoverflow.com/questions/16770673/…)

@Satys 2016-05-15 15:29:36

@allAwesomePeople: I have setup and everything is working as expected. But now I want to send stream of responses(realtime changing data) over this keepalive connection. How can I do that? I don't want to make any additional request(that is why I chose keepalive). Thanks.

@Ashwath S H 2016-07-18 17:12:42

Is app_yourdomain and yourdomain are they both same in the above nginx configuration file. If I try this steps still I'm not able to launch my website. Here is my question stackoverflow.com/questions/38442105/…

@eenblam 2016-09-23 13:07:59

@meetamit's observation is certainly relevant to anyone using a RedHat flavor (e.g. CentOS, RHEL, Fedora.)

@Sampath Sri Anuradha 2018-03-13 05:54:34

@JoaoDaSilva This was helped lot. Only one thing I need to ask you how we run the application automatically in production without stopping.

@indospace.io 2018-12-09 18:05:36

@SampathSriAnuradha - use PM2 to keep your app running, even when it fails. github.com/Unitech/pm2

@I Am Batman 2017-01-07 18:54:02

We can easily setup a Nodejs app by Nginx acting as a reverse proxy.
The following configuration assumes the NodeJS application is running on 127.0.0.1:8080,

  server{
     server_name domain.com sub.domain.com; # multiple domains

     location /{ 
      proxy_pass http://127.0.0.1:8080;  
      proxy_set_header Host $host;
      proxy_pass_request_headers on;  
     }

     location /static/{
       alias /absolute/path/to/static/files; # nginx will handle js/css
     }
   } 

in above setup your Nodejs app will,

  • get HTTP_HOST header where you can apply domain specific logic to serve the response. '
  • Your Application must be managed by a process manager like pm2 or supervisor for handling situations/reusing sockets or resources etc.

  • Setup an error reporting service for getting production errors like sentry or rollbar

NOTE: you can setup logic for handing domain specific request routes, create a middleware for expressjs application

@SQUALLIE 2018-12-14 00:04:19

Another reason to use pm2 is so that you can run your app 'forever' after exiting the shell, and automatically start it if you ever need to reboot your server, see: pm2.keymetrics.io/docs/usage/startup

@I Am Batman 2018-12-14 04:56:07

process manager

@code ninja 2013-07-05 14:17:12

You could also use node.js to generate static files into a directory served by nginx. Of course, some dynamic parts of your site could be served by node, and some by nginx (static).

Having some of them served by nginx increases your performance..

@Hugo Mota 2012-01-03 04:51:37

answering your question 2:

I would use option b simply because it consumes much less resources. with option 'a', every client will cause the server to consume a lot of memory, loading all the files you need (even though i like php, this is one of the problems with it). With option 'b' you can load your libraries (reusable code) and share them among all client requests.

But be ware that if you have multiple cores you should tweak node.js to use all of them.

@robocat 2016-02-08 00:56:03

Follow this advice if resources are your most important issue (unlikely). There are different compromises between (a) and (b). Option (a) is probably better if you wish to the sites to be more independent e.g. site restart or maintenance, db connections, code base, library dependencies, moving sites between servers, etc.

Related Questions

Sponsored Content

12 Answered Questions

[SOLVED] What is the purpose of Node.js module.exports and how do you use it?

  • 2011-03-15 11:56:10
  • mrwooster
  • 457916 View
  • 1379 Score
  • 12 Answer
  • Tags:   javascript node.js

35 Answered Questions

[SOLVED] How do I debug Node.js applications?

18 Answered Questions

[SOLVED] How to exit in Node.js

  • 2011-03-10 21:30:05
  • Bryan Field
  • 798858 View
  • 1684 Score
  • 18 Answer
  • Tags:   node.js

30 Answered Questions

[SOLVED] Using node.js as a simple web server

17 Answered Questions

[SOLVED] Writing files in Node.js

29 Answered Questions

11 Answered Questions

[SOLVED] What is the --save option for npm install?

  • 2013-10-24 23:54:11
  • Dmitri
  • 534101 View
  • 1611 Score
  • 11 Answer
  • Tags:   node.js npm

3 Answered Questions

[SOLVED] How do I get started with Node.js

  • 2010-03-01 04:09:28
  • Joneph O.
  • 1222615 View
  • 1265 Score
  • 3 Answer
  • Tags:   javascript node.js

6 Answered Questions

[SOLVED] Read environment variables in Node.js

17 Answered Questions

[SOLVED] How to decide when to use Node.js?

Sponsored Content