Configure Nginx with NodeJS application on AWS

NGINX is a powerful web server and uses a non-threaded, event-driven architecture that enables it to outperform Apache if configured correctly. It can also do other important things, such as load balancing, HTTP caching, or be used as a reverse proxy.

This architecture makes handling high and fluctuating loads much more predictable in terms of RAM usage, CPU usage, and latency.

Here in this blog, we will discuss how to set up a NodeJS environment that is composed of Ubuntu 18.04 servers providing users access to the application through an Nginx reverse proxy to the application server.

Installing NGINX on AWS EC2 Instance with Ubuntu Server 18.04

To begin with, we’ll install the latest version of Nginx setup from the following commands:

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install nginx -y

Setup Nginx

Following are the commands for starting and checking the status of Nginx

sudo systemctl status nginx    # To check the status of nginx
sudo systemctl start nginx # To start nginx

Ensure every time you restart your system Nginx starts up automatically.

sudo systemctl enable nginx

Nginx should be UP and running. If not check for distribution used(The above steps are only for Ubuntu distribution)

Setting up Node.js and NPM

I have used node.js as backend but any other app servers can be used as backend

Install Nodejs using the following commands:-

sudo apt-get update
sudo apt-get install nodejs

Install npm using the following command:-

sudo apt-get install npm

Verify Nodejs and npm installations using below commands

node --version
npm --version

versions of node.js and npm would be displayed

Setting up Nginx as a reverse proxy for Nodejs application

SSH into the EC2 instance (For ubuntu instance username would be ‘ubuntu@your_public_ip’)and pull out your Instance Private IP from below command or you can get it through console also(from the Description tab of that specific EC2 instance.)

wget -q -O - 'http://169.254.169.254/latest/meta-data/local-ipv4'

Remove and add default file to sites-available path by using following commands:-

sudo rm /etc/nginx/sites-available/default
sudo vi /etc/nginx/sites-available/default

Now start entering the code for server block, Sample given for Port 8080 and 8081

server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://your_private_IP:8080;
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;
}
location /admin {
proxy_pass http://your_private_IP:8081;
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;
}
}

In the above configuration, I’ve used port 8080 to serve ‘www.example.com/’ (non-admin pages) and port 8081 to serve ‘www.example.com/admin’ (admin pages). Replace your_private_IP with Instance private IP address obtained from the previous command.

You can also use a separate server to host the backend application.

Make sure the configuration doesn’t have any syntax errors and then Save.

Test configuration and Reload Nginx and check if OK is the status from following commands:

sudo nginx -t
sudo /etc/init.d/nginx reload

Creating Nodejs application using Expressjs

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. It is an open source framework developed and maintained by the Node.js foundation.

Create your project directory and install Expressjs into your directory (Directory named as nodeapp)from following commands:

mkdir nodeapp
cd nodeapp
npm install express

Create Express app into ‘nodeapp’ directory. Here I’ve named it as ‘app.js

vi app.js

Make it listen to Port 8080 and 8081 and your_private_ip.

var express = require('express');
var app = express();
app.get('/*', function(req, res){
res.send("Hello World!");
});
app.listen(process.env.PORT || 8081, "your_private_ip");

Above code is a very simple NodeJS express app which listens on the given port and responds to the HTTP requests. Using Express, we can implement different handlers for different URL path requests but for the simplicity, we have used “/*” wild card path to match any URL. Also I am running 2 instances of the same app on different ports, one for non-admin pages on 8080 and other for admin pages on 8081.

For local testing, without registering the domains we can test by modifying the hosts file.

Now Go to host file (Windows path C:\Windows\System32\drivers\etc\hosts file)of your local system and edit it with below command:

sudo nano /private/etc/hosts         #Path in MacOS
Please note: For some MacOS versions hosts file path is /etc/hosts

Make an entry of your Instance public IP with your domain name. It should look like this:

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost
your_public_ip  www.example.com
your_public_ip  www.example.com/admin

Save it through Ctrl+x →y →Enter. Now go back and SSH your instance, then enter your ‘nodeapp’ directory and run the below commands for specific ports.

PORT=8080 node app.js          #For 'www.example.com'
PORT=8081 node app.js #For 'www.example.com/admin'
In this configuration you cannot run both the domains together. you need to terminate(ctrl+x) one and then run the other.

Now open your browser and browse your domain. It should display Hello World!

For PORT 8080
For PORT 8081

CONCLUSION

In this blog, you have learned the basic concepts of NGINX and its routing capabilities, now you know how to configure NGINX to route various URL paths of the websites to different backend application servers or ports.