π Deploying a Node.js App on AWS EC2 with PM2 and NGINX (Day 22 of #90DaysOfCloud)

Table of contents
- βοΈ Part 1: Launching the EC2 Instance
- π Part 2: SSH into EC2 Instance
- π§± Part 3: Install Node.js and NPM
- ποΈ Part 4: Create Your Node.js Application
- π Part 5: Test the Application
- π Part 6: Run App in Background using PM2
- π Part 7: Configure NGINX as Reverse Proxy
- β Final Result
- π Tips & Best Practices
- β Summary
- π Whatβs Next?

Todayβs cloud journey was all about building and hosting a Node.js application from scratch on an AWS EC2 instance, without using Docker. I went from provisioning the server to configuring the application and making it available through a web browser β using PM2 for background processing and NGINX as a reverse proxy.
Letβs go step-by-step π
βοΈ Part 1: Launching the EC2 Instance
1οΈβ£ Go to AWS EC2 Console β Launch Instance
2οΈβ£ Choose AMI:
- Amazon Linux 2 (Free tier eligible)
3οΈβ£ Choose Instance Type:
t2.micro
(Free tier)
4οΈβ£ Configure Key Pair:
- Create or use existing key pair (e.g.,
my-key.pem
)
5οΈβ£ Configure Security Group (Allow only):
Port 22 (SSH) β Your IP only
Port 80 (HTTP) β Anywhere
(Optional) Port 3000 β for direct app testing
6οΈβ£ Launch the instance
π Part 2: SSH into EC2 Instance
After launching:
ssh -i "my-key.pem" ec2-user@<your-ec2-public-ip>
Replace <your-ec2-public-ip>
with your EC2 instanceβs public IP.
π§± Part 3: Install Node.js and NPM
Update system and install required packages:
sudo yum update -y
sudo yum install nodejs -y
sudo yum install npm -y
Verify installation:
node -v
npm -v
ποΈ Part 4: Create Your Node.js Application
Step 1: Create Project Directory
mkdir nodeapp
cd nodeapp
Step 2: Initialize and Create Files
Create package.json
vim package.json
Paste:
jsonCopyEdit{
"name": "nodeapp",
"version": "1.0.0",
"description": "Simple Node.js App",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.18.2"
}
}
Create app.js
vim app.js
Paste:
javascriptCopyEditconst express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello from Node.js app on EC2!');
});
const port = 3000;
app.listen(port, () => {
console.log(`App running on port ${port}`);
});
Step 3: Install Dependencies
npm install
π Part 5: Test the Application
Run the app:
node app.js
Open browser and visit:
http://<your-ec2-public-ip>:3000
If it works, press Ctrl + C
to stop it for now.
π Part 6: Run App in Background using PM2
Step 1: Install PM2 globally
sudo npm install -g pm2
Step 2: Start the app using PM2
pm2 start app.js
Step 3: Auto-start on reboot
pm2 startup
Follow the command it gives you (usually something like sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u ec2-user --hp /home/ec2-user
)
Then run:
pm2 save
App will now persist across reboots!
π Part 7: Configure NGINX as Reverse Proxy
Step 1: Install NGINX
sudo yum install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
Step 2: Edit NGINX Config
sudo vim /etc/nginx/nginx.conf
In the server
block, add this inside the location /
:
location / {
proxy_pass http://localhost:3000;
}
Example section:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:3000;
}
}
Step 3: Restart NGINX
sudo systemctl restart nginx
β Final Result
Now you can visit:
http://<your-ec2-public-ip>
π You should see: Hello from Node.js app on EC2!
π Tips & Best Practices
Open only required ports in security groups (22, 80)
Use PM2 for production-grade Node.js app management
Use NGINX to proxy requests (avoid exposing port 3000)
Backup your key file (
my-key.pem
) safelyEnable auto-restart on reboot with
pm2 startup && pm2 save
β Summary
On Day 22, I learned to:
Launch an EC2 instance from scratch
Install and configure Node.js and NGINX
Serve an app via PM2 and expose it with a clean public URL
Use Linux terminal, Vim, and systemctl efficiently
π Whatβs Next?
On Day 23, Iβll be deploying a Python Flask application on an EC2 instance β just like we did with Node.js.
π§ Iβll cover:
Installing Python & pip on EC2
Setting up a Flask web app
Running it in the background with Gunicorn or PM2
Exposing it using NGINX as a reverse proxy
Securing ports and handling multiple app deployments
This will strengthen my experience in hosting apps using different backends and prepare me for multi-language DevOps workflows! π
Subscribe to my newsletter
Read articles from Pratik Das directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
