Node.js + Nginx - What now?
Asked Answered
O

12

1139

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.

Omaromara answered 15/2, 2011 at 20:49 Comment(0)
L
1436

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

This is what I have done in my Ubuntu box:

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

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

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.example www.yourdomain.example;
    access_log /var/log/nginx/yourdomain.example.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.example yourdomain.example

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.example

One last note with 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.

Lawyer answered 16/2, 2011 at 10:20 Comment(18)
Thanks for the post, will nginx cache node.js responses for the server above, or rerun them each time.Peignoir
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?Hypostasis
the upstream block is just for organizing / factoring stuff out, you're not forced to use it.Unitarian
+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).Rodarte
@Robin Winslow in case you want to add more servers for servers for load balancing.Lawyer
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..Montiel
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.Titter
@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.Lawyer
Only thing I don't get at this point: Is nginx now just a proxy? Will there be caching?Arbitrament
*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) ;)Disclamation
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.Sholeen
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?Scales
I'm using this configuration, but I'm getting a 502, I have made a post on serverfault serverfault.com/questions/629318/…Cum
It looks like you forget to remove default symlink in sites-enabled directoryMudra
I got a question, why we need an nginx as 'front end server'? why don't we just use node server directly?Bayonet
@wdanxa nginx is more efficient, more secure, better at dealing with permissions (i.e. #16771173)Istic
i did with nginx in 5 min what i struggle to do with apache in 2 daysBalk
Does "front end" mean that it doesn't actually host the backend? I have an nginx docker on unraid, and have successfully published my site, but any attempt I make to call my controllers fail. Everything works fine in dev, but in production, all I get back is the main page.Contrabassoon
D
187

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

For example to achieve these:

  • domain1.example -> to Node.js process running locally http://127.0.0.1:4000
  • domain2.example -> to Node.js process running locally http://127.0.0.1:5000

These ports (4000 and 5000) should be used to listen the app requests in your app code.

/etc/nginx/sites-enabled/domain1

server {
    listen 80;
    listen [::]:80;
    server_name domain1.example;
    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.example;
    access_log /var/log/nginx/domain2.access.log;
    location / {
        proxy_pass    http://127.0.0.1:5000/;
    }
}
Decollate answered 2/5, 2012 at 11:38 Comment(3)
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?Larousse
Do you have Cloudflare or something similar? The configuration above shouldn't redirect at all.Volsung
@Larousse You'll need to add proxy_set_header Host $host to avoid HTTP 302 redirection.Albion
B
71

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

  • yourdomain.example/app1/* -> to Node.js process running locally http://127.0.0.1:3000
  • yourdomain.example/app2/* -> to Node.js process running locally http://127.0.0.1:4000

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

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

    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/');
Branson answered 31/3, 2015 at 17:31 Comment(5)
Open source community version is free but they have version with other features which are not free. nginx.com/products/feature-matrixBranson
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.Viol
@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.Branson
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?Viol
@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.Branson
H
37

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

Heuristic answered 13/7, 2012 at 7:53 Comment(1)
Why and how you should do it in subdomains instead: skovalyov.blogspot.dk/2012/10/…Heuristic
V
14

Node.js with Nginx configuration.

$ sudo nano /etc/nginx/sites-available/subdomain.your-domain.example

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.example

upstream subdomain.your-domain.example {
  server 127.0.0.1:3000;
}
server {
  listen 80;
  listen [::]:80;
  server_name subdomain.your-domain.example;
  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.example;
    proxy_redirect off;
  }
}
Verlie answered 17/3, 2014 at 12:24 Comment(0)
F
10

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;
        }
}
Fantasize answered 18/3, 2015 at 10:24 Comment(0)
Q
9

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.

Quadruple answered 3/1, 2012 at 4:51 Comment(1)
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.Bazooka
W
7

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.example sub.mydomain.example;
    
      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.example/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.example/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.

Wool answered 27/9, 2017 at 8:7 Comment(0)
C
6

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..

Clova answered 5/7, 2013 at 14:17 Comment(0)
B
6

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.example sub.domain.example; # 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

Balladeer answered 7/1, 2017 at 18:54 Comment(1)
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/startupPhinney
D
4

The best and simpler setup with Nginx and Nodejs is to use Nginx as an HTTP and TCP load balancer with proxy_protocol enabled. In this context, Nginx will be able to proxy incoming requests to nodejs, and also terminate SSL connections to the backend Nginx server(s), and not to the proxy server itself. (SSL-PassThrough)

In my opinion, there is no point in giving non-SSL examples, since all web apps are (or should be) using secure environments.

Example config for the proxy server, in /etc/nginx/nginx.conf

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
  upstream webserver-http {
    server 192.168.1.4; #use a host port instead if using docker
    server 192.168.1.5; #use a host port instead if using docker
  }
  upstream nodejs-http {
    server 192.168.1.4:8080; #nodejs listening port
    server 192.168.1.5:8080; #nodejs listening port
  }
  server {
    server_name example.com;
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $server_name;
      proxy_set_header Connection "";
      add_header       X-Upstream $upstream_addr;
      proxy_redirect     off;
      proxy_connect_timeout  300;
      proxy_http_version 1.1;
      proxy_buffers 16 16k;
      proxy_buffer_size 16k;
      proxy_cache_background_update on;
      proxy_pass http://webserver-http$request_uri;
    }
  }
  server {
    server_name node.example.com;
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $server_name;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      add_header       X-Upstream $upstream_addr;
      proxy_redirect     off;
      proxy_connect_timeout  300;
      proxy_http_version 1.1;
      proxy_buffers 16 16k;
      proxy_buffer_size 16k;
      proxy_cache_background_update on;
      proxy_pass http://nodejs-http$request_uri;
    }
  }
}
stream {
  upstream webserver-https {
    server 192.168.1.4:443; #use a host port instead if using docker
    server 192.168.1.5:443; #use a host port instead if using docker
  }

  server {
    proxy_protocol on;
    tcp_nodelay on;
    listen 443;
    proxy_pass webserver-https;
  }
  log_format proxy 'Protocol: $protocol - $status $bytes_sent $bytes_received $session_time';
  access_log  /var/log/nginx/access.log proxy;
  error_log /var/log/nginx/error.log debug;
}

Now, let's handle the backend webserver. /etc/nginx/nginx.conf:

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
load_module /etc/nginx/modules/ngx_http_geoip2_module.so; # GeoIP2
events {
    worker_connections  1024;
}
http {
    variables_hash_bucket_size 64;
    variables_hash_max_size 2048;
    server_tokens off;
    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;
    autoindex off;
    keepalive_timeout  30;
    types_hash_bucket_size 256;
    client_max_body_size 100m;
    server_names_hash_bucket_size 256;
    include         mime.types;
    default_type    application/octet-stream;
    index  index.php index.html index.htm;
    # GeoIP2
    log_format  main    'Proxy Protocol Address: [$proxy_protocol_addr] '
                        '"$request" $remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

    # GeoIP2
    log_format  main_geo    'Original Client Address: [$realip_remote_addr]- Proxy Protocol Address: [$proxy_protocol_addr] '
                            'Proxy Protocol Server Address:$proxy_protocol_server_addr - '
                            '"$request" $remote_addr - $remote_user [$time_local] "$request" '
                            '$status $body_bytes_sent "$http_referer" '
                            '$geoip2_data_country_iso $geoip2_data_country_name';

    access_log  /var/log/nginx/access.log  main_geo; # GeoIP2
#===================== GEOIP2 =====================#
    geoip2 /usr/share/geoip/GeoLite2-Country.mmdb {
        $geoip2_metadata_country_build  metadata build_epoch;
        $geoip2_data_country_geonameid  country geoname_id;
        $geoip2_data_country_iso        country iso_code;
        $geoip2_data_country_name       country names en;
        $geoip2_data_country_is_eu      country is_in_european_union;
    }
    #geoip2 /usr/share/geoip/GeoLite2-City.mmdb {
    #   $geoip2_data_city_name city names en;
    #   $geoip2_data_city_geonameid city geoname_id;
    #   $geoip2_data_continent_code continent code;
    #   $geoip2_data_continent_geonameid continent geoname_id;
    #   $geoip2_data_continent_name continent names en;
    #   $geoip2_data_location_accuracyradius location accuracy_radius;
    #   $geoip2_data_location_latitude location latitude;
    #   $geoip2_data_location_longitude location longitude;
    #   $geoip2_data_location_metrocode location metro_code;
    #   $geoip2_data_location_timezone location time_zone;
    #   $geoip2_data_postal_code postal code;
    #   $geoip2_data_rcountry_geonameid registered_country geoname_id;
    #   $geoip2_data_rcountry_iso registered_country iso_code;
    #   $geoip2_data_rcountry_name registered_country names en;
    #   $geoip2_data_rcountry_is_eu registered_country is_in_european_union;
    #   $geoip2_data_region_geonameid subdivisions 0 geoname_id;
    #   $geoip2_data_region_iso subdivisions 0 iso_code;
    #   $geoip2_data_region_name subdivisions 0 names en;
   #}

#=================Basic Compression=================#
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/css text/xml text/plain application/javascript image/jpeg image/png image/gif image/x-icon image/svg+xml image/webp application/font-woff application/json application/vnd.ms-fontobject application/vnd.ms-powerpoint;
    gzip_static on;

    include /etc/nginx/sites-enabled/example.com-https.conf;
}

Now, let's configure the virtual host with this SSL and proxy_protocol enabled config at /etc/nginx/sites-available/example.com-https.conf:

server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name 192.168.1.4; #Your current server ip address. It will redirect to the domain name.
    listen 80;
    listen 443 ssl http2;
    listen [::]:80;
    listen [::]:443 ssl http2;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    return 301 https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name  example.com;
    listen       *:80;
    return 301   https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name www.example.com;
    listen 80;
    listen 443 http2;
    listen [::]:80;
    listen [::]:443 ssl http2 ;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    return 301 https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name example.com;
    listen 443 proxy_protocol ssl http2;
    listen [::]:443 proxy_protocol ssl http2;
    root /var/www/html;
    charset UTF-8;
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy no-referrer;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;
    keepalive_timeout   70;
    ssl_buffer_size 1400;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=86400;
    resolver_timeout 10;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_trusted_certificate /etc/nginx/certs/example.com.crt;
location ~* \.(jpg|jpe?g|gif|png|ico|cur|gz|svgz|mp4|ogg|ogv|webm|htc|css|js|otf|eot|svg|ttf|woff|woff2)(\?ver=[0-9.]+)?$ {
    expires modified 1M;
    add_header Access-Control-Allow-Origin '*';
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    access_log off;
    }
    location ~ /.well-known { #For issuing LetsEncrypt Certificates
        allow all;
    }
location / {
    index index.php;
    try_files $uri $uri/ /index.php?$args;
    }
error_page  404    /404.php;

location ~ \.php$ {
    try_files       $uri =404;
    fastcgi_index   index.php;
    fastcgi_pass    unix:/tmp/php7-fpm.sock;
    #fastcgi_pass    php-container-hostname:9000; (if using docker)
    fastcgi_pass_request_headers on;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
    fastcgi_ignore_client_abort off;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_request_buffering on;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    include fastcgi_params;
}
location = /robots.txt {
    access_log off;
    log_not_found off;
    }
location ~ /\. {
    deny  all;
    access_log off;
    log_not_found off;
    }
}

And lastly, a sample of 2 nodejs webservers: First server:

var http = require('http');

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

Second server:

var http = require('http');

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

Now everything should be perfectly working and load-balanced.

A while back I wrote about How to set up Nginx as a TCP load balancer in Docker. Check it out if you are using Docker.

Donica answered 10/12, 2019 at 23:31 Comment(1)
So the above setup uses the nginx both as a reverse proxy and a web server.Is this correct?Baseline
H
1

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.example)

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

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

Check weather 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

Hudgins answered 6/7, 2018 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.