Ash-Docs
Updated for Ubuntu 24.04 LTS

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.

js

Node.js (LTS)

v18 or higher

Git & GitHub

Version Control

VS Code

Editor

MongoDB

Compass GUI or Atlas (Cloud-Based DB)

1 Prerequisites & Policies

AWS Security Group (Inbound Rules)
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.

Backend Initialization
npm init -y
npm install express mongoose cors dotenv
Frontend Initialization (Vite + Tailwind)
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.

Install Node.js v20 (LTS) & Git
# 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
Clone & Configure Code
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!

Star on GitHub
Clone & Configure Code
# 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.

PM2 Configuration
# 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.

File path: /etc/nginx/sites-available/default
Nginx Config Block
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

Run in Home Directory
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

  1. Open config: sudo nano /etc/nginx/nginx.conf
  2. Find line: user www-data;
  3. Change to: user ubuntu;
  4. Save & Exit.

7 Go Live

Restart Services
sudo nginx -t
sudo systemctl restart nginx

🎉 Deployment Complete!

Visit your Public IP address in the browser to see your MERN app live.

Thanvir Assif

Created by Thanvir Assif

Cloud & DevOps Engineer | AWS Certified | Full Stack Developer. Helping professionals and enthusiasts master cloud deployments.

© 2026 Thanvir Assif. All rights reserved.