Streaming Server with Nginx-RTMP: Complete Setup Guide

Introduction

Live streaming has become an essential communication tool for content creators, educators, businesses, and gamers worldwide. While platforms like Twitch, YouTube Live, and Facebook Live offer ready-made solutions, hosting your own streaming server provides unparalleled control, privacy, and flexibility. The Nginx-RTMP module transforms the powerful Nginx web server into a full-featured streaming platform capable of handling multiple simultaneous streams, transcoding video in real-time, and distributing content to various platforms.

This comprehensive guide walks you through building a professional-grade streaming server using Nginx with the RTMP (Real-Time Messaging Protocol) module. You'll learn how to configure RTMP ingestion, set up HLS (HTTP Live Streaming) for web playback, implement multi-platform restreaming, add authentication and security, optimize for low latency, and monitor performance.

Whether you're creating a private streaming solution for your organization, building a platform for educational content, setting up a gaming stream server, or developing a foundation for a custom video platform, this guide provides everything needed to deploy a production-ready streaming infrastructure on Linux.

Use Case Overview

Why Host Your Own Streaming Server?

Running a self-hosted streaming server offers significant advantages over relying solely on third-party platforms:

Complete Privacy and Control: Your content remains on infrastructure you control. No algorithms deciding content visibility, no unexpected policy changes, and no platform censorship concerns.

Zero Platform Fees: Commercial streaming platforms often charge for advanced features, higher bitrates, or increased storage. Self-hosting eliminates ongoing platform fees.

Custom Features: Implement custom authentication, integrate with existing systems, add specialized overlays, or build unique interactive features impossible on commercial platforms.

Multi-Platform Distribution: Simultaneously restream to multiple platforms (Twitch, YouTube, Facebook) from a single source, managing everything from one central location.

Lower Latency: Direct RTMP streaming can achieve sub-second latency, crucial for interactive applications, gaming, auctions, or live events where real-time interaction matters.

Unlimited Storage: Record streams with only your storage capacity as the limit, not arbitrary platform restrictions or deletion policies.

Brand Control: Fully white-label streaming experiences with custom players, branding, and user interfaces without platform watermarks or recommendations.

Common Deployment Scenarios

Corporate Communications: Companies streaming internal meetings, training sessions, or company-wide announcements with guaranteed privacy and integration with existing authentication systems.

Educational Streaming: Schools and universities delivering live lectures, seminars, or distance learning programs with recorded archives and custom learning management system integration.

Gaming Tournaments: Esports organizations streaming competitions with low-latency feeds to multiple platforms simultaneously, custom overlays, and instant replay capabilities.

Surveillance and Monitoring: Security systems streaming multiple camera feeds to centralized monitoring stations with recording and playback capabilities.

Religious Organizations: Churches, mosques, temples, and synagogues streaming services to congregation members unable to attend in person, with permanent archives.

Content Creator Networks: Multi-creator platforms where numerous streamers broadcast through shared infrastructure with centralized management and analytics.

Live Events: Conferences, concerts, webinars, and workshops streamed to audiences with optional ticketing, Q&A integration, and high-quality archival.

Technical Capabilities

A properly configured Nginx-RTMP server provides:

  • RTMP Ingestion: Accept streams from OBS Studio, Streamlabs, XSplit, and other broadcasting software
  • HLS Transcoding: Convert RTMP to HLS for browser-based playback without plugins
  • Multi-Bitrate Streaming: Adaptive bitrate streaming for viewers with varying bandwidth
  • Recording: Automatic recording of live streams to video files
  • DVR Functionality: Pause, rewind, and replay live streams
  • Multiple Application Support: Separate streaming applications for different purposes
  • Statistics and Monitoring: Real-time metrics on viewers, bitrates, and server performance
  • Restreaming: Forward streams to external platforms automatically

Requirements

System Requirements

Minimum Requirements (Single Stream, 720p):

  • CPU: 2 cores at 2.5+ GHz (Intel Core i3 or AMD Ryzen 3)
  • RAM: 2GB
  • Storage: 20GB (more for recording storage)
  • Network: 10 Mbps upload (for 720p streaming at 3-4 Mbps bitrate)
  • OS: Ubuntu 20.04/22.04, Debian 11/12, CentOS 8, Rocky Linux 8/9

Recommended Requirements (Multiple Streams, 1080p with transcoding):

  • CPU: 4+ cores at 3.0+ GHz (Intel Core i5/i7 or AMD Ryzen 5/7)
  • RAM: 8GB
  • Storage: 100GB+ SSD (for recordings and transcoding cache)
  • Network: 50+ Mbps upload bandwidth
  • OS: Ubuntu 22.04 LTS (recommended)

High-Performance Requirements (Many simultaneous streams, 4K, heavy transcoding):

  • CPU: 8+ cores at 3.5+ GHz (Intel Xeon or AMD EPYC)
  • RAM: 16GB+
  • Storage: 500GB+ NVMe SSD
  • Network: 100+ Mbps dedicated bandwidth with low latency
  • OS: Ubuntu 22.04 LTS with kernel optimizations

Bandwidth Considerations

Streaming Bitrate Requirements:

  • 480p (SD): 1-2 Mbps
  • 720p (HD): 3-5 Mbps
  • 1080p (Full HD): 5-8 Mbps
  • 1440p (2K): 8-12 Mbps
  • 2160p (4K): 15-25 Mbps

Calculate total bandwidth: (Number of simultaneous streams × bitrate) + (Number of viewers × bitrate)

For example, hosting 5 simultaneous 1080p streams with 100 viewers:

  • Ingest: 5 streams × 6 Mbps = 30 Mbps
  • Viewers: 100 viewers × 6 Mbps = 600 Mbps
  • Total: ~630 Mbps

Content Delivery Networks (CDNs) significantly reduce server bandwidth requirements for large audiences.

Software Requirements

Build Dependencies: GCC compiler, make, build tools, and development libraries for compiling Nginx with RTMP module.

FFmpeg: Required for transcoding, recording, and format conversion. Version 4.0 or newer recommended.

SSL/TLS Certificates: Let's Encrypt for HTTPS delivery of HLS streams (optional but recommended).

Video Players: Video.js, HLS.js, or custom HTML5 players for browser-based playback.

Network Requirements

Open Ports:

  • 1935/TCP: RTMP streaming protocol (incoming streams)
  • 80/TCP: HTTP for HLS delivery (if not using separate web server)
  • 443/TCP: HTTPS for secure HLS delivery
  • 8080/TCP: Optional statistics page

Firewall Configuration: Allow incoming connections on RTMP and HTTP/HTTPS ports.

Low Latency Network: Lower latency improves streaming experience. Sub-50ms latency to streamers ideal.

Prerequisites Knowledge

  • Linux command-line proficiency
  • Basic understanding of video codecs and streaming protocols
  • Familiarity with Nginx web server configuration
  • Network configuration knowledge (ports, firewalls, DNS)
  • Basic video broadcasting software operation (OBS Studio recommended)

Step-by-Step Setup

Step 1: System Preparation and Updates

Connect to your Linux server via SSH and update system packages:

# Ubuntu/Debian
sudo apt update && sudo apt upgrade -y

# CentOS/Rocky Linux
sudo dnf update -y

Install essential build tools and dependencies:

# Ubuntu/Debian
sudo apt install -y build-essential libpcre3 libpcre3-dev libssl-dev \
    zlib1g-dev git wget unzip

# CentOS/Rocky Linux
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y pcre-devel openssl-devel zlib-devel git wget unzip

Step 2: Install FFmpeg

FFmpeg handles video transcoding and recording.

Ubuntu/Debian:

sudo apt install -y ffmpeg

CentOS/Rocky Linux:

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

# Enable RPM Fusion repository
sudo dnf install -y --nogpgcheck \
    https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm

# Install FFmpeg
sudo dnf install -y ffmpeg

Verify installation:

ffmpeg -version

Step 3: Download Nginx and RTMP Module

Create working directory:

cd /tmp

Download Nginx source (use latest stable version):

wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzf nginx-1.24.0.tar.gz

Download nginx-rtmp-module:

git clone https://github.com/arut/nginx-rtmp-module.git

Step 4: Compile Nginx with RTMP Module

Navigate to Nginx source directory:

cd nginx-1.24.0

Configure build with RTMP module:

./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --modules-path=/usr/lib64/nginx/modules \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --http-client-body-temp-path=/var/cache/nginx/client_temp \
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
    --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
    --user=nginx \
    --group=nginx \
    --with-http_ssl_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_stub_status_module \
    --with-http_auth_request_module \
    --with-threads \
    --with-stream \
    --with-stream_ssl_module \
    --with-http_slice_module \
    --with-file-aio \
    --with-http_v2_module \
    --add-module=/tmp/nginx-rtmp-module

Compile and install:

make -j$(nproc)
sudo make install

This process takes several minutes depending on CPU performance.

Step 5: Create Nginx User and Directories

Create nginx user:

sudo useradd -r -M -s /sbin/nologin nginx

Create required directories:

sudo mkdir -p /var/cache/nginx/client_temp
sudo mkdir -p /var/cache/nginx/proxy_temp
sudo mkdir -p /var/cache/nginx/fastcgi_temp
sudo mkdir -p /var/cache/nginx/uwsgi_temp
sudo mkdir -p /var/cache/nginx/scgi_temp

sudo mkdir -p /var/www/html/hls
sudo mkdir -p /var/www/html/dash
sudo mkdir -p /var/www/html/recordings

sudo chown -R nginx:nginx /var/www/html
sudo chown -R nginx:nginx /var/cache/nginx

Step 6: Configure Nginx with RTMP

Create main Nginx configuration:

sudo nano /etc/nginx/nginx.conf

Add the following comprehensive configuration:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

# RTMP configuration
rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        allow publish 127.0.0.1;
        deny publish all;

        # Main live streaming application
        application live {
            live on;
            record off;

            # HLS packaging
            hls on;
            hls_path /var/www/html/hls;
            hls_fragment 3;
            hls_playlist_length 60;

            # Disable consuming the stream from nginx as rtmp
            deny play all;
        }

        # Recording application
        application recording {
            live on;
            record all;
            record_path /var/www/html/recordings;
            record_suffix -%Y%m%d-%H%M%S.flv;
            record_unique on;

            hls on;
            hls_path /var/www/html/hls;
            hls_fragment 3;
            hls_playlist_length 60;
        }

        # Streaming application with authentication
        application secure {
            live on;

            # Enable stream key authentication
            on_publish http://localhost/auth;

            hls on;
            hls_path /var/www/html/hls;
            hls_fragment 3;
            hls_playlist_length 60;
        }
    }
}

# HTTP configuration
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # HLS delivery
    server {
        listen 80;
        server_name _;

        # HLS stream delivery
        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /var/www/html;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }

        # DASH stream delivery
        location /dash {
            root /var/www/html;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }

        # Recordings
        location /recordings {
            root /var/www/html;
            autoindex on;
            add_header Access-Control-Allow-Origin *;
        }

        # Statistics
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root /etc/nginx;
        }

        # Test player page
        location /player {
            root /var/www/html;
            index player.html;
        }
    }
}

Save and exit.

Step 7: Create Systemd Service

Create systemd service file:

sudo nano /etc/systemd/system/nginx.service

Add the following content:

[Unit]
Description=Nginx RTMP Streaming Server
After=network.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Enable and start Nginx:

sudo systemctl daemon-reload
sudo systemctl enable nginx
sudo systemctl start nginx

Check status:

sudo systemctl status nginx

Step 8: Configure Firewall

Open required ports:

# UFW (Ubuntu/Debian)
sudo ufw allow 1935/tcp comment 'RTMP'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# Firewalld (CentOS/Rocky Linux)
sudo firewall-cmd --permanent --add-port=1935/tcp
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Step 9: Create Test HTML Player

Create a simple test player:

sudo mkdir -p /var/www/html/player
sudo nano /var/www/html/player/player.html

Add this HTML5 player using Video.js:

<!DOCTYPE html>
<html>
<head>
    <title>RTMP Stream Player</title>
    <link href="https://vjs.zencdn.net/8.6.1/video-js.css" rel="stylesheet" />
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #1a1a1a;
            color: #fff;
        }
        h1 {
            text-align: center;
        }
        .video-container {
            max-width: 900px;
            margin: 0 auto;
        }
        .info {
            background: #2a2a2a;
            padding: 20px;
            margin-top: 20px;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <h1>Live Stream Player</h1>

    <div class="video-container">
        <video id="my-video" class="video-js vjs-default-skin" controls preload="auto"
               width="900" height="506" data-setup='{}'>
            <source src="http://YOUR_SERVER_IP/hls/stream.m3u8" type="application/x-mpegURL">
        </video>
    </div>

    <div class="info">
        <h2>Stream Information</h2>
        <p><strong>RTMP URL:</strong> rtmp://YOUR_SERVER_IP/live</p>
        <p><strong>Stream Key:</strong> stream</p>
        <p><strong>HLS Playback URL:</strong> http://YOUR_SERVER_IP/hls/stream.m3u8</p>
    </div>

    <script src="https://vjs.zencdn.net/8.6.1/video.min.js"></script>
</body>
</html>

Replace YOUR_SERVER_IP with your actual server IP address.

Set permissions:

sudo chown -R nginx:nginx /var/www/html/player

Step 10: Test the Streaming Setup

Configure OBS Studio (or similar broadcasting software):

  1. Download and install OBS Studio from obsproject.com
  2. Open OBS Studio
  3. Go to Settings > Stream
  4. Select "Custom" as Service
  5. Enter Server: rtmp://YOUR_SERVER_IP/live
  6. Enter Stream Key: stream
  7. Click OK

Start Streaming:

  1. Add sources to OBS (webcam, screen capture, etc.)
  2. Click "Start Streaming"
  3. OBS should connect to your server

Watch Stream:

Open browser and navigate to:

http://YOUR_SERVER_IP/player/player.html

The stream should appear after a few seconds of buffering.

Configuration

RTMP Applications Configuration

The RTMP module supports multiple applications for different purposes.

Basic Live Streaming Application:

application live {
    live on;
    record off;

    # Allow publishing from specific IPs
    allow publish 192.168.1.0/24;
    allow publish 10.0.0.0/8;
    deny publish all;

    # Allow playback from anywhere
    allow play all;

    # HLS settings
    hls on;
    hls_path /var/www/html/hls;
    hls_fragment 3;
    hls_playlist_length 60;
    hls_cleanup on;
}

Recording Application:

application recording {
    live on;

    # Record all streams
    record all;
    record_path /var/www/html/recordings;
    record_suffix -%Y%m%d-%H%M%S.flv;
    record_unique on;
    record_max_size 1024M;
    record_max_frames 2;

    # Optional: execute command when recording finishes
    exec_record_done ffmpeg -i $path -codec copy /var/www/html/recordings/$basename.mp4;
}

Multi-Bitrate Streaming:

application live {
    live on;

    # Create multiple quality variants
    exec ffmpeg -i rtmp://localhost/live/$name
        -c:v libx264 -preset veryfast -tune zerolatency -b:v 5000k -maxrate 5000k -bufsize 10000k -s 1920x1080 -c:a aac -b:a 128k -f flv rtmp://localhost/hls/$name_1080p
        -c:v libx264 -preset veryfast -tune zerolatency -b:v 3000k -maxrate 3000k -bufsize 6000k -s 1280x720 -c:a aac -b:a 128k -f flv rtmp://localhost/hls/$name_720p
        -c:v libx264 -preset veryfast -tune zerolatency -b:v 1500k -maxrate 1500k -bufsize 3000k -s 854x480 -c:a aac -b:a 96k -f flv rtmp://localhost/hls/$name_480p;
}

application hls {
    live on;
    hls on;
    hls_path /var/www/html/hls;
    hls_fragment 3;
    hls_playlist_length 60;
    hls_variant _1080p BANDWIDTH=5128000;
    hls_variant _720p BANDWIDTH=3128000;
    hls_variant _480p BANDWIDTH=1596000;
}

Stream Authentication

Implement stream key authentication to prevent unauthorized streaming:

Create authentication script:

sudo nano /var/www/html/auth.php
<?php
// Simple stream key authentication
$valid_keys = [
    'secret_key_1' => 'streamer1',
    'secret_key_2' => 'streamer2',
    'secret_key_3' => 'streamer3'
];

$stream_key = $_POST['name'] ?? '';

if (array_key_exists($stream_key, $valid_keys)) {
    http_response_code(200);
    echo "OK";
} else {
    http_response_code(403);
    echo "Forbidden";
}
?>

Install PHP:

sudo apt install php-fpm -y

Configure Nginx for PHP:

Add to HTTP server block:

location /auth {
    fastcgi_pass unix:/var/run/php/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME /var/www/html/auth.php;
    include fastcgi_params;
}

Update RTMP application:

application secure {
    live on;
    on_publish http://localhost/auth;

    hls on;
    hls_path /var/www/html/hls;
}

HLS Configuration Optimization

Low Latency Settings:

hls on;
hls_path /var/www/html/hls;
hls_fragment 2;           # Smaller fragments = lower latency
hls_playlist_length 10;    # Shorter playlist = lower latency
hls_cleanup on;
hls_nested on;             # Organize by stream name

High Compatibility Settings:

hls on;
hls_path /var/www/html/hls;
hls_fragment 6;            # Larger fragments = better compatibility
hls_playlist_length 60;
hls_type live;
hls_continuous on;         # Don't reset on disconnect

Restreaming to Multiple Platforms

Configure automatic restreaming to Twitch, YouTube, and Facebook:

application multistream {
    live on;

    # Stream to Twitch
    push rtmp://live.twitch.tv/app/YOUR_TWITCH_STREAM_KEY;

    # Stream to YouTube
    push rtmp://a.rtmp.youtube.com/live2/YOUR_YOUTUBE_STREAM_KEY;

    # Stream to Facebook
    push rtmps://live-api-s.facebook.com:443/rtmp/YOUR_FACEBOOK_STREAM_KEY;

    # Local HLS
    hls on;
    hls_path /var/www/html/hls;
    hls_fragment 3;
    hls_playlist_length 60;
}

Streamers use this application to simultaneously broadcast to all platforms:

rtmp://YOUR_SERVER_IP/multistream/YOUR_STREAM_KEY

DVR and Time-Shift Configuration

Enable DVR functionality for pause/rewind:

application dvr {
    live on;

    # Enable HLS DVR
    hls on;
    hls_path /var/www/html/hls;
    hls_fragment 6;
    hls_playlist_length 3600;  # 1 hour of DVR
    hls_type event;            # Event type for DVR
    hls_continuous on;
}

Statistics Page Setup

Copy the statistics stylesheet:

sudo wget https://raw.githubusercontent.com/arut/nginx-rtmp-module/master/stat.xsl -O /etc/nginx/stat.xsl

Access statistics at: http://YOUR_SERVER_IP/stat

Optimization

Worker Process Optimization

Optimize Nginx worker processes based on CPU cores:

# Set to number of CPU cores
worker_processes auto;

events {
    worker_connections 4096;  # Increase for many concurrent connections
    use epoll;                # Linux-specific optimization
    multi_accept on;
}

RTMP Performance Tuning

rtmp {
    server {
        listen 1935;
        chunk_size 4096;      # Default, can increase to 8192 for better performance
        max_connections 1000; # Limit total connections

        application live {
            live on;

            # Limit bitrate
            max_bitrate 10000k;

            # Buffer settings
            buffer 5s;

            # Drop slow clients
            drop_idle_publisher 10s;

            # Synchronization
            sync 10ms;
        }
    }
}

FFmpeg Transcoding Optimization

Hardware Acceleration with NVIDIA GPU:

exec ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i rtmp://localhost/live/$name
    -c:v h264_nvenc -preset fast -b:v 3000k -maxrate 3000k -bufsize 6000k -s 1280x720
    -c:a aac -b:a 128k -f flv rtmp://localhost/hls/$name_720p;

CPU Optimization:

exec ffmpeg -threads 4 -i rtmp://localhost/live/$name
    -c:v libx264 -preset veryfast -tune zerolatency -profile:v baseline
    -b:v 3000k -maxrate 3000k -bufsize 6000k -s 1280x720
    -c:a aac -b:a 128k -f flv rtmp://localhost/hls/$name_720p;

Network Buffer Optimization

System-wide TCP tuning:

sudo nano /etc/sysctl.conf

Add:

# Increase TCP buffer sizes
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864

# Optimize connection handling
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 5000
net.core.somaxconn = 1024

# Enable TCP Fast Open
net.ipv4.tcp_fastopen = 3

Apply changes:

sudo sysctl -p

Storage Optimization

Use SSD/NVMe for HLS fragments:

HLS generation involves many small file writes. Fast storage significantly improves performance.

Tmpfs for temporary HLS files (reduces disk I/O):

sudo mkdir -p /tmp/hls
sudo mount -t tmpfs -o size=2G tmpfs /tmp/hls

Update nginx.conf:

hls_path /tmp/hls;

Make persistent across reboots by adding to /etc/fstab:

tmpfs /tmp/hls tmpfs defaults,size=2G 0 0

Load Balancing Multiple Servers

For large-scale deployments, use multiple streaming servers:

Origin Server (receives streams):

application origin {
    live on;
    push rtmp://edge1.example.com/live;
    push rtmp://edge2.example.com/live;
}

Edge Servers (deliver to viewers):

application live {
    live on;
    pull rtmp://origin.example.com/origin/$name;

    hls on;
    hls_path /var/www/html/hls;
}

Use DNS round-robin or load balancer to distribute viewer traffic across edge servers.

Troubleshooting

Stream Not Appearing

Check if Nginx is receiving the stream:

# Check RTMP statistics
curl http://localhost/stat

# Check nginx error log
sudo tail -f /var/log/nginx/error.log

# Verify port 1935 is listening
sudo netstat -tlnp | grep 1935

Verify OBS connection:

In OBS, check the bottom status bar. Should show green "Live" indicator with bitrate.

Check firewall:

# UFW
sudo ufw status

# Firewalld
sudo firewall-cmd --list-all

Ensure port 1935 is allowed.

Check HLS directory permissions:

ls -la /var/www/html/hls

Should be owned by nginx user:

sudo chown -R nginx:nginx /var/www/html/hls

Playback Issues

HLS files not generating:

# Check if HLS directory exists and has write permissions
ls -la /var/www/html/hls/

# Watch for new .ts and .m3u8 files being created
watch -n 1 ls -la /var/www/html/hls/

CORS errors in browser console:

Ensure CORS headers are set:

location /hls {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, OPTIONS";
}

High latency:

Reduce HLS fragment size:

hls_fragment 2;
hls_playlist_length 10;

Buffering issues:

Check viewer bandwidth:

  • 480p requires 1-2 Mbps
  • 720p requires 3-5 Mbps
  • 1080p requires 5-8 Mbps

Implement adaptive bitrate streaming with multiple quality variants.

High CPU Usage

Identify cause:

# Check nginx worker CPU usage
top -p $(pgrep nginx | tr '\n' ',' | sed 's/,$//')

# Check ffmpeg processes
ps aux | grep ffmpeg

Solutions:

  • Reduce transcoding complexity (use faster presets)
  • Limit number of quality variants
  • Use hardware acceleration (GPU encoding)
  • Increase CPU resources

Optimize FFmpeg settings:

exec ffmpeg -threads 2 -i rtmp://localhost/live/$name
    -c:v libx264 -preset ultrafast -tune zerolatency
    -c:a copy -f flv rtmp://localhost/hls/$name;

Recording Issues

Recordings not saving:

# Check recording directory permissions
ls -la /var/www/html/recordings/

# Set correct permissions
sudo chown -R nginx:nginx /var/www/html/recordings/
sudo chmod 755 /var/www/html/recordings/

Check available disk space:

df -h /var/www/html/recordings/

Disk full errors:

Implement automatic cleanup:

record_max_size 2048M;  # Limit recording file size

# Or use cron job to delete old recordings
0 2 * * * find /var/www/html/recordings -name "*.flv" -mtime +7 -delete

Authentication Not Working

Check PHP-FPM status:

sudo systemctl status php-fpm

Verify auth script:

curl -X POST -d "name=secret_key_1" http://localhost/auth

Should return "OK" for valid keys, "Forbidden" for invalid.

Check nginx error log:

sudo tail -f /var/log/nginx/error.log

Look for FastCGI or authentication errors.

Connection Drops

Increase timeouts:

rtmp {
    server {
        timeout 60s;
        ping 30s;
        ping_timeout 30s;
    }
}

Check network stability:

# Ping test
ping -c 100 YOUR_SERVER_IP

# Check for packet loss
mtr YOUR_SERVER_IP

Increase buffer sizes:

application live {
    live on;
    buffer 10s;  # Increase buffer
}

Advanced Features

SSL/TLS for Secure Streaming

Install Certbot for Let's Encrypt:

sudo apt install certbot -y

Obtain certificate:

sudo certbot certonly --standalone -d stream.example.com

Configure HTTPS in nginx:

server {
    listen 443 ssl http2;
    server_name stream.example.com;

    ssl_certificate /etc/letsencrypt/live/stream.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/stream.example.com/privkey.pem;

    location /hls {
        types {
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
        }
        root /var/www/html;
        add_header Cache-Control no-cache;
        add_header Access-Control-Allow-Origin *;
    }
}

Custom Video Player with Controls

Create advanced player with quality selection:

<!DOCTYPE html>
<html>
<head>
    <title>Advanced Stream Player</title>
    <link href="https://vjs.zencdn.net/8.6.1/video-js.css" rel="stylesheet" />
    <link href="https://cdn.jsdelivr.net/npm/videojs-contrib-quality-levels@2/dist/videojs-contrib-quality-levels.css" rel="stylesheet" />
</head>
<body>
    <video id="player" class="video-js vjs-default-skin" controls width="1280" height="720">
        <source src="https://stream.example.com/hls/stream.m3u8" type="application/x-mpegURL">
    </video>

    <script src="https://vjs.zencdn.net/8.6.1/video.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/videojs-contrib-quality-levels@2/dist/videojs-contrib-quality-levels.min.js"></script>
    <script>
        var player = videojs('player', {
            liveui: true,
            controls: true,
            autoplay: true,
            preload: 'auto'
        });
    </script>
</body>
</html>

Webhook Notifications

Execute scripts on stream events:

application live {
    live on;

    # Execute on stream start
    on_publish http://localhost/webhook/publish;

    # Execute on stream end
    on_publish_done http://localhost/webhook/publish_done;

    # Execute on playback start
    on_play http://localhost/webhook/play;
}

Create webhook handler:

<?php
// /var/www/html/webhook/publish.php

$stream = $_POST['name'] ?? 'unknown';
$timestamp = date('Y-m-d H:i:s');

// Log event
file_put_contents('/var/log/nginx/stream_events.log',
    "$timestamp - Stream started: $stream\n", FILE_APPEND);

// Send notification (email, Slack, Discord, etc.)
// Example: mail('[email protected]', 'Stream Started', "Stream $stream is now live");

http_response_code(200);
?>

Conclusion

You now have a fully functional, professional-grade streaming server powered by Nginx-RTMP. This setup provides enterprise-level streaming capabilities with complete control over your content, viewer experience, and data.

Key achievements from this guide:

  • Custom streaming infrastructure independent of commercial platforms
  • Multi-format delivery supporting RTMP ingestion and HLS playback
  • Production-ready configuration with authentication, recording, and monitoring
  • Optimized performance for low latency and high concurrent viewer counts
  • Scalability foundation ready for expansion with load balancing and CDN integration
  • Advanced features including multi-bitrate streaming, DVR, and multi-platform restreaming

The modular architecture allows incremental improvements. Start with basic streaming and progressively add features like transcoding, authentication, analytics, and content delivery network integration as requirements grow.

Remember to monitor server performance regularly, implement regular backups of configuration files and recordings, and keep Nginx and FFmpeg updated for security and performance improvements. The streaming landscape continuously evolves, so staying informed about new protocols (like SRT and WebRTC) and optimization techniques ensures your infrastructure remains cutting-edge.

Whether hosting personal streams, building a platform for content creators, delivering corporate communications, or creating educational content, this Nginx-RTMP foundation provides the flexibility and power needed for professional streaming operations.

Happy streaming!