AlmaLinuxRHEL Based

How To Install MERN Stack on AlmaLinux 10

Install MERN Stack on AlmaLinux 10

Building modern web applications requires a robust technology stack that combines efficiency, scalability, and developer productivity. The MERN Stack—MongoDB, Express.js, React.js, and Node.js—has emerged as one of the most popular full-stack JavaScript frameworks for creating dynamic, data-driven applications. When paired with AlmaLinux 10, a stable, enterprise-grade Linux distribution that serves as a community-driven alternative to Red Hat Enterprise Linux, developers gain a powerful foundation for both development and production environments. AlmaLinux 10 delivers long-term support, enhanced security features, and exceptional performance characteristics that make it ideal for hosting MERN applications. This comprehensive guide walks through the complete installation process, from initial system preparation through deploying a production-ready MERN application on AlmaLinux 10.

Prerequisites and System Requirements

Hardware Requirements

Setting up a functional MERN Stack environment demands adequate system resources. The minimum hardware specifications include a 64-bit x86_64 processor architecture, which AlmaLinux 10 requires for compatibility. Allocate at least 2 GB of RAM for basic development work, though 4 GB or more is strongly recommended when running all MERN components simultaneously. Storage requirements begin at 20 GB of available disk space, with 40 GB or greater preferred for production deployments that will accumulate data, logs, and application assets over time. Running MongoDB, Node.js development servers, React build processes, and various development tools concurrently creates meaningful resource demands that underscore the importance of adequate provisioning.

Software Prerequisites

Begin with a fresh AlmaLinux 10 installation with full root access or a user account configured with sudo privileges. Ensure all system packages are current and an active internet connection exists for downloading required software components. Familiarity with basic Linux command-line operations, text editors such as nano or vi, and fundamental JavaScript concepts will facilitate the installation process. Understanding of client-server architecture and REST API principles proves beneficial but is not strictly mandatory for following this tutorial.

Security Considerations

Plan firewall configurations before beginning installation. MongoDB typically operates on port 27017, while Node.js development servers commonly use ports 3000 and 5000. Production deployments may require additional port configurations depending on the chosen hosting architecture and reverse proxy setup.

Step 1: Update AlmaLinux 10 System

System updates form the foundation of secure server management. Open a terminal session and execute the complete system update command:

sudo dnf update -y

This command refreshes package repositories and installs all available security patches and software updates. The -y flag automatically confirms installation prompts, streamlining the update process. System updates protect against known vulnerabilities and ensure package compatibility with newer software versions.

Install essential development tools required for compiling native Node.js modules and building software from source:

sudo dnf groupinstall "Development Tools" -y

This group installation provides gcc, g++, make, and other compilation utilities. Additionally, install fundamental utilities:

sudo dnf install git curl wget -y

Git enables version control for project files, while curl and wget facilitate downloading installation scripts and software packages. Verify successful installation by checking version information:

git --version
curl --version

Expected output displays version numbers, confirming proper installation.

Step 2: Install Node.js and NPM

NodeSource Repository Method

AlmaLinux default repositories typically contain older Node.js versions. The NodeSource repository provides access to current Long-Term Support releases. Download and execute the NodeSource setup script for Node.js 24.x LTS:

curl -fsSL https://rpm.nodesource.com/setup_24.x | sudo bash -

This script configures the NodeSource repository on the system. The -fsSL flags ensure silent operation with failed request handling and redirect following. After repository configuration completes, install Node.js:

sudo dnf install nodejs -y

This single package includes both the Node.js runtime and NPM package manager. Using NodeSource repositories instead of default AlmaLinux packages ensures access to modern JavaScript features, performance improvements, and active security maintenance.

Verification

Confirm successful installation by checking installed versions:

node -v
npm -v

Expected output shows Node.js version 24.x and NPM version 10.x or higher. Version mismatches or command-not-found errors indicate installation problems requiring troubleshooting.

Global NPM Configuration

Avoid permission-related issues during global package installation by configuring NPM to use a user-owned directory:

mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

This configuration redirects global packages to the home directory, eliminating the need for sudo when installing global utilities.

Step 3: Install and Configure MongoDB

Adding MongoDB Repository

MongoDB requires manual repository configuration on AlmaLinux 10. Create a new repository file:

sudo nano /etc/yum.repos.d/mongodb-org-8.0.repo

Add the following repository configuration for MongoDB 8.0:

[mongodb-org-8.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-8.0.asc

Save and exit the editor. This configuration specifies the MongoDB package source, enables GPG signature verification for security, and provides the public key location for package authentication.

Installing MongoDB Server

Execute the MongoDB installation command:

sudo dnf install mongodb-org -y

This meta-package installs multiple components: mongodb-org-server (the database daemon), mongodb-org-mongos (sharding router), mongodb-org-shell (command-line client), and mongodb-org-tools (import/export utilities).

Starting and Enabling MongoDB

Start the MongoDB service immediately:

sudo systemctl start mongod

Enable automatic startup on system boot:

sudo systemctl enable mongod

Verify the service is running properly:

sudo systemctl status mongod

Active status with “running” confirmation indicates successful startup. Press ‘q’ to exit the status display.

Securing MongoDB

Fresh MongoDB installations lack authentication, creating security vulnerabilities. Connect to MongoDB shell:

mongosh

Create an administrative user:

use admin
db.createUser({
  user: "admin",
  pwd: "StrongPassword123!",
  roles: [{role: "userAdminAnyDatabase", dbOwner: "admin"}]
})

Replace “StrongPassword123!” with a secure password. Exit the shell with exit. Enable authentication by editing the MongoDB configuration:

sudo nano /etc/mongod.conf

Locate the security section and uncomment or add:

security:
  authorization: enabled

Save the file and restart MongoDB:

sudo systemctl restart mongod

Test authenticated access:

mongosh -u admin -p

Enter the password when prompted. Successful authentication confirms proper security configuration.

Firewall Configuration

If remote MongoDB access is required, open the appropriate firewall port:

sudo firewall-cmd --permanent --add-port=27017/tcp
sudo firewall-cmd --reload

For development environments, restricting MongoDB to localhost connections is recommended for enhanced security.

Step 4: Set Up Project Directory Structure

Organized project structure facilitates maintenance and scalability. Create a main project directory:

mkdir -p ~/mern-almalinux
cd ~/mern-almalinux

The MERN architecture separates concerns between backend API logic and frontend user interface. This separation enables independent development, testing, and deployment of each layer. Initialize version control:

git init

Create a .gitignore file to exclude sensitive and unnecessary files:

nano .gitignore

Add the following entries:

node_modules/
.env
build/
dist/
*.log

This prevents committing dependencies, environment variables, and build artifacts to version control.

Step 5: Build the Backend (Express + Node.js)

Initialize Backend Directory

Create and navigate to the backend folder:

mkdir backend
cd backend

Initialize a new Node.js project:

npm init -y

The -y flag accepts default values, generating a package.json file that manages project metadata and dependencies.

Install Backend Dependencies

Install core backend packages:

npm install express mongoose cors dotenv

Express.js provides the web application framework, Mongoose offers elegant MongoDB object modeling, CORS enables cross-origin resource sharing, and dotenv loads environment variables from files. Install development dependency:

npm install --save-dev nodemon

Nodemon automatically restarts the server when file changes are detected, improving development workflow.

Environment Variables Configuration

Create an environment file:

nano .env

Add configuration variables:

PORT=5000
MONGO_URI=mongodb://admin:StrongPassword123!@localhost:27017/merndb?authSource=admin

Replace the password with the actual MongoDB admin password. Never commit this file to version control repositories.

Create Mongoose Model

Establish a models directory:

mkdir models
nano models/Item.js

Define a sample data model:

const mongoose = require('mongoose');

const ItemSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  description: {
    type: String,
    default: ''
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('Item', ItemSchema);

This schema defines an Item collection with name, description, and timestamp fields. Mongoose handles validation and database interactions.

Build Express Server

Create the main server file:

nano server.js

Implement the Express application:

require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const Item = require('./models/Item');

const app = express();
const PORT = process.env.PORT || 5000;

// Middleware
app.use(cors());
app.use(express.json());

// MongoDB Connection
mongoose.connect(process.env.MONGO_URI)
  .then(() => console.log('MongoDB connected successfully'))
  .catch(err => console.error('MongoDB connection error:', err));

// Routes
app.get('/api/items', async (req, res) => {
  try {
    const items = await Item.find().sort({ createdAt: -1 });
    res.json(items);
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

app.post('/api/items', async (req, res) => {
  try {
    const item = new Item({
      name: req.body.name,
      description: req.body.description
    });
    const newItem = await item.save();
    res.status(201).json(newItem);
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
});

app.delete('/api/items/:id', async (req, res) => {
  try {
    await Item.findByIdAndDelete(req.params.id);
    res.json({ message: 'Item deleted' });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

// Start Server
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

This server implements RESTful endpoints for creating, reading, and deleting items.

Package.json Scripts

Edit package.json to add convenience scripts:

nano package.json

Modify the scripts section:

"scripts": {
  "start": "node server.js",
  "dev": "nodemon server.js"
}

The dev script enables hot-reloading during development.

Step 6: Create the Frontend (React.js)

Initialize React Application

Navigate to the project root and create a React application using Vite:

cd ~/mern-almalinux
npm create vite@latest frontend -- --template react

Vite provides faster build times and superior development experience compared to traditional Create React App. Navigate to the frontend directory:

cd frontend
npm install

This installs all React dependencies.

Install Frontend Dependencies

Add Axios for HTTP requests:

npm install axios

Axios simplifies API communication with promise-based syntax.

Configure API Connection

Create an API service file:

mkdir src/services
nano src/services/api.js

Configure the Axios instance:

import axios from 'axios';

const api = axios.create({
  baseURL: 'http://localhost:5000/api'
});

export default api;

This centralized configuration simplifies endpoint management.

Build React Components

Edit the main App component:

nano src/App.jsx

Implement the application logic:

import { useState, useEffect } from 'react';
import api from './services/api';
import './App.css';

function App() {
  const [items, setItems] = useState([]);
  const [name, setName] = useState('');
  const [description, setDescription] = useState('');

  useEffect(() => {
    fetchItems();
  }, []);

  const fetchItems = async () => {
    try {
      const response = await api.get('/items');
      setItems(response.data);
    } catch (error) {
      console.error('Error fetching items:', error);
    }
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await api.post('/items', { name, description });
      setName('');
      setDescription('');
      fetchItems();
    } catch (error) {
      console.error('Error creating item:', error);
    }
  };

  const handleDelete = async (id) => {
    try {
      await api.delete(`/items/${id}`);
      fetchItems();
    } catch (error) {
      console.error('Error deleting item:', error);
    }
  };

  return (
    <div className="container">
      <h1>MERN Stack on AlmaLinux 10</h1>
      
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="Item name"
          value={name}
          onChange={(e) => setName(e.target.value)}
          required
        />
        <input
          type="text"
          placeholder="Description"
          value={description}
          onChange={(e) => setDescription(e.target.value)}
        />
        <button type="submit">Add Item</button>
      </form>

      <div className="items-list">
        <h2>Items</h2>
        {items.map(item => (
          <div key={item._id} className="item">
            <h3>{item.name}</h3>
            <p>{item.description}</p>
            <small>{new Date(item.createdAt).toLocaleString()}</small>
            <button onClick={() => handleDelete(item._id)}>Delete</button>
          </div>
        ))}
      </div>
    </div>
  );
}

export default App;

This component manages state with React hooks, fetches data from the backend, and provides a user interface for CRUD operations.

Styling Considerations

Add basic styling to App.css:

nano src/App.css

Include responsive, clean styles that enhance usability without overwhelming complexity.

CORS Configuration

The Express CORS middleware enables the React development server (typically port 5173) to communicate with the backend on port 5000. Alternative approaches include configuring Vite’s proxy settings to avoid CORS entirely during development.

Step 7: Testing the MERN Application

Running Backend Server

Open a terminal session and start the backend:

cd ~/mern-almalinux/backend
npm run dev

Successful output displays “MongoDB connected successfully” and “Server running on port 5000”. Leave this terminal running.

Running Frontend Server

Open a second terminal and start React:

cd ~/mern-almalinux/frontend
npm run dev -- --host 0.0.0.0

The --host flag allows external access, useful for server deployments. Vite displays the local access URL, typically http://localhost:5173.

Testing CRUD Operations

Access the application through a web browser. Test the CREATE operation by entering an item name and clicking “Add Item”. The interface should refresh, displaying the new entry retrieved from MongoDB. This demonstrates the complete data flow: React frontend → Express API → MongoDB database → Express response → React update. Test DELETE functionality by clicking the delete button on any item. Verify data persists by stopping and restarting both servers.

MongoDB Verification

Connect to MongoDB shell:

mongosh -u admin -p

Query the database directly:

use merndb
db.items.find().pretty()

This displays all stored documents, confirming successful data persistence.

Step 8: Production Deployment with PM2

Installing PM2 Process Manager

PM2 ensures Node.js applications remain running, automatically restart after crashes, and survive system reboots. Install PM2 globally:

npm install pm2@latest -g

Verify installation:

pm2 --version

Building Production React App

Navigate to the frontend directory and create an optimized production build:

cd ~/mern-almalinux/frontend
npm run build

Vite generates minified, optimized static files in the dist directory.

Configuring Express for Production

Modify the backend to serve React static files. Edit server.js:

cd ~/mern-almalinux/backend
nano server.js

Add before the route definitions:

const path = require('path');

// Serve static files in production
if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, '../frontend/dist')));
  
  app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, '../frontend/dist/index.html'));
  });
}

This configuration serves the React application from Express, eliminating the need for separate frontend hosting.

Starting Backend with PM2

Launch the application with PM2:

cd ~/mern-almalinux/backend
NODE_ENV=production pm2 start server.js --name mern-backend

View running processes:

pm2 list

The application appears with status “online”.

PM2 Configuration

Save the current PM2 configuration:

pm2 save

Generate a startup script:

pm2 startup

Execute the command PM2 displays to enable automatic startup. This ensures the application restarts after system reboots.

Process Monitoring

Monitor application performance in real-time:

pm2 monit

View application logs:

pm2 logs mern-backend

Restart the application:

pm2 restart mern-backend

Reload with zero downtime:

pm2 reload mern-backend

Stop the application:

pm2 stop mern-backend

These commands provide comprehensive process management capabilities.

Step 9: Security Best Practices

Environment Security

Never expose sensitive credentials in code or version control. Environment files remain local only. Use environment-specific configurations for development, staging, and production environments. Consider using secret management services for production deployments.

MongoDB Security

Implement strong password policies requiring complexity, length, and regular rotation. Configure MongoDB’s bind_ip directive to restrict network access:

net:
  bindIp: 127.0.0.1

This limits connections to localhost only. Implement regular backup strategies using mongodump:

mongodump --uri="mongodb://admin:password@localhost:27017" --out=/backup/mongodb

Application Security

Validate and sanitize all user inputs to prevent injection attacks. Install and configure Helmet.js for Express:

npm install helmet

Add to server.js:

const helmet = require('helmet');
app.use(helmet());

Implement rate limiting to prevent abuse:

npm install express-rate-limit

Configure limits based on endpoint sensitivity. Deploy HTTPS with SSL/TLS certificates in production using Let’s Encrypt or commercial certificate authorities.

Firewall Configuration

Configure AlmaLinux firewall for production:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --remove-port=3000/tcp
sudo firewall-cmd --permanent --remove-port=5000/tcp
sudo firewall-cmd --reload

Expose only necessary ports while closing development-specific ports.

Updates and Maintenance

Regularly audit dependencies for vulnerabilities:

npm audit

Address identified issues:

npm audit fix

Update packages systematically:

npm update

Keep AlmaLinux system packages current:

sudo dnf update -y

Establish maintenance schedules for security patches and updates.

Step 10: Troubleshooting Common Issues

Connection Problems

MongoDB connection failures often stem from incorrect connection strings. Verify service status:

sudo systemctl status mongod

Ensure authentication credentials match those created during setup. CORS errors between frontend and backend typically indicate missing CORS middleware or incorrect origin configuration. Verify the backend CORS setup accepts requests from the frontend URL.

Installation Errors

Node.js version incompatibilities cause obscure errors. Verify the installed version matches application requirements:

node -v

MongoDB repository configuration issues on AlmaLinux 10 may require manual verification of repository files and GPG keys. NPM permission errors when installing global packages indicate incorrect directory permissions. Reconfigure NPM prefix as described in the Node.js installation section.

Runtime Errors

Express server errors often relate to missing dependencies or syntax errors. Check server logs:

npm run dev

Examine error messages carefully. React build failures typically stem from dependency conflicts. Delete node_modules and package-lock.json, then reinstall:

rm -rf node_modules package-lock.json
npm install

PM2 process crashes require log analysis:

pm2 logs mern-backend --lines 100

Identify error patterns and address underlying causes.

Performance Issues

Optimize MongoDB queries using indexes. Create indexes on frequently queried fields:

db.items.createIndex({ createdAt: -1 })

Reduce React bundle size by implementing code splitting and lazy loading:

const Component = lazy(() => import('./Component'));

Configure PM2 cluster mode for load balancing across CPU cores:

pm2 start server.js -i max

This spawns worker processes matching available CPUs.

Congratulation’s! You have successfully installed MERN. Thanks for using this tutorial for installing the MERN Stack on your AlmaLinux OS 10 system. For additional help or useful information, we recommend you check the official MERN website.

VPS Manage Service Offer
If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get a best deal!

r00t

r00t is an experienced Linux enthusiast and technical writer with a passion for open-source software. With years of hands-on experience in various Linux distributions, r00t has developed a deep understanding of the Linux ecosystem and its powerful tools. He holds certifications in SCE and has contributed to several open-source projects. r00t is dedicated to sharing her knowledge and expertise through well-researched and informative articles, helping others navigate the world of Linux with confidence.
Back to top button