Technical Setup Guide

Complete Node Media Server Setup Guide

Step-by-step tutorial for installing and configuring Node Media Server on Linux. Learn RTMP server setup, HLS streaming, authentication, FFmpeg transcoding, security hardening, and production deployment. Estimated time: 2-3 hours.

2-3 Hours Ubuntu/CentOS Intermediate
Prefer Hassle-Free Streaming? Skip the 2-3 hour setup and ongoing maintenance. Start streaming in 5 minutes with Shoutcast Net managed hosting from $4/mo - includes 24/7 support, 99.9% uptime, and zero maintenance.

Prerequisites & Requirements

Server Requirements

Minimum Specs (5-10 streams):
  • CPU: 2 cores (2.0 GHz+)
  • RAM: 2 GB minimum
  • Storage: 20 GB SSD
  • Network: 100 Mbps port
  • Bandwidth: 1 TB/month minimum
  • OS: Ubuntu 20.04/22.04 or CentOS 8+
Recommended (20-50 streams):
  • CPU: 4-8 cores (3.0 GHz+)
  • RAM: 8-16 GB
  • Storage: 100+ GB SSD NVMe
  • Network: 1 Gbps dedicated port

Software Requirements

Required:
  • Node.js: Version 10.x or higher (14.x+ recommended)
  • npm: Comes with Node.js installation
  • SSH Access: Root or sudo privileges
  • Text Editor: nano, vim, or VS Code remote
Optional (But Recommended):
  • FFmpeg: For HLS/DASH transcoding
  • PM2: Process manager for production
  • Nginx: Reverse proxy for SSL/load balancing
  • Domain Name: For SSL certificate (Let's Encrypt)
Knowledge Prerequisites

To complete this guide successfully, you should have:

  • Linux CLI Basics: Navigate directories, edit files, manage processes
  • Node.js Familiarity: Understand npm, package.json, running Node apps
  • Networking Basics: Ports, firewalls, IP addresses, TCP/UDP protocols
  • Streaming Concepts: RTMP, HLS, encoders (OBS), bitrates, codecs
1

Install Node.js and npm

Node Media Server requires Node.js runtime. We'll install Node.js 18.x LTS (Long Term Support) which provides the best stability and performance.

On Ubuntu 20.04/22.04:

First, install Node.js using NodeSource repository (recommended method):

# Update system packages
sudo apt update && sudo apt upgrade -y

# Install Node.js 18.x LTS from NodeSource
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# Verify installation
node --version # Should show v18.x.x
npm --version # Should show 9.x.x or higher

Alternative: Use apt install nodejs npm but this may install older versions. NodeSource gives you the latest LTS release.

On CentOS 8/RHEL 8:

# Enable EPEL repository
sudo dnf install epel-release -y

# Install Node.js 18.x from NodeSource
curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -
sudo dnf install -y nodejs

# Verify installation
node --version
npm --version

Install Build Tools (Optional):

Some npm packages require compilation. Install build tools just in case:

# Ubuntu/Debian
sudo apt install -y build-essential

# CentOS/RHEL
sudo dnf groupinstall "Development Tools" -y
2

Install Node Media Server Package

Now we'll create a project directory and install the node-media-server npm package.

Create Project Directory:
# Create directory for streaming server
sudo mkdir -p /opt/streaming-server
cd /opt/streaming-server

# Initialize npm project
npm init -y
Install Node Media Server:
# Install node-media-server package
npm install node-media-server --save

# Verify installation
npm list node-media-server

Note: You can also install globally with npm install -g node-media-server but local installation is recommended for production environments.

Create Basic Server File:

Create server.js file with basic RTMP configuration:

const NodeMediaServer = require('node-media-server');

const config = {
  rtmp: {
    port: 1935,
    chunk_size: 60000,
    gop_cache: true,
    ping: 30,
    ping_timeout: 60
  },
  http: {
    port: 8000,
    allow_origin: '*'
  }
};

var nms = new NodeMediaServer(config);
nms.run();

console.log('Node Media Server running...');
console.log('RTMP: rtmp://localhost:1935');
console.log('HTTP-FLV: http://localhost:8000');

Save this as /opt/streaming-server/server.js. You can test it with: node server.js

3

Configure RTMP Server

Let's enhance the RTMP configuration with production-ready settings for optimal streaming performance.

Advanced RTMP Configuration:
const config = {
  rtmp: {
    port: 1935,
    chunk_size: 60000, // Data chunk size (bytes)
    gop_cache: true, // Enable GOP cache for instant playback
    ping: 30, // Ping interval (seconds)
    ping_timeout: 60 // Ping timeout (seconds)
  },
  http: {
    port: 8000,
    mediaroot: './media', // Media file storage path
    allow_origin: '*' // CORS header
  },
  logType: 3 // 0=no log, 1=error, 2=normal, 3=debug
};
Configuration Parameters Explained:
  • port (1935): Standard RTMP port. Keep default unless you have port conflicts.
  • chunk_size (60000): Larger = better throughput, smaller = lower latency. 60KB is good balance.
  • gop_cache (true): Caches Group of Pictures for instant stream start. Highly recommended!
  • ping/ping_timeout: Keeps connection alive. Default values work for most cases.
  • allow_origin (*): Allows cross-origin playback. Restrict in production for security.
Firewall Configuration:

Open RTMP port (1935) and HTTP port (8000) in your firewall:

# UFW (Ubuntu)
sudo ufw allow 1935/tcp
sudo ufw allow 8000/tcp
sudo ufw reload

# Firewalld (CentOS)
sudo firewall-cmd --permanent --add-port=1935/tcp
sudo firewall-cmd --permanent --add-port=8000/tcp
sudo firewall-cmd --reload
4

Enable HLS and DASH Streaming

HTTP Live Streaming (HLS) enables adaptive bitrate streaming compatible with iOS, Android, and modern web browsers. Requires FFmpeg for transcoding.

Install FFmpeg:

# Ubuntu/Debian
sudo apt install -y ffmpeg

# CentOS 8+ (Enable RPM Fusion first)
sudo dnf install -y ffmpeg

# Verify installation
ffmpeg -version

Configure HLS Transcoding:

Update your server.js with transcoding configuration:

const config = {
  rtmp: {
    port: 1935,
    chunk_size: 60000,
    gop_cache: true,
    ping: 30,
    ping_timeout: 60
  },
  http: {
    port: 8000,
    mediaroot: './media',
    allow_origin: '*'
  },
  trans: {
    ffmpeg: '/usr/bin/ffmpeg',
    tasks: [
      {
        app: 'live',
        hls: true,
        hlsFlags: '[hls_time=2:hls_list_size=3:hls_flags=delete_segments]',
        dash: true,
        dashFlags: '[f=dash:window_size=3:extra_window_size=5]'
      }
    ]
  }
};

HLS Configuration Explained:

  • app: 'live': Applies transcoding to streams published to /live/* path
  • hls: true: Enables HLS output generation
  • hls_time: 2: Segment duration 2 seconds (lower = lower latency but more files)
  • hls_list_size: 3: Keep 3 segments in playlist (memory optimization)
  • delete_segments: Auto-delete old segments to save disk space
  • dash: true: Also generates MPEG-DASH for universal browser support

Playback URLs:

  • RTMP: rtmp://yourserver:1935/live/streamkey
  • HTTP-FLV: http://yourserver:8000/live/streamkey.flv
  • HLS: http://yourserver:8000/live/streamkey/index.m3u8
5

Implement Authentication & Security

By default, anyone can publish to your server. Let's add authentication to control who can stream and view content.

Event-Based Authentication:

Node Media Server triggers events you can hook into. Add this code to your server.js:

const NodeMediaServer = require('node-media-server');

// ... config object here ...

var nms = new NodeMediaServer(config);
nms.run();

// Hook: Before someone publishes a stream
nms.on('prePublish', (id, StreamPath, args) => {
  console.log('[NodeEvent on prePublish]', `id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`);
  
  // Extract stream key from path (e.g., /live/streamkey -> streamkey)
  let stream_key = getStreamKeyFromStreamPath(StreamPath);
  
  // Validate stream key (check database, hardcoded list, etc.)
  if (!isValidStreamKey(stream_key)) {
    console.log('[Auth] Invalid stream key, rejecting:', stream_key);
    let session = nms.getSession(id);
    session.reject(); // Reject the connection
  } else {
    console.log('[Auth] Valid stream key, allowing:', stream_key);
  }
});

// Hook: Before someone plays a stream
nms.on('prePlay', (id, StreamPath, args) => {
  console.log('[NodeEvent on prePlay]', `id=${id} StreamPath=${StreamPath}`);
  
  // Add viewer authentication logic here if needed
  // For public streams, you can leave this empty
});

// Helper function to extract stream key from path
function getStreamKeyFromStreamPath(path) {
  let parts = path.split('/');
  return parts[parts.length - 1];
}

// Validation function (customize for your needs)
function isValidStreamKey(key) {
  // Example: Hardcoded list of allowed keys
  const allowedKeys = ['secret123', 'mystream', 'live2024'];
  return allowedKeys.includes(key);
  
  // OR: Check against database
  // return db.streamKeys.find(k => k.key === key && k.active);
}

Available Events:

  • prePublish - Before stream publish (auth check)
  • postPublish - After publish starts (logging, notifications)
  • donePublish - Stream ended (cleanup, save stats)
  • prePlay - Before viewer plays stream (viewer auth)
  • postPlay - Viewer connected (analytics)
  • donePlay - Viewer disconnected (viewer stats)
Database Integration Example:

For production, validate stream keys against a database (MySQL, PostgreSQL, MongoDB):

const mysql = require('mysql2/promise');

const db = mysql.createPool({
  host: 'localhost',
  user: 'streamuser',
  password: 'password',
  database: 'streaming'
});

async function isValidStreamKey(key) {
  try {
    const [rows] = await db.query(
      'SELECT * FROM stream_keys WHERE stream_key = ? AND active = 1',
      [key]
    );
    return rows.length > 0;
  } catch (err) {
    console.error('Database error:', err);
    return false;
  }
}
6

Connect Encoder (OBS Studio)

Now let's configure OBS Studio to stream to your Node Media Server. These settings also apply to other encoders like vMix, Wirecast, or FFmpeg.

OBS Studio Configuration

  1. Open OBS Studio
    Go to File → Settings → Stream
  2. Service: Select Custom...
  3. Server:
    rtmp://YOUR_SERVER_IP:1935/live
  4. Stream Key:
    secret123 (or your authenticated key)
  5. Click Apply and OK

Recommended Encoder Settings

Output Settings:
  • Video Bitrate: 2500-4500 kbps (720p-1080p)
  • Audio Bitrate: 128-160 kbps
  • Encoder: x264 (software) or NVENC (hardware)
  • Rate Control: CBR (Constant Bitrate)
  • Keyframe Interval: 2 seconds
Video Settings:
  • Resolution: 1920x1080 or 1280x720
  • FPS: 30 or 60 fps
  • Preset: veryfast or faster
Test Your Stream:
  1. Click Start Streaming in OBS Studio
  2. Check server logs: node server.js should show connection
  3. Test playback with VLC or online players:
  • RTMP URL: rtmp://YOUR_SERVER_IP:1935/live/secret123
  • HTTP-FLV URL: http://YOUR_SERVER_IP:8000/live/secret123.flv
  • HLS URL: http://YOUR_SERVER_IP:8000/live/secret123/index.m3u8
7

Production Deployment with PM2

Don't run node server.js manually in production. Use PM2 process manager for automatic restarts, monitoring, and log management.

Install PM2:

# Install PM2 globally
sudo npm install -g pm2

# Start your server with PM2
cd /opt/streaming-server
pm2 start server.js --name "streaming-server"

# Enable auto-start on server reboot
pm2 startup
pm2 save

PM2 Management Commands:

Basic Commands:
pm2 list # List all processes
pm2 logs streaming-server # View logs
pm2 restart streaming-server # Restart
pm2 stop streaming-server # Stop
pm2 delete streaming-server # Remove
pm2 monit # Monitoring dashboard
Advanced Commands:
pm2 logs --lines 100 # Last 100 log lines
pm2 flush # Clear logs
pm2 scale streaming-server 4 # Scale to 4 instances
pm2 reload streaming-server # Zero-downtime reload
pm2 describe streaming-server # Detailed info

Alternative: Systemd Service:

Create systemd service for native Linux integration:

# Create service file
sudo nano /etc/systemd/system/streaming.service

# Add this content:
[Unit]
Description=Node Media Streaming Server
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/streaming-server
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=streaming-server

[Install]
WantedBy=multi-user.target
# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable streaming.service
sudo systemctl start streaming.service

# Check status
sudo systemctl status streaming.service
8

Monitoring & Troubleshooting

HTTP API for Monitoring

Enable HTTP API in your config:

http: {
  port: 8000,
  allow_origin: '*',
  api: true // Enable API
}
API Endpoints:
  • GET /api/streams - List all streams
  • GET /api/server - Server stats
  • POST /api/streams/:app/:stream/stop - Stop stream

Common Issues & Solutions

  • Connection Refused:
    Check firewall (port 1935), verify server running, check IP address
  • Stream Won't Play:
    Check GOP cache enabled, verify FFmpeg installed for HLS, test with VLC
  • High CPU Usage:
    Disable transcoding if not needed, reduce number of streams, upgrade server
  • Authentication Not Working:
    Check event hooks, verify stream key validation logic, review logs
Useful Debugging Commands:
# Check if server is running
ps aux | grep node

# Check open ports
sudo netstat -tulpn | grep :1935
sudo netstat -tulpn | grep :8000

# Monitor server logs
pm2 logs streaming-server --lines 50

# Test RTMP connectivity from another machine
ffmpeg -i rtmp://YOUR_SERVER:1935/live/test -f null -

# Check server resource usage
htop
df -h # Disk space
free -h # Memory

Completed the Setup? Here's What to Expect Next...

Congratulations on setting up your Node Media Server! Now begins the ongoing maintenance:

  • Weekly: Security patches, Node.js updates, monitoring downtime
  • Monthly: Bandwidth cost surprises, log file cleanup, backup verification
  • When Issues Hit: Debug at 2 AM, research error messages, community forum searches
  • Scaling: Configure load balancers, CDN integration, database optimization

Reality Check: Most users spend 4-8 hours/month maintaining their streaming server. At $50/hr, that's $200-400/month in hidden costs - far more than managed hosting.

4-8 hrs/month

Maintenance Time

Go Managed Instead

From $4/mo - Zero maintenance

Next Steps & Resources

Secure with SSL

Setup Nginx reverse proxy with Let's Encrypt SSL certificate for HTTPS/RTMPS

SSL Guide

Optimize Performance

Tune server settings, enable CDN, configure edge servers for global delivery

Learn More

Scale to Production

Load balancing, auto-scaling, multi-region deployment for enterprise traffic

Scaling Tips

Or Go Managed

Skip all this complexity. Stream in 5 minutes with professional support and uptime

Start Now

Congratulations! You've Built Your Streaming Server

You now have a functional RTMP streaming server. Remember: this is just the beginning. Production streaming requires monitoring, security hardening, bandwidth management, and 24/7 vigilance.

Compare Your Options:
Your DIY Server:
$10-20/mo hosting
+ 4-8 hrs/mo maintenance
+ Bandwidth overages
+ Downtime stress
= $300+/mo total cost
Shoutcast Net Managed:
$4-16/mo all-inclusive
+ 0 hrs maintenance
+ Unlimited bandwidth
+ 99.9% uptime SLA
= $4-16/mo total cost
Switch to Managed Hosting