Deploy a Full-Stack App on AWS EC2 (React + Node.js)
Deploying a full-stack application on AWS EC2 is a must-have skill for frontend and full-stack developers. In this guide, we’ll deploy:
This setup is production-ready, simple, and scalable.
Architecture Overview
AWS EC2 Setup
Step 1: Launch EC2 Instance
Step 2: Connect to EC2
Open a terminal on your local computer where the .pem file is located and run the following commands:
chmod 400 my-key.pem
ssh -i my-key.pem ubuntu@<public-dns-name>
Now you are connected to the EC2 instance from your local terminal
Server Preparation
Run the following commands to refresh the list of available packages and install the new versions of installed packages.
sudo apt update
sudo apt upgrade -y
Install Node.js
# Download and install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
# in lieu of restarting the shell
\. "$HOME/.nvm/nvm.sh"
# Download and install Node.js version as per your requirement:
nvm install 24
# Verify the Node.js version:
node -v # Should print "v24.12.0".
# Verify npm version:
npm -v # Should print "11.6.2".
Frontend Deployment (React + Vite)
Step 1: Clone & Build
git clone <repo-url>
cd frontend
npm install
npm run build
This generates a dist/ folder.
Step 2: Install & Configure Nginx
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
Copy build files:
sudo scp -r dist/* /var/www/html/
Visit:
http://<public-ip>
Your frontend is now live.
Backend Deployment (Node.js + PM2)
Step 1: Allow MongoDB Access
This is required to allow your EC2 server to connect securely to the MongoDB database. MongoDB Atlas blocks all external connections by default unless the IP is explicitly whitelisted.
Step 2: Install PM2
PM2 is used to keep the Node.js backend running continuously in a production environment. It automatically restarts the server if it crashes and provides logging and monitoring.
npm install -g pm2
Step 3: Run Backend
cd backend
npm install
pm2 start npm --name "api-server" -- start
Folllwing are some useful PM2 commands:
pm2 logs
pm2 list
pm2 restart api-server
pm2 stop api-server
pm2 delete api-server
pm2 monit
pm2 flush
Ensure backend port (e.g. 7777) is allowed in the AWS Security Group.
Nginx Reverse Proxy Configuration
Step 1: Edit Nginx Config
Nginx is used to route frontend API requests (/api) to the backend server securely. This hides backend ports from public access and keeps frontend and backend on the same domain.
sudo nano /etc/nginx/sites-available/default
Step 2: Paste Configuration
server {
listen 80;
server_name <public-dns-name>;
root /var/www/html;
index index.html;
location /api/ {
proxy_pass http://localhost:<port-number>/;
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;
}
}
Restart Nginx:
sudo systemctl restart nginx
sudo systemctl status nginx
After restarting Nginx, the frontend and backend start working together seamlessly through the reverse proxy. The React (Vite) application is served as static files, while all /api requests are securely routed to the Node.js backend running under PM2, without exposing backend ports to the public.
This setup reflects a real-world production architecture: stable, secure, and easy to maintain. By combining AWS EC2, Nginx, and PM2, you gain full control over deployment, performance, and scalability while keeping costs low. Once you understand this flow, deploying full-stack applications becomes predictable and repeatable, an essential skill for any modern frontend or full-stack developer.
Happy coding!