In this article we are going to cover Deploy MERN Stack Web App on Ubuntu 24.04 LTS.
we will set up a real-time chat application using the MERN (MongoDB, Express.js, React, Node.js) stack and deploy it on an AWS EC2 instance. This guide provides a step-by-step approach to installing the necessary dependencies, configuring the backend and frontend, and deploying the application using PM2.
Table of Contents
Prerequisites
Before proceeding, ensure you have the following:
- AWS Account with Ubuntu 24.04 LTS EC2 Instance choose type t3.medium.
- Node.js and npm installed
- MongoDB installed on the EC2 instance
- Basic knowledge of JavaScript, React, and Node.js
Set up MERN Stack Web App on Ubuntu 24.04 LTS.
Below diagram represents the architecture of a MERN stack web application deployed on an Ubuntu 24.04 LTS server. Let’s setup MERN Stack web app on Ubuntu 24.04 LTS EC2 instance.

This task provides a step-by-step procedure to installing the necessary dependencies, configuring the backend and frontend, and deploying the application using PM2.
Step #1:Update and Install Required Packages on Ubuntu 24.04 LTS
First update the system’s package index.
sudo apt update

Install required dependencies (build-essential
and curl
):
sudo apt install -y build-essential curl

Step #2:Install Node.js and npm on Ubuntu 24.04 LTS
This command installs the latest LTS (Long-Term Support) version of Node.js from NodeSource on your Ubuntu 24.04 LTS instance.
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash

After running the command, install Node.js on Ubuntu 24.04 LTS using apt package manager
sudo apt install -y nodejs

After installing Node.js, confirm that it has been installed correctly by checking its version with the following command:
node -v

The Node.js package from NodeSource includes npm
by default.
To verify that npm
was installed, run:
npm -v

Step #3:Install MongoDB on Ubuntu 24.04 LTS
It displays information about the installed Ubuntu version.
cat /etc/lsb-release

Before installing MongoDB, its repository needs to be trusted by the system. To do this, import the MongoDB public GPG key using the following command:
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \
--dearmor

After importing the GPG key, add the official MongoDB repository to the system’s package sources by running the following command.
Create the list file /etc/apt/sources.list.d/mongodb-org-8.0.list
for Ubuntu 24.04 (Noble)
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list


Reload the package index.
sudo apt-get update

Install MongoDB on Ubuntu 24.04 LTS system
sudo apt-get install -y mongodb-org

Start MongoDB on Ubuntu 24.04 LTS system
sudo systemctl start mongod

Enable MongoDB on Ubuntu 24.04 LTS system
sudo systemctl enable mongod

Verify status of MongoDB on Ubuntu 24.04 LTS system
sudo systemctl status mongod

Step #4:Setting Up the MERN stack web App on Ubuntu 24.04 LTS
Let’s create MERN stack web app directory to store entire application with name “mern-realtime-app” and navigate to mern-realtime-app directory
mkdir mern-realtime-app
cd mern-realtime-app

Create folders of MERN stack web app for frontend and backend.
mkdir -p backend frontend
ls

Step #5:Set Up Backend with Express and Socket.io on Ubuntu 24.04 LTS
Initialize the Backend Project : Navigate to your backend directory.
cd backend

To create a new Node.js project and generate a default package.json
file, run the following command:
npm init -y


To set up the backend for your MERN web app, install the necessary Node.js packages by running the following command:
npm install express socket.io cors mongoose dotenv

express
: Web framework for handling API requests.socket.io
: Enables real-time communication between clients and the server.cors
: Allows cross-origin requests.mongoose
: Helps in interacting with MongoDB.dotenv
: Manages environment variables.

Step #6:Create Backend Server for MERN project on Ubuntu 24.04 LTS
Create a file named server.js
.
touch server.js
ls

open the file server.js and add the following code.
nano server.js

require("dotenv").config();
const express = require("express");
const http = require("http");
const socketIo = require("socket.io");
const mongoose = require("mongoose");
const cors = require("cors");
const app = express();
const server = http.createServer(app);
const io = socketIo(server, {
cors: { origin: "*" }
});
app.use(cors());
app.use(express.json());
// MongoDB Connection
mongoose.connect(process.env.MONGO_URI)
.then(() => console.log("MongoDB Connected"))
.catch(err => console.log("MongoDB Connection Error:", err));
// Message Schema
const MessageSchema = new mongoose.Schema({ text: String });
const Message = mongoose.model("Message", MessageSchema);
// WebSocket Connection
io.on("connection", (socket) => {
console.log("New client connected");
// Handle incoming messages
socket.on("message", async (data) => {
const message = new Message({ text: data });
await message.save();
io.emit("message", data);
});
socket.on("disconnect", () => {
console.log("Client disconnected");
});
});
// API Route
app.get("/", (req, res) => res.send("Server is running"));
// API Endpoint to Save Messages
app.post("/api/messages", (req, res) => {
const { message } = req.body;
if (!message) {
return res.status(400).json({ success: false, error: "Message is required" });
}
console.log(`Message received: ${message}`);
res.status(200).json({ success: true, message: "Message received" });
});
// Start Server
const PORT = process.env.PORT || 5000;
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Explanation of server.js
:
- Import Required Packages: Loads
express
,http
,socket.io
,mongoose
, andcors
. - Set Up Express Server: Creates an Express app and HTTP server.
- MongoDB Connection: Uses
MONGO_URI
from the.env
file to connect to MongoDB. - Message Schema: Defines a
Message
model for storing chat messages. - WebSocket Communication:
- Listens for new messages from clients.
- Saves messages to MongoDB.
- Broadcasts messages to all connected users.
- API Routes:
GET /
: Simple test route.POST /api/messages
: Accepts new messages via API.
Step #7:Create Environment File for MERN Project on Ubuntu 24.04 LTS
To securely store environment variables like database connection details, create a .env
file in your project root directory
Create a .env
file in the backend
folder:
touch .env

Open the .env file from backend folder.
nano .env

This is the MongoDB connection string that tells your backend how to connect to your local MongoDB database.
Add the below string into .env file.
MONGO_URI=mongodb://localhost:27017/realtime-chat
PORT=5000
mongodb://
→ Specifies that we’re using MongoDB.localhost
→ Refers to the database running on the same machine (EC2 instance).27017
→ Default MongoDB port.realtime-chat
→ Name of the database where chat data will be stored.- Port 5000 is commonly used as a development server port, especially for Node.js and Express.js applications

Save and exit.
To start your Node.js application, navigate to the backend directory your server.js
file is located and run the following command in your terminal.
node server.js

Running node server.js
starts your Express.js and Socket.io backend, allowing your application to handle requests and real-time communication.
Step #8:Set Up Frontend with React for MERN Project on Ubuntu 24.04 LTS
In this step we create a frontend React app using Vite, install dependencies, and set up Socket.io for real-time communication.
To create a new React project using Vite, navigate to the parent directory of your project and run the following command:
cd ..
npm create vite@latest frontend -- --template react

Navigate into Your Project directory frontend
cd frontend

After navigating to frontend directory, run the following command to install all the required dependencies:
npm install

To enable real-time communication in your React application, you’ll need to install the socket.io-client
library. In your frontend
directory, run the following command:
npm install socket.io-client

Step #9:Create Chat Component for MERN Project on Ubuntu 24.04 LTS
To start editing the main component of your React application, open the App.jsx
file using the nano
text editor. Run the following command in your terminal:
nano src/App.jsx

Replace the existing code with the following:
import { useEffect, useState } from "react";
import io from "socket.io-client";
const socket = io("ws://your-ec2-public-ip:5000"); // Use Public IP
function Chat() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState("");
useEffect(() => {
socket.on("message", (message) => {
setMessages((prev) => [...prev, message]);
});
return () => socket.off("message");
}, []);
const sendMessage = () => {
if (input.trim()) {
socket.emit("message", input);
setInput("");
}
};
return (
<div style={styles.container}>
<h2 style={styles.title}>💬 Real-Time Chat</h2>
<div style={styles.chatBox}>
{messages.map((msg, index) => (
<p key={index} style={styles.message}>{msg}</p>
))}
</div>
<div style={styles.inputContainer}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Type a message..."
style={styles.input}
/>
<button onClick={sendMessage} style={styles.button}>Send</button>
</div>
</div>
);
}
// Styling object
const styles = {
container: {
maxWidth: "500px",
margin: "40px auto",
padding: "20px",
border: "1px solid #ddd",
borderRadius: "8px",
boxShadow: "0 2px 10px rgba(0,0,0,0.1)",
backgroundColor: "#fff",
fontFamily: "Arial, sans-serif",
textAlign: "center"
},
title: {
color: "#333",
},
chatBox: {
height: "300px",
overflowY: "auto",
border: "1px solid #ddd",
padding: "10px",
borderRadius: "5px",
backgroundColor: "#f9f9f9",
textAlign: "left",
},
message: {
background: "#e3f2fd",
padding: "10px",
borderRadius: "5px",
margin: "5px 0",
display: "inline-block",
maxWidth: "80%",
},
inputContainer: {
display: "flex",
marginTop: "10px",
},
input: {
flex: 1,
padding: "10px",
borderRadius: "5px",
border: "1px solid #ccc",
},
button: {
marginLeft: "10px",
padding: "10px 15px",
border: "none",
borderRadius: "5px",
backgroundColor: "#007bff",
color: "white",
cursor: "pointer",
}
};
export default Chat;

This component connects to the WebSocket server, listens for incoming messages, and provides an input field to send messages.
Change localhost with public_ip in socket.io() method for src/App.jsx file.

Step #10:Add Port 5173 in AWS Security Group (EC2) instance on Ubuntu 24.04 LTS
To allow incoming traffic on port 5173 (the default port for Vite development servers) to your EC2 instance, you’ll need to update the security group settings in AWS. Follow these steps:
- Go to the AWS Management Console.
- Navigate to EC2 and select Security Groups from the left-hand menu.
- Find the security group associated with your EC2 instance and click on its ID to open the settings.
- Under the Inbound rules tab, click on Edit inbound rules.
- Add a new rule with the following settings:
- Type: Custom TCP Rule
- Port Range: 5173
- Source: Anywhere (or specify a specific IP range for more security)
- Click Save rules.
Step #11:Deploy Backend Using PM2 for MERN Project on Ubuntu 24.04 LTS
What is PM2?
PM2 (Process Manager 2) is a production-grade process manager for Node.js applications. It helps keep your app running continuously, even after a server reboot or crash.
Navigate to parent directory and install PM2.
cd ..
sudo npm install -g pm2

After installing the PM2 verify the version.
pm2 -v

After installing PM2,navigate to backend directory And start the backend server with PM2
cd backend
pm2 start server.js --name backend


Save the process list (so it restarts automatically on reboot)
pm2 save

To configure PM2 to start your application automatically when the system reboots, run the following command:
pm2 startup

To view the logs of your backend application managed by PM2, run the following command in your terminal:
pm2 logs backend

Navigate first parent directory after that to the frontend directory.
cd ..
cd frontend


To start your React development server and make it accessible on your local network, run the following command:
npm run dev -- --host

Step #12:Test Web Chat Application
Open http://your-ec2-public-ip:5173 in a browser(Replace with your EC2-ip)
Open two browser tabs (or use two different devices) with url http://your-ec2-public-ip:5173
Type a message (e.g., “Hi”) in first tab and click Send.

Now, you will see the message “hii” in first tab.

Now, open second tab to see the same message “hii”

The message should instantly appear in both tabs without any refreshing.
Step #13:Viewing Stored Messages in MongoDB on Ubuntu 24.04 LTS.
After Sending a Message in the Chat App check if messages are stored in MongoDB.
1.Open MongoDB shell:
mongosh

2.Show databases:
show dbs

3.Switch to the chat database:
use realtime-chat

4.View stored messages:
db.messages.find().pretty()
You should see all the stored chat messages in mongodb even if you refresh the page it will store the messages.

Conclusion:
You have successfully deployed a real-time chat application using the MERN stack on an AWS EC2 instance. By setting up Express for the backend, React for the frontend, MongoDB for data storage, and WebSockets for real-time communication, you have built a functional and interactive chat system. Additionally, you configured PM2 to manage the backend process efficiently and ensured the server remains active.
Related Articles:
Multi Tier WebApp with Python Django and PostgreSQL
Reference: