android
+
mvn
+
+
+
parcel
+
+
+
+
stimulus
+
wsl
+
backbone
<-
webpack
+
+
mocha
babel
azure
+
+
+
gradle
git
+
+
+
+
+
fedora
jenkins
+
<-
+
=>
+
+
+
+
+
|>
+
+
+
--
rider
meteor
numpy
sqlite
+
+
debian
+
+
fauna
ember
+
flask
+
+
node
+
gin
+
+
aws
+
gitlab
+
ocaml
+
hugging
+
+
...
+
+
+
@
macos
jquery
+
+
vb
+
elementary
Back to Blog
๐Ÿš€ Node.js Development Environment Setup on AlmaLinux: Complete Guide
Node.js Installation JavaScript Development AlmaLinux Node.js

๐Ÿš€ Node.js Development Environment Setup on AlmaLinux: Complete Guide

Published Sep 14, 2025

Set up Node.js development environment on AlmaLinux with this comprehensive step-by-step guide. Learn Node.js installation, npm package management, project setup, debugging, and production deployment.

19 min read
0 views
Table of Contents

๐Ÿš€ Node.js Development Environment Setup on AlmaLinux: Complete Guide

Ready to build lightning-fast web applications with JavaScript? ๐Ÿš€ Today weโ€™ll set up a complete Node.js development environment on AlmaLinux - powering millions of applications including Netflix, LinkedIn, and Uber! Whether youโ€™re building APIs, web apps, or microservices, this guide makes Node.js setup simple and powerful! ๐ŸŽฏ

๐Ÿค” Why is Node.js on AlmaLinux Important?

Node.js on AlmaLinux delivers incredible benefits:

  • ๐Ÿ“Œ JavaScript everywhere - Use the same language for frontend and backend
  • ๐Ÿ”ง Blazing fast performance - Built on Chromeโ€™s V8 engine with event-driven architecture
  • ๐Ÿš€ Massive ecosystem - Access to over 2 million packages on npm
  • ๐Ÿ” Enterprise ready - Used by Fortune 500 companies with excellent security
  • โญ Perfect scalability - Handle thousands of concurrent connections efficiently

๐ŸŽฏ What You Need

Before setting up Node.js on AlmaLinux:

  • โœ… AlmaLinux 9 system (server or desktop)
  • โœ… Root or sudo access
  • โœ… At least 2GB RAM (4GB+ recommended for development)
  • โœ… 5GB+ free disk space
  • โœ… Basic command line knowledge (weโ€™ll guide you!)

๐Ÿ“ Step 1: Install Node.js and npm

Letโ€™s get the latest Node.js installed with multiple methods! ๐Ÿ› ๏ธ

Method 1: Install from AlmaLinux Repository (Quick & Easy)

# Update system packages first
sudo dnf update -y

# Install Node.js and npm from default repository
sudo dnf install -y nodejs npm

# Verify Node.js installation
node --version
# v18.19.1

# Verify npm installation  
npm --version
# 10.2.4

# Check installation paths
which node
which npm

echo "โœ… Node.js and npm installed from repository!"

Method 2: Install Latest Node.js from NodeSource Repository

# Add NodeSource repository for latest Node.js
curl -fsSL https://rpm.nodesource.com/setup_lts.x | sudo bash -

# Install Node.js (includes npm)
sudo dnf install -y nodejs

# Install additional development tools
sudo dnf install -y gcc-c++ make

# Verify latest Node.js version
node --version
# v20.11.1

# Check npm version
npm --version
# 10.2.4

# Test Node.js installation
node -e "console.log('๐Ÿš€ Node.js is working!')"

echo "โœ… Latest Node.js installed from NodeSource!"
# Install NVM (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Reload bash profile
source ~/.bashrc

# Verify NVM installation
nvm --version
# 0.39.7

# List available Node.js versions
nvm list-remote --lts

# Install latest LTS Node.js
nvm install --lts

# Use the installed version
nvm use --lts

# Set default Node.js version
nvm alias default node

# Verify installation
node --version
npm --version

# Install multiple Node.js versions (example)
nvm install 18
nvm install 20
nvm list

echo "โœ… Node.js installed with NVM - multiple versions available!"

๐Ÿ”ง Step 2: Configure Development Environment

Set up essential tools and global packages:

Install Essential Global Packages

# Update npm to latest version
npm install -g npm@latest

# Install essential development tools globally
npm install -g nodemon          # Auto-restart server on changes
npm install -g pm2              # Production process manager
npm install -g express-generator # Express.js project generator
npm install -g create-react-app  # React application generator
npm install -g @vue/cli          # Vue.js CLI
npm install -g typescript        # TypeScript compiler
npm install -g ts-node          # Run TypeScript directly
npm install -g eslint           # JavaScript linter
npm install -g prettier         # Code formatter

# Verify global installations
npm list -g --depth=0

# Check nodemon installation
nodemon --version

# Check PM2 installation
pm2 --version

echo "โœ… Essential Node.js development tools installed!"

Configure npm and Set Up Development Directory

# Configure npm with your information
npm config set init-author-name "Your Name"
npm config set init-author-email "[email protected]"
npm config set init-license "MIT"

# Check npm configuration
npm config list

# Create development workspace
mkdir -p ~/nodejs-projects
cd ~/nodejs-projects

# Set npm registry (optional - use faster mirror)
# npm config set registry https://registry.npmmirror.com/

# Create .npmrc for project-specific settings
tee ~/.npmrc << 'EOF'
# Global npm configuration
save-exact=true
init-version=1.0.0
init-license=MIT

# Security settings
audit-level=moderate
fund=false

# Performance settings
prefer-offline=true
cache-max=86400000
EOF

echo "โœ… Node.js development environment configured!"

๐ŸŒŸ Step 3: Create Your First Node.js Application

Build a complete web application from scratch:

Create Express.js Web Application

# Create new project directory
mkdir my-first-node-app
cd my-first-node-app

# Initialize npm project
npm init -y

# Install Express.js framework
npm install express

# Install development dependencies
npm install --save-dev nodemon eslint prettier

# Create main application file
tee app.js << 'EOF'
// My First Node.js Application on AlmaLinux
const express = require('express');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));

// Routes
app.get('/', (req, res) => {
    res.send(`
        <h1>๐Ÿš€ Welcome to Node.js on AlmaLinux!</h1>
        <p>Your Node.js development environment is working perfectly!</p>
        <p><strong>Server Info:</strong></p>
        <ul>
            <li>Node.js Version: ${process.version}</li>
            <li>Platform: ${process.platform}</li>
            <li>Architecture: ${process.arch}</li>
            <li>Process ID: ${process.pid}</li>
            <li>Uptime: ${Math.floor(process.uptime())} seconds</li>
        </ul>
        <p><a href="/api/status">Check API Status</a> | <a href="/api/system">System Info</a></p>
    `);
});

// API Routes
app.get('/api/status', (req, res) => {
    res.json({
        status: 'success',
        message: '๐ŸŽ‰ Node.js API is running!',
        timestamp: new Date().toISOString(),
        environment: process.env.NODE_ENV || 'development'
    });
});

app.get('/api/system', (req, res) => {
    res.json({
        nodeVersion: process.version,
        platform: process.platform,
        architecture: process.arch,
        memory: {
            total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024) + ' MB',
            used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024) + ' MB'
        },
        uptime: Math.floor(process.uptime()) + ' seconds'
    });
});

// Error handling middleware
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({
        error: 'Something went wrong!',
        message: err.message
    });
});

// 404 handler
app.use((req, res) => {
    res.status(404).json({
        error: 'Page not found',
        path: req.path
    });
});

// Start server
app.listen(PORT, () => {
    console.log(`๐Ÿš€ Server running on http://localhost:${PORT}`);
    console.log(`๐Ÿ“Š Environment: ${process.env.NODE_ENV || 'development'}`);
    console.log(`๐Ÿ”ง Node.js Version: ${process.version}`);
});

module.exports = app;
EOF

# Update package.json scripts
npm pkg set scripts.start="node app.js"
npm pkg set scripts.dev="nodemon app.js"
npm pkg set scripts.test="echo \"No tests specified\" && exit 1"

# Create basic static files
mkdir public
tee public/style.css << 'EOF'
body {
    font-family: Arial, sans-serif;
    margin: 40px;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
}
.container {
    max-width: 800px;
    margin: 0 auto;
    background: rgba(255,255,255,0.1);
    padding: 30px;
    border-radius: 10px;
    backdrop-filter: blur(10px);
}
EOF

# Test the application
npm run dev &
sleep 3

# Test API endpoints
curl http://localhost:3000
curl http://localhost:3000/api/status
curl http://localhost:3000/api/system

# Kill the test server
pkill -f nodemon

echo "โœ… First Node.js application created and tested!"

Set Up Database Connection (MongoDB Example)

# Install MongoDB driver
npm install mongodb mongoose

# Install environment variable manager
npm install dotenv

# Create environment configuration
tee .env << 'EOF'
# Node.js Environment Configuration
NODE_ENV=development
PORT=3000
DB_HOST=localhost
DB_PORT=27017
DB_NAME=mynodeapp
DB_USER=nodeuser
DB_PASS=securepassword123

# Security
JWT_SECRET=your-super-secret-jwt-key-here
SESSION_SECRET=your-session-secret-here

# External APIs
API_BASE_URL=http://localhost:3000/api
EOF

# Create database configuration file
tee config/database.js << 'EOF'
// Database Configuration
require('dotenv').config();
const mongoose = require('mongoose');

const connectDB = async () => {
    try {
        const mongoURI = process.env.MONGODB_URI || 
            `mongodb://${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`;
        
        await mongoose.connect(mongoURI, {
            useNewUrlParser: true,
            useUnifiedTopology: true,
        });
        
        console.log('๐Ÿƒ MongoDB connected successfully');
    } catch (error) {
        console.error('โŒ MongoDB connection error:', error.message);
        process.exit(1);
    }
};

module.exports = connectDB;
EOF

# Create models directory and sample model
mkdir models
tee models/User.js << 'EOF'
// User Model
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true,
        trim: true
    },
    email: {
        type: String,
        required: true,
        unique: true,
        lowercase: true
    },
    createdAt: {
        type: Date,
        default: Date.now
    }
});

module.exports = mongoose.model('User', userSchema);
EOF

# Create config directory
mkdir -p config

echo "โœ… Database configuration and models created!"

โœ… Step 4: Set Up Development Tools and Debugging

Configure essential development and debugging tools:

Set Up ESLint and Prettier for Code Quality

# Initialize ESLint configuration
npx eslint --init

# Create .eslintrc.js if not created automatically
tee .eslintrc.js << 'EOF'
module.exports = {
    env: {
        browser: true,
        commonjs: true,
        es2021: true,
        node: true
    },
    extends: [
        'eslint:recommended'
    ],
    parserOptions: {
        ecmaVersion: 'latest'
    },
    rules: {
        'indent': ['error', 4],
        'linebreak-style': ['error', 'unix'],
        'quotes': ['error', 'single'],
        'semi': ['error', 'always'],
        'no-unused-vars': 'warn',
        'no-console': 'off'
    }
};
EOF

# Create Prettier configuration
tee .prettierrc << 'EOF'
{
    "semi": true,
    "trailingComma": "es5",
    "singleQuote": true,
    "printWidth": 80,
    "tabWidth": 4,
    "useTabs": false
}
EOF

# Create .prettierignore
tee .prettierignore << 'EOF'
node_modules/
dist/
build/
*.min.js
package-lock.json
EOF

# Add lint and format scripts to package.json
npm pkg set scripts.lint="eslint ."
npm pkg set scripts.lint:fix="eslint . --fix"
npm pkg set scripts.format="prettier --write ."
npm pkg set scripts.format:check="prettier --check ."

# Test linting and formatting
npm run lint
npm run format

echo "โœ… Code quality tools configured!"

Set Up Debugging and Testing Environment

# Install testing framework
npm install --save-dev jest supertest

# Install debugging tools
npm install --save-dev debug

# Create Jest configuration
tee jest.config.js << 'EOF'
module.exports = {
    testEnvironment: 'node',
    testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'],
    collectCoverageFrom: [
        'src/**/*.js',
        '!src/**/*.test.js',
        '!src/**/node_modules/**'
    ],
    coverageDirectory: 'coverage',
    coverageReporters: ['text', 'lcov', 'html']
};
EOF

# Create sample test file
mkdir -p __tests__
tee __tests__/app.test.js << 'EOF'
// Application Tests
const request = require('supertest');
const app = require('../app');

describe('Node.js Application Tests', () => {
    test('GET / should return welcome message', async () => {
        const response = await request(app)
            .get('/')
            .expect(200);
        
        expect(response.text).toContain('Welcome to Node.js on AlmaLinux');
    });
    
    test('GET /api/status should return JSON status', async () => {
        const response = await request(app)
            .get('/api/status')
            .expect(200)
            .expect('Content-Type', /json/);
        
        expect(response.body.status).toBe('success');
        expect(response.body.message).toContain('Node.js API is running');
    });
    
    test('GET /api/system should return system info', async () => {
        const response = await request(app)
            .get('/api/system')
            .expect(200)
            .expect('Content-Type', /json/);
        
        expect(response.body).toHaveProperty('nodeVersion');
        expect(response.body).toHaveProperty('platform');
        expect(response.body).toHaveProperty('memory');
    });
    
    test('GET /nonexistent should return 404', async () => {
        const response = await request(app)
            .get('/nonexistent')
            .expect(404);
        
        expect(response.body.error).toBe('Page not found');
    });
});
EOF

# Update test script in package.json
npm pkg set scripts.test="jest"
npm pkg set scripts.test:watch="jest --watch"
npm pkg set scripts.test:coverage="jest --coverage"

# Create VS Code debugging configuration
mkdir -p .vscode
tee .vscode/launch.json << 'EOF'
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Node.js App",
            "type": "node",
            "request": "launch",
            "program": "${workspaceFolder}/app.js",
            "env": {
                "NODE_ENV": "development"
            },
            "console": "integratedTerminal",
            "restart": true,
            "runtimeExecutable": "node"
        },
        {
            "name": "Debug Tests",
            "type": "node", 
            "request": "launch",
            "program": "${workspaceFolder}/node_modules/.bin/jest",
            "args": ["--runInBand"],
            "console": "integratedTerminal",
            "env": {
                "NODE_ENV": "test"
            }
        }
    ]
}
EOF

# Run tests
npm test

echo "โœ… Testing and debugging environment configured!"

๐ŸŽฎ Quick Examples

Example 1: Complete REST API with Express.js ๐ŸŒ

# Create REST API project
mkdir nodejs-rest-api
cd nodejs-rest-api

npm init -y

# Install dependencies
npm install express cors helmet morgan compression
npm install --save-dev nodemon

# Create complete REST API
tee server.js << 'EOF'
// Complete REST API with Express.js
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const compression = require('compression');

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

// Middleware
app.use(helmet()); // Security headers
app.use(cors()); // Enable CORS
app.use(compression()); // Gzip compression
app.use(morgan('combined')); // Logging
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));

// In-memory data store (use database in production)
let users = [
    { id: 1, name: 'John Doe', email: '[email protected]', role: 'admin' },
    { id: 2, name: 'Jane Smith', email: '[email protected]', role: 'user' }
];

// Routes
app.get('/', (req, res) => {
    res.json({
        message: '๐Ÿš€ Node.js REST API on AlmaLinux',
        version: '1.0.0',
        endpoints: {
            users: '/api/users',
            health: '/api/health'
        }
    });
});

// Health check endpoint
app.get('/api/health', (req, res) => {
    res.json({
        status: 'healthy',
        timestamp: new Date().toISOString(),
        uptime: process.uptime(),
        memory: process.memoryUsage()
    });
});

// GET all users
app.get('/api/users', (req, res) => {
    const { page = 1, limit = 10, role } = req.query;
    
    let filteredUsers = users;
    if (role) {
        filteredUsers = users.filter(user => user.role === role);
    }
    
    const startIndex = (page - 1) * limit;
    const endIndex = page * limit;
    const paginatedUsers = filteredUsers.slice(startIndex, endIndex);
    
    res.json({
        users: paginatedUsers,
        pagination: {
            current: parseInt(page),
            total: Math.ceil(filteredUsers.length / limit),
            count: paginatedUsers.length,
            totalUsers: filteredUsers.length
        }
    });
});

// GET user by ID
app.get('/api/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) {
        return res.status(404).json({ error: 'User not found' });
    }
    res.json(user);
});

// POST create user
app.post('/api/users', (req, res) => {
    const { name, email, role = 'user' } = req.body;
    
    if (!name || !email) {
        return res.status(400).json({ error: 'Name and email are required' });
    }
    
    if (users.some(u => u.email === email)) {
        return res.status(409).json({ error: 'Email already exists' });
    }
    
    const newUser = {
        id: Math.max(...users.map(u => u.id)) + 1,
        name,
        email,
        role,
        createdAt: new Date().toISOString()
    };
    
    users.push(newUser);
    res.status(201).json(newUser);
});

// PUT update user
app.put('/api/users/:id', (req, res) => {
    const userId = parseInt(req.params.id);
    const userIndex = users.findIndex(u => u.id === userId);
    
    if (userIndex === -1) {
        return res.status(404).json({ error: 'User not found' });
    }
    
    const { name, email, role } = req.body;
    users[userIndex] = { ...users[userIndex], name, email, role, updatedAt: new Date().toISOString() };
    
    res.json(users[userIndex]);
});

// DELETE user
app.delete('/api/users/:id', (req, res) => {
    const userId = parseInt(req.params.id);
    const userIndex = users.findIndex(u => u.id === userId);
    
    if (userIndex === -1) {
        return res.status(404).json({ error: 'User not found' });
    }
    
    const deletedUser = users.splice(userIndex, 1)[0];
    res.json({ message: 'User deleted', user: deletedUser });
});

// Error handling
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({ error: 'Internal server error' });
});

app.use((req, res) => {
    res.status(404).json({ error: 'Endpoint not found' });
});

app.listen(PORT, () => {
    console.log(`๐ŸŒ REST API server running on http://localhost:${PORT}`);
    console.log(`๐Ÿ“Š Health check: http://localhost:${PORT}/api/health`);
    console.log(`๐Ÿ‘ฅ Users API: http://localhost:${PORT}/api/users`);
});

module.exports = app;
EOF

# Add scripts
npm pkg set scripts.start="node server.js"
npm pkg set scripts.dev="nodemon server.js"

# Test the REST API
npm run dev &
sleep 3

# Test API endpoints
echo "Testing REST API endpoints..."
curl -X GET http://localhost:3000/api/health
curl -X GET http://localhost:3000/api/users
curl -X POST http://localhost:3000/api/users -H "Content-Type: application/json" -d '{"name":"Bob Wilson","email":"[email protected]","role":"user"}'

pkill -f nodemon

echo "โœ… Complete REST API created and tested!"

Example 2: Real-time WebSocket Application ๐Ÿ”„

# Create WebSocket application
mkdir nodejs-websocket-app
cd nodejs-websocket-app

npm init -y

# Install Socket.IO for WebSockets
npm install express socket.io

# Create real-time chat application
tee server.js << 'EOF'
// Real-time WebSocket Application
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const path = require('path');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

const PORT = process.env.PORT || 3000;

// Serve static files
app.use(express.static('public'));

// Store connected users
const connectedUsers = new Map();
const chatHistory = [];

// Socket.IO connection handling
io.on('connection', (socket) => {
    console.log(`๐Ÿ”— User connected: ${socket.id}`);
    
    // Handle user join
    socket.on('user_join', (userData) => {
        connectedUsers.set(socket.id, {
            id: socket.id,
            name: userData.name || `User${socket.id.substring(0, 6)}`,
            joinTime: new Date()
        });
        
        // Send chat history to new user
        socket.emit('chat_history', chatHistory);
        
        // Broadcast user list update
        io.emit('users_update', Array.from(connectedUsers.values()));
        
        // Broadcast join message
        const joinMessage = {
            type: 'system',
            message: `${connectedUsers.get(socket.id).name} joined the chat`,
            timestamp: new Date()
        };
        socket.broadcast.emit('message', joinMessage);
        
        console.log(`๐Ÿ‘ค User ${connectedUsers.get(socket.id).name} joined`);
    });
    
    // Handle chat messages
    socket.on('chat_message', (messageData) => {
        const user = connectedUsers.get(socket.id);
        if (!user) return;
        
        const message = {
            id: Date.now(),
            user: user.name,
            userId: socket.id,
            message: messageData.message,
            timestamp: new Date(),
            type: 'user'
        };
        
        // Store message in history
        chatHistory.push(message);
        if (chatHistory.length > 100) {
            chatHistory.shift(); // Keep only last 100 messages
        }
        
        // Broadcast message to all clients
        io.emit('message', message);
        
        console.log(`๐Ÿ’ฌ ${user.name}: ${message.message}`);
    });
    
    // Handle typing indicator
    socket.on('typing', (data) => {
        const user = connectedUsers.get(socket.id);
        if (user) {
            socket.broadcast.emit('user_typing', {
                userId: socket.id,
                userName: user.name,
                isTyping: data.isTyping
            });
        }
    });
    
    // Handle disconnect
    socket.on('disconnect', () => {
        const user = connectedUsers.get(socket.id);
        if (user) {
            // Remove user from connected users
            connectedUsers.delete(socket.id);
            
            // Broadcast user list update
            io.emit('users_update', Array.from(connectedUsers.values()));
            
            // Broadcast leave message
            const leaveMessage = {
                type: 'system',
                message: `${user.name} left the chat`,
                timestamp: new Date()
            };
            socket.broadcast.emit('message', leaveMessage);
            
            console.log(`๐Ÿ‘‹ User ${user.name} disconnected`);
        }
    });
});

// API endpoints for stats
app.get('/api/stats', (req, res) => {
    res.json({
        connectedUsers: connectedUsers.size,
        totalMessages: chatHistory.length,
        uptime: process.uptime(),
        serverTime: new Date()
    });
});

server.listen(PORT, () => {
    console.log(`๐Ÿ”„ WebSocket server running on http://localhost:${PORT}`);
    console.log(`๐Ÿ“Š Stats API: http://localhost:${PORT}/api/stats`);
});
EOF

# Create client-side HTML
mkdir public
tee public/index.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Node.js WebSocket Chat - AlmaLinux</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 0; background: #f0f0f0; }
        .container { max-width: 800px; margin: 0 auto; background: white; height: 100vh; display: flex; flex-direction: column; }
        .header { background: #007acc; color: white; padding: 20px; text-align: center; }
        .chat-area { flex: 1; padding: 20px; overflow-y: auto; }
        .message { margin: 10px 0; padding: 10px; border-radius: 5px; }
        .user-message { background: #e3f2fd; }
        .system-message { background: #f3e5f5; font-style: italic; }
        .input-area { padding: 20px; background: #fafafa; border-top: 1px solid #ddd; }
        .input-area input { width: 70%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; }
        .input-area button { width: 25%; padding: 10px; background: #007acc; color: white; border: none; border-radius: 5px; margin-left: 10px; cursor: pointer; }
        .users-list { background: #f9f9f9; padding: 15px; border-bottom: 1px solid #ddd; }
        .typing { font-style: italic; color: #666; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>๐Ÿš€ Node.js WebSocket Chat</h1>
            <p>Real-time messaging powered by AlmaLinux</p>
        </div>
        <div class="users-list">
            <strong>Online Users:</strong> <span id="usersList">None</span>
        </div>
        <div class="chat-area" id="chatArea"></div>
        <div class="typing" id="typingIndicator"></div>
        <div class="input-area">
            <input type="text" id="messageInput" placeholder="Type your message..." maxlength="500">
            <button onclick="sendMessage()">Send</button>
        </div>
    </div>
    
    <script src="/socket.io/socket.io.js"></script>
    <script>
        const socket = io();
        const chatArea = document.getElementById('chatArea');
        const messageInput = document.getElementById('messageInput');
        const usersList = document.getElementById('usersList');
        const typingIndicator = document.getElementById('typingIndicator');
        
        let userName = prompt('Enter your name:') || 'Anonymous';
        let typingTimer;
        
        // Join the chat
        socket.emit('user_join', { name: userName });
        
        // Listen for messages
        socket.on('message', (data) => {
            const messageDiv = document.createElement('div');
            messageDiv.className = `message ${data.type}-message`;
            messageDiv.innerHTML = `
                <strong>${data.user || 'System'}:</strong> ${data.message}
                <small style="float: right; color: #666;">${new Date(data.timestamp).toLocaleTimeString()}</small>
            `;
            chatArea.appendChild(messageDiv);
            chatArea.scrollTop = chatArea.scrollHeight;
        });
        
        // Listen for chat history
        socket.on('chat_history', (history) => {
            chatArea.innerHTML = '';
            history.forEach(msg => {
                socket.emit('message', msg);
            });
        });
        
        // Listen for user updates
        socket.on('users_update', (users) => {
            usersList.textContent = users.map(u => u.name).join(', ') || 'None';
        });
        
        // Listen for typing indicators
        socket.on('user_typing', (data) => {
            if (data.isTyping) {
                typingIndicator.textContent = `${data.userName} is typing...`;
            } else {
                typingIndicator.textContent = '';
            }
        });
        
        // Send message function
        function sendMessage() {
            const message = messageInput.value.trim();
            if (message) {
                socket.emit('chat_message', { message });
                messageInput.value = '';
                socket.emit('typing', { isTyping: false });
            }
        }
        
        // Handle Enter key
        messageInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                sendMessage();
            } else {
                // Handle typing indicator
                socket.emit('typing', { isTyping: true });
                clearTimeout(typingTimer);
                typingTimer = setTimeout(() => {
                    socket.emit('typing', { isTyping: false });
                }, 1000);
            }
        });
        
        console.log('๐Ÿ”— Connected to WebSocket server!');
    </script>
</body>
</html>
EOF

# Add scripts
npm pkg set scripts.start="node server.js"
npm pkg set scripts.dev="nodemon server.js"

echo "โœ… Real-time WebSocket application created!"
echo "Visit: http://localhost:3000 to test the chat application"

Example 3: Production Deployment with PM2 โšก

# Production deployment setup
echo "=== Production Deployment with PM2 ==="

# Install PM2 globally if not already installed
npm install -g pm2

# Create production configuration
tee ecosystem.config.js << 'EOF'
module.exports = {
  apps: [{
    name: 'nodejs-app',
    script: './app.js',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'development',
      PORT: 3000
    },
    env_production: {
      NODE_ENV: 'production',
      PORT: 8080
    },
    // Logging
    log_file: './logs/combined.log',
    out_file: './logs/out.log',
    error_file: './logs/error.log',
    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
    
    // Restart policy
    restart_delay: 4000,
    max_restarts: 10,
    min_uptime: '10s',
    
    // Memory and monitoring
    max_memory_restart: '500M',
    monitoring: true,
    
    // Advanced features
    watch: false,
    ignore_watch: ['node_modules', 'logs'],
    
    // Health monitoring
    health_check_grace_period: 3000,
    health_check_fatal_exceptions: true
  }]
};
EOF

# Create logs directory
mkdir -p logs

# Create production startup script
tee start-production.sh << 'EOF'
#!/bin/bash
# Production deployment script

echo "๐Ÿš€ Starting Node.js application in production mode..."

# Create logs directory
mkdir -p logs

# Start application with PM2
pm2 start ecosystem.config.js --env production

# Save PM2 configuration
pm2 save

# Setup PM2 to start on boot
pm2 startup

echo "โœ… Application started in production mode"
echo "๐Ÿ“Š Monitor with: pm2 monit"
echo "๐Ÿ“‹ Status: pm2 status"
echo "๐Ÿ“ Logs: pm2 logs"
EOF

chmod +x start-production.sh

# Create monitoring and management scripts
tee manage-app.sh << 'EOF'
#!/bin/bash
# Application management script

case "$1" in
    start)
        echo "Starting application..."
        pm2 start ecosystem.config.js --env production
        ;;
    stop)
        echo "Stopping application..."
        pm2 stop nodejs-app
        ;;
    restart)
        echo "Restarting application..."
        pm2 restart nodejs-app
        ;;
    reload)
        echo "Reloading application (zero-downtime)..."
        pm2 reload nodejs-app
        ;;
    status)
        pm2 status
        ;;
    logs)
        pm2 logs nodejs-app
        ;;
    monit)
        pm2 monit
        ;;
    delete)
        echo "Deleting application from PM2..."
        pm2 delete nodejs-app
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|reload|status|logs|monit|delete}"
        exit 1
        ;;
esac
EOF

chmod +x manage-app.sh

# Create health check endpoint in main app if not exists
echo "
// Health check for production monitoring
app.get('/health', (req, res) => {
    res.status(200).json({
        status: 'healthy',
        uptime: process.uptime(),
        timestamp: new Date().toISOString(),
        version: process.version
    });
});
" >> app.js

# Install production security packages
npm install helmet cors compression morgan

echo "โœ… Production deployment configuration created!"
echo "๐Ÿ“‹ Start production: ./start-production.sh"
echo "๐Ÿ”ง Manage app: ./manage-app.sh {start|stop|restart|status|logs}"
echo "๐Ÿ“Š Monitor: pm2 monit"

๐Ÿšจ Fix Common Problems

Problem 1: Node.js Version Issues โŒ

Symptoms:

  • App crashes with โ€œunsupported Node.js versionโ€
  • Package installation fails

Try this:

# Check current Node.js version
node --version
npm --version

# Update Node.js using NVM
nvm install --lts
nvm use --lts
nvm alias default node

# Clear npm cache
npm cache clean --force

# Rebuild native modules
npm rebuild

# Check for version compatibility
npm ls
npm audit

# Update packages
npm update

Problem 2: Port Already in Use โŒ

Try this:

# Find process using port 3000
sudo ss -tlnp | grep :3000
# or
sudo lsof -i :3000

# Kill process using the port
sudo fuser -k 3000/tcp

# Use different port in your application
export PORT=3001
node app.js

# Check for processes
ps aux | grep node
pkill -f "node app.js"

Problem 3: Permission Errors with npm โŒ

Check these things:

# Fix npm permissions (preferred method)
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'

# Add to ~/.bashrc
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# Alternative: Fix npm folder permissions
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

# Check npm configuration
npm config list
npm config get prefix

# Clear npm cache if needed
npm cache clean --force

๐Ÿ“‹ Simple Commands Summary

TaskCommand
๐Ÿ”ง Install Node.jssudo dnf install nodejs npm
๐Ÿ“Š Check versionnode --version
๐Ÿš€ Create new projectnpm init -y
๐Ÿ“ Install packagenpm install package-name
โš™๏ธ Run applicationnode app.js
๐ŸŒ Start with nodemonnodemon app.js
๐Ÿ”„ List packagesnpm list

๐Ÿ’ก Tips for Success

  1. Use NVM for version management ๐ŸŒŸ - Switch between Node.js versions easily
  2. Always use package.json ๐Ÿ” - Track dependencies and scripts properly
  3. Implement error handling ๐Ÿš€ - Use try-catch and proper middleware
  4. Use environment variables ๐Ÿ“ - Keep sensitive data in .env files
  5. Regular updates ๐Ÿ”„ - Keep Node.js and packages updated for security

๐Ÿ† What You Learned

Congratulations! Now you can:

  • โœ… Install and configure Node.js development environment on AlmaLinux
  • โœ… Set up npm package management and development tools
  • โœ… Build complete web applications with Express.js framework
  • โœ… Implement real-time features with WebSocket technology
  • โœ… Deploy and manage production applications with PM2

๐ŸŽฏ Why This Matters

Your Node.js development environment on AlmaLinux provides:

  • ๐Ÿš€ Full-stack JavaScript development capability with one language everywhere
  • ๐Ÿ” Production-ready platform for building scalable web applications and APIs
  • ๐Ÿ“Š Enterprise-grade performance with event-driven, non-blocking I/O architecture
  • โšก Rapid development workflow with hot reloading and modern tooling

Remember: Node.js powers over 30 million websites and applications worldwide - with your AlmaLinux setup, youโ€™re ready to build the next generation of web applications! From simple APIs to complex real-time systems, you now have a professional development environment! โญ

Youโ€™ve successfully mastered Node.js development environment setup on AlmaLinux! Your system is now ready for modern JavaScript development with all the tools and optimizations needed for success! ๐Ÿ™Œ