Deploy Nodejs app on AWS EC2 Server

Jagannath Swarnkar
5 min readFeb 13, 2024

--

These are the following steps we will follow.

  1. Login to AWS server using terminal and using termius app.
  2. Server setup for deployment.
  3. Run node js app with pm2 to keep alive.
  4. Setup Nginx and domain cofiguration.
  5. Add free SSL certificate with Let's Encrypt .
  6. Configure domain in nginx for https.
  7. Bonus Step: Configuration for Next.js & React js | SPA

Requirements:

I’m assuming you already have aws account and server details, and you need these credentials ip address, username, password or pem file, and a domain.

Step 1.

Login to aws account in terminal using ssh . 🔗

if you have password instead of pem file then try this.

$ ssh username@ip_address
Example: ssh ubuntu@192.168.3.103
// it will ask you the password once you run this command

if you don’t have password, you have .pem file then try this.

$ ssh -i file.pem username@ip_address
Example: ssh -i aws_key.pem ubuntu@192.168.3.103 // use sudo if required

Login using termius:

if you have .pem file, you need to upload it on termius, click on setting icon ⚙️ on top left corner. select Keychain click on 🗝️key and click on Drag and drop a private key fine to import and upload you pem file.

For this you need to install termius app first and go to Host section in left sidebar, click on New Host, a prompt will open in right sidebar, fill your IP Address, add Username, & Password that’s it and click on top right corner.

if you don’t have password then select key option below password, one key input will be visible there. ( before that you need to add a pem file to termius ) select your pem file and go next, you don’t need to add password.

Step 2

Once you login to the server, run command sudo su to enter into sudo.

Install all required dependencies — nodejs npm nginx pm2 git

# Update apt package index
sudo apt update

# Install curl if not already installed
sudo apt install -y curl

# Install Node.js and npm from NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# Install Nginx
sudo apt-get install -y nginx
sudo ufw allow 'Nginx HTTP'
sudo service nginx start
sudo systemctl enable nginx

# Install PM2
sudo npm install -g pm2

# Install git
sudo apt install git

Step 3

Clone you Nodejs repository inside /var/www/html/ this path is recommended not mandatory you can clone anywhere.

Once you clone your repo, setup all your env and install dependencies ( complete your project setup ) and run a production build. ( assuming your node app is running on port 8000 )

Note: to access your port on ip like this http://192.168.3.153:8000 , you need to add this port to your AWS security group’s inbound rule . make sure you did this if you want to use your app with ip:port

To run your node app with pm2 run this script:

# if you have a file to run use this
$ pm2 start server.js --name "node_api:8000"

# if you want to run a script using pm2
$ pm2 start npm --name "node_api:8000" --run "start"

# here --name <name to your pm2 instance> & --run <script to run your app>

Step 4 ( Manual domain configuration )

Note: you can skip this step if you want to use Let’s encrypt free SSL certificate

First thing you need is a domain and you need to add this server ip to your domain provider ( go to dns configuration > add new dns record > select type: A, Name: your subdoamin, points to: ip address ).
Note: this may take few time to whitelist your ip on DNS

Open nginx default configuration file:
First navigate to /etc/nginx/sites-available
and open default file with nano editor — and add the below

For http

# configutaion for http only
server {
listen 80;
listen [::]:80;

server_name website.com;

location / {
proxy_pass http://localhost:8000;
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;
}
}

For https ( with custom SSL certificates )

# configuration for https with ssl certificates
server {
listen [::]:443 ssl;
listen 443 ssl;
server_name website.com;
ssl_certificate /etc/ssl/myApp/website_com.crt;
ssl_certificate_key /etc/ssl/myApp/server.key;
location / {
proxy_pass http://localhost:8000;
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;
}
}

# add this for automatically redirect http request to https
server {
if ($host = website.com) {
return 301 https://$host$request_uri;
}
listen 80 ;
listen [::]:80 ;
server_name staging.website.com;
return 404;
}

Step 5 & 6 ( domain configuration with let’s encrypt )

Note: you can skip this step if you want to use your custom ssl certificate.

Secure your domain with let’s encrypt (read this document)

  1. Install Certbot
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt install python3-certbot-nginx
# if this line don't work for you use python-certbot-nginx

# verify nginx configuration
$ sudo nginx -t

2. Obtaining SSL Certificate

$ sudo certbot --nginx -d example.com -d www.example.com

3. Verify Certbot Auto-Renewal

$ sudo certbot renew --dry-run

Note: the above step 3 will automatically generate ssl configuration and add certificate for that domain. you need to run this command every time for each sub domain you want to add and get new certificate for that sub domain.
to add certificate only on sub domain add -d subdomain only

$ sudo certbot --nginx -d staging.example.com

Note: after this you need to modify nginx configuration according to your requirements ( You can follow Step 4 for this ).

Most probably you need to update server location

location / {
proxy_pass http://localhost:8000;
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;
}

Once you done with all configuration and everything, restart your nginx
sudo service nginx restart or for mac: brew services restart nginx .

7. Bonus Step

a. Deploy Next js code

You can follow the same steps for next js also, as in next js you need to run a server on a port.

b. Deploy React Js or Single Page Application
( react, angular, view, html pages, etc. )

For React js, you may follow all the steps but you don’t need pm2 and you don’t need to start your server because you just need the path of your html file in your build.

Your configuration will be like this

server_name my-website.com;

# path to your build html file. & make sure there is a html file inside
root /var/www/html/react-website/build;

# add this line tell nginx to detect one of these files
index index.html index.htm index.nginx-debian.html;

# in location add this only
location / {
try_files $uri$args $uri$args/ $uri $uri/ /index.html =404;
}
}

Thank you 🙏

Happy Coding 😊
👨‍💻👨‍💻👨‍💻👨‍💻👨‍💻

--

--

Jagannath Swarnkar
Jagannath Swarnkar

Written by Jagannath Swarnkar

Sr. Software Engineer | React js | Next js | Node Js | Flutter

No responses yet