Deploying MERN on AWS EC2
This documentation provides a strict, step-by-step workflow to deploy a full-stack MERN application. It covers everything from setting up cloud security groups to configuring Nginx as a reverse proxy and securing file permissions.
0 Required Software & Tools
Ensure you have the following installed on your local machine to follow this guide.
Node.js (LTS)
v18 or higher
Git & GitHub
Version Control
VS Code
Editor
MongoDB
Compass GUI or Atlas (Cloud-Based DB)
1 Prerequisites & Policies
| Type | Port | Source | Reason |
|---|---|---|---|
| SSH | 22 | My IP (Recommended) | Remote server access |
| HTTP | 80 | Anywhere (0.0.0.0/0) | Frontend web traffic |
| HTTPS | 443 | Anywhere (0.0.0.0/0) | Secure SSL traffic |
| Custom TCP | 5000 | Custom Port (5000) | To test your Backend API directly |
MongoDB Atlas Network Access
Don't forget to whitelist 0.0.0.0/0 (Allow Anywhere) or your EC2 Public IP in
MongoDB Atlas under Network Access, otherwise the backend will crash on
connection timeout.
2 Local Development Setup
Run these commands on your local machine to prepare the project structure.
npm init -y
npm install express mongoose cors dotenv
npm create vite@latest frontend -- --template react
cd frontend
npm install lucide-react
npm install -D tailwindcss@3 postcss autoprefixer
npx tailwindcss init -p
3 Server Setup (EC2)
Connect to your instance via SSH and install the environment.
# Update OS
sudo apt update && sudo apt upgrade -y
# Install Node.js v20 (Source)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Verify installation
node -v
npm -v
sudo apt install git -y
git clone <YOUR_REPO_LINK>
# 1. Setup Backend
cd <REPO_NAME>/backend
npm install
nano .env
# (Paste MONGO_URI, PORT=5000, JWT_SECRET)
# 2. Setup Frontend
cd ../frontend
npm install
npm run build
Use My Repository
For testing, you can clone my Expense Tracker repo.
Support my work by starring ⭐ the repo!
# 1. Clone the Repository
git clone https://github.com/Thanvirassif731/personal-expense-tracker-ash-web-app.git
# 2. Setup Backend
cd personal-expense-tracker-ash-web-app/backend
npm install
nano .env
# (Paste MONGO_URI, PORT=5000, JWT_SECRET)
# 3. Setup Frontend
cd ../frontend
npm install
npm run build
4 Process Management (PM2)
PM2 keeps the Node.js backend alive forever, even after server reboots.
# Install Globally
sudo npm install -g pm2
# Start Backend (Execute inside backend folder)
pm2 start server.js --name "expense-backend"
# Freeze process list
pm2 save
pm2 startup
5 Web Server (Nginx)
Install Nginx and configure it as a Reverse Proxy.
server {
listen 80;
server_name _;
# 1. Serve React Frontend
# UPDATE THIS PATH to match your actual build folder!
root /home/ubuntu/<REPO_NAME>/frontend/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 2. Proxy API Requests to Backend
location /api {
proxy_pass http://localhost:5000;
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;
}
}
6. Permission Policies (Crucial)
Most deployments fail with 403 Forbidden or 500 Internal Error because
Nginx (running as www-data) cannot read files owned by ubuntu. Apply
both fixes below.
A. Fix Directory Permissions
chmod 755 /home/ubuntu
chmod 755 /home/ubuntu/<REPO_NAME>
chmod 755 /home/ubuntu/<REPO_NAME>/frontend
chmod 755 /home/ubuntu/<REPO_NAME>/frontend/dist
B. Nginx User Policy Override
- Open config:
sudo nano /etc/nginx/nginx.conf - Find line:
user www-data; - Change to:
user ubuntu; - Save & Exit.
7 Go Live
sudo nginx -t
sudo systemctl restart nginx
🎉 Deployment Complete!
Visit your Public IP address in the browser to see your MERN app live.