DEV Community

Shadid Haque
Shadid Haque

Posted on • Updated on

How To Deploy Your Node.js App On AWS With NGINX And SSL

  • Photo by Bill Jelen on Unsplash

Originally published in my blog

In this tutorial, we will briefly go over the process of deploying a Node.js/Express application on AWS EC2 instance. Let’s face it, server configuration and application deployment can be tedious tasks. As a developer, you may not know every knits and bit about network security, or how to reverse proxy and load balancing works. The first time I had to deploy my application I went through a plethora of information on stack overflow and various blog posts. Wouldn’t it be nice to have a step-by-step guide to deploy your application? I asked myself. That question led me to write this blog post.
In this article we will cover:

  1. Configuration of an EC2 Instance (i.e. network configurations, ports, etc)
  2. Installing and configuring Nginx for reverse proxy
  3. Pointing EC2 to a custom domain (optional)
  4. Securing our site with LetsEncrypt SSL

You can also follow these steps if you are using other cloud providers such as Azure, Google Cloud Platform, IBM, or Digital ocean.
Configuration of an EC2 Instance
First of all, we need to create a VM. To do so, we will go to the AWS console and from services, we will select EC2 as shown in the picture below.

pick EC2 from AWS console
This will take you to the EC2 dashboard. From here you can select to create a new EC2 instance by clicking the ‘launch instance’ button.

You can choose which operating system to run on your instance. I will be using ubuntu 20.04.

Next, you will be prompted to select an instance type. I will go with the free t2 micro instance here.

You can accept the default configuration for steps 3, 4, and 5. In step 6 you are given the options to select security group rules. Here I will be choosing SSH, HTTP, and HTTPS. I also choose a custom TCP port 8000. We will run our Node application on the 8000 port.

We can change these configurations later if we want to, so don’t worry if you mess this up 😅.
Once the instance is created go ahead and ssh into your instance. The first thing we would need to set up is Node.js itself. I am going to run the following command to get Node in my instance.

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt install nodejs

node --version
Enter fullscreen mode Exit fullscreen mode

Once we are done setting up node we can clone our repository and run the code in our cloud instance.

git clone <project_repo>
cd yourproject
npm install
npm start (or whatever your start command)
# stop app
ctrl+C
Enter fullscreen mode Exit fullscreen mode

I am running my app in port 8000. We can test our app by going to the public ip address and port. So for my instance, it is http://54.210.195.17:8000/.
Next, we are going to install a library called pm2 this will keep our node application running in the background. Run the following commands to start your application with pm2.

sudo npm i pm2 -g
pm2 start app 
Enter fullscreen mode Exit fullscreen mode

This will start our app. We can visit the ip address with port again and will see the application running.

running in browser
Setting up NGNIX and Reverse Proxy
Next, we will setup NGNIX and create a reverse proxy. This will redirect our application with the default port 80. We will also add SSL through the NGNIX server.
We run the following command to install NGNIX:

sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

Once NGNIX is installed we can configure it to set up a reverse proxy and redirect our application to port 80. To do so we have to edit the following file

sudo nano /etc/nginx/sites-available/default
server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://localhost:8000; # your app's port
        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;
    }
Enter fullscreen mode Exit fullscreen mode

In the location, the section makes the changes as shown above. If you are using a custom domain name, go to your DNS provider and add an A Record like shown below.

A record
In the target section, we will be adding our instance’s public IP address.
After this is done jump back to your terminal and restart NGNIX.

# Restart NGINX
sudo service nginx restart
Enter fullscreen mode Exit fullscreen mode

You need to give some time for the custom domain to propagate. After some time you can go to your custom domain and see the application running.

Securing our site with SSL encryption
Finally, the only task left to do here is to secure our web server with SSL encryption. We can do this with the LetsEncrypt library very easily.
First, we install to certbot package by running the following commands

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python3-certbot-nginx
Enter fullscreen mode Exit fullscreen mode

Once the installation is done we will be using certbot cli to generate an SSL certificate for us. Run the following command and provide your email information when prompted to generate the SSL cert.



    sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com


Enter fullscreen mode Exit fullscreen mode

Once the cert is generated, you should connect to your application via HTTPS.

That’s it. Now you have a secure web application running in your EC2 instance. 👏

Top comments (12)

Collapse
 
salis010 profile image
Stephen Saliba

I tried many similar articles, but many failed, yours is the best I found. Thank you a lot.

May I just point out to a tiny typo: in the nginx installation command, 'Nginx' should be in lower case, the below does not work:

sudo apt install Nginx
Enter fullscreen mode Exit fullscreen mode

Anyway, you earned a follower.

Collapse
 
shadid12 profile image
Shadid Haque

Thank you Stephen. I totally missed that one. Glad that I could help 😀

Collapse
 
adrienfloor profile image
Floor

Thank you for the great article ! Could you explain how to setup env variables on the created instance ? I couldn't find a clear answer ... Thank you !!

Collapse
 
abdurrkhalid333 profile image
Abdur Rehman Khalid

What an awesome article this is. It has Helped me a lot and I am bookmarking this article so that I can come here again and again. Thank you and I will also be implementing the same technique with deployment of the Angular Application as well.

Collapse
 
shadid12 profile image
Shadid Haque

Thank you, means a lot. Feel free to reach out on twitter.com/haqueshadid

Collapse
 
ithinkobjects profile image
Marlon • Edited

This is really cool! Thanks for sharing the insight. I look forward to coming back to this every now and then!

Collapse
 
bonaparteit profile image
BonaparteIT

After command:

sudo add-apt-repository ppa:certbot/certbot

The PPA has been DEPRECATED.

To get up to date instructions on how to get certbot for your systems, please see certbot.eff.org/docs/install.html.
More info: launchpad.net/~certbot/+archive/ub...

Collapse
 
ashadnasim52 profile image
ashad nasim

Awesome Article, but for Nginx part, your article is not correct. The correct way is

  1. Install NGINX and configure sudo apt install nginx

sudo nano /etc/nginx/sites-available/default
Add the following to the location part of the server block

server_name yourdomain.com yourdomain.com;

location / {
proxy_pass localhost:5000; #whatever port your app runs on
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;
}

Enter fullscreen mode Exit fullscreen mode




Check NGINX config

sudo nginx -t

Restart NGINX

sudo service nginx restart

Taken from gist.github.com/bradtraversy/cd90d...

Collapse
 
drsimplegraffiti profile image
Abayomi Ogunnusi

Thank you and God bless you.... I am really happy for this.

It worked like charm

Collapse
 
akdenied profile image
akdenied • Edited

nginx -t fails
I think because

server {
    server_name yourdomain.com www.yourdomain.com;
    location / {
        proxy_pass http://localhost:8000; # your app's port
        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;
    }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
trason profile image
Boris

In the DNS step, you have set TTL to be 300. However, when I try that on my custom domain name manager, it says that TTL "should be higher or equal to 3600." Can you provide any more information about that?

Collapse
 
mdmohsinghazi1 profile image
MD Mohsin Ghazi

Getting this after configuring all configuration on EC2-instance
"ErrorResponse is not defined"