RTMP (Real-Time Messaging Protocol) was originally developed by Macromedia (later Adobe) as the backbone of Flash-based streaming. Despite Flash's decline, RTMP remains the industry standard for first-mile delivery—the critical path between your encoder and streaming server. This protocol excels at maintaining persistent connections and delivering low-latency video, making it indispensable for live streaming applications in 2025.
When you stream to platforms like YouTube Live, Twitch, or Facebook Live, your encoder is using RTMP under the hood. The protocol breaks video into small chunks and transmits them with minimal overhead, typically achieving latencies of 2-5 seconds—far better than HTTP-based alternatives for live content.
Nginx has emerged as the go-to solution for RTMP servers due to its lightweight architecture, exceptional performance, and modular design. Unlike traditional media servers such as Wowza or Adobe Media Server, Nginx offers:
Before diving into installation, let's ensure your server environment is properly configured. The following specifications will support different streaming scenarios:
For operating systems, Ubuntu 22.04 LTS, Debian 12, or CentOS Stream 9 provide the most stable foundations. These distributions offer long-term support and extensive package repositories, reducing dependency headaches during compilation.
Install the following packages to ensure successful compilation of Nginx with the RTMP module:
# For Ubuntu/Debian systems
sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev \\
libxml2-dev libxslt1-dev libgd-dev libgeoip-dev \\
ffmpeg git wget curl
Each dependency serves a specific purpose in your streaming stack:
Proper network setup is crucial for accessible streams. Configure your firewall to allow the following ports:
# Configure UFW firewall
sudo ufw allow 22/tcp # SSH access
sudo ufw allow 1935/tcp # RTMP streaming
sudo ufw allow 8080/tcp # HLS playback (if using)
sudo ufw allow 443/tcp # HTTPS for secure streaming
sudo ufw enable
Unlike installing Nginx from package managers, compiling from source gives you complete control over module selection and optimization flags. Here's the systematic approach:
# Create working directory
mkdir -p ~/nginx-build && cd ~/nginx-build
# Download Nginx source (always verify checksums in production)
wget https://nginx.org/download/nginx-1.24.0.tar.gz
wget https://nginx.org/download/nginx-1.24.0.tar.gz.asc
# Verify download integrity
sha256sum nginx-1.24.0.tar.gz
# Extract source
tar -xzf nginx-1.24.0.tar.gz
The official Nginx RTMP module is maintained on GitHub. Clone it alongside your Nginx source:
# Clone the RTMP module repository
git clone https://github.com/arut/nginx-rtmp-module.git
# Optional: Checkout a specific stable tag
cd nginx-rtmp-module
git checkout v1.2.2 # Latest stable release as of 2025
cd ..
This is where the real power of source compilation shines. Configure Nginx with modules tailored for streaming:
cd nginx-1.24.0
./configure \\
--prefix=/usr/local/nginx \\
--add-module=../nginx-rtmp-module \\
--with-http_ssl_module \\
--with-http_v2_module \\
--with-http_realip_module \\
--with-http_stub_status_module \\
--with-threads \\
--with-file-aio \\
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong' \\
--with-ld-opt='-Wl,-z,relro -Wl,-z,now'
Let's break down what each flag provides:
# Compile using all available CPU cores
make -j$(nproc)
# Install to the configured prefix
sudo make install
# Verify the installation
/usr/local/nginx/sbin/nginx -V
/usr/local/nginx/sbin/nginx -t
The -V flag shows compiled modules—confirm you see
nginx-rtmp-module in the output. A successful syntax
check with -t confirms your base configuration is valid.
The heart of your streaming server lies in the nginx.conf file. Here's a production-ready configuration with detailed explanations:
# Main context - global settings
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
# Events context - connection handling
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
# RTMP context - streaming configuration
rtmp {
server {
listen 1935;
chunk_size 4096;
# Enable TCP optimizations
tcp_nodelay on;
# Timeout settings
timeout 30s;
drop_idle_publisher 30s;
# Live streaming application
application live {
live on;
record off;
# HLS configuration
hls on;
hls_path /var/www/html/hls;
hls_fragment 3s;
hls_playlist_length 30s;
hls_continuous on;
# DASH configuration (optional)
dash on;
dash_path /var/www/html/dash;
dash_fragment 3s;
# Security - allow publishing only from trusted sources
allow publish 127.0.0.1;
allow publish 192.168.1.0/24;
deny publish all;
# Stream notification
notify_method get;
}
# VOD application
application vod {
play /var/media/vod;
}
}
}
The HTTP block serves HLS and DASH streams to viewers. Here's the companion configuration:
http {
include mime.types;
default_type application/octet-stream;
# Performance optimizations
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
# Gzip compression
gzip on;
gzip_types text/plain application/xml application/javascript text/css;
server {
listen 8080;
server_name _;
# HLS 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 delivery
location /dash {
types {
application/dash+xml mpd;
video/mp4 mp4;
}
root /var/www/html;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
# Statistics page
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root /usr/local/nginx/html;
}
# Health check endpoint
location /health {
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
}
HLS (HTTP Live Streaming) transforms your RTMP stream into a format playable by virtually every modern device. When configured, Nginx RTMP automatically segments your live stream into small .ts files and generates .m3u8 playlist files that browsers can consume natively.
The magic happens through the RTMP module's built-in HLS functionality. As your encoder pushes an RTMP stream, Nginx simultaneously writes HLS segments to disk, enabling both low-latency RTMP delivery and broad HLS compatibility.
Adjust these parameters based on your specific streaming requirements:
# Low-latency HLS configuration (2-3 second delay)
application live_lowlatency {
live on;
hls on;
hls_path /var/www/html/hls_low;
hls_fragment 1s;
hls_playlist_length 10s;
hls_continuous on;
}
# Standard quality HLS (5-7 second delay)
application live_standard {
live on;
hls on;
hls_path /var/www/html/hls_std;
hls_fragment 3s;
hls_playlist_length 30s;
}
# High quality archive HLS (10+ second delay, better compression)
application live_archive {
live on;
hls on;
hls_path /var/www/html/hls_archive;
hls_fragment 6s;
hls_playlist_length 60s;
}
Protecting your streaming infrastructure requires multiple layers of security. Start with RTMP authentication:
# On-publish authentication
application secure_live {
live on;
on_publish http://localhost:8080/auth;
on_publish_done http://localhost:8080/auth_done;
on_play http://localhost:8080/auth_play;
}
Implement the authentication endpoint using a simple script that validates tokens:
# Example auth validation endpoint (Node.js)
const crypto = require('crypto');
app.get('/auth', (req, res) => {
const { name, token } = req.query;
const expected = crypto
.createHmac('sha256', 'your-secret-key')
.update(name)
.digest('hex');
if (token === expected) {
res.status(200).end();
} else {
res.status(403).end();
}
});
Restrict publishing to trusted IP ranges while allowing unrestricted viewing:
application production {
live on;
# Publisher restrictions
allow publish 10.0.0.0/8;
allow publish 172.16.0.0/12;
deny publish all;
# Viewer access - open to all
allow play all;
}
For production deployments, encrypt your streams using RTMPS (RTMP over SSL):
server {
listen 1936 ssl;
ssl_certificate /etc/letsencrypt/live/stream.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/stream.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
application secure {
live on;
hls on;
hls_path /var/www/html/secure_hls;
}
}
Before tuning Nginx, optimize your operating system for high-concurrency streaming:
# /etc/sysctl.conf optimizations
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
# Apply changes
sudo sysctl -p
Fine-tune Nginx worker processes for your specific hardware:
# Optimal worker configuration
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
events {
worker_connections 8192;
multi_accept on;
use epoll;
}
# Thread pool for blocking operations
thread_pool stream_pool threads=32 max_queue=65536;
Adjust buffer sizes and timeouts for stable streaming under load:
rtmp {
server {
# Buffer optimizations
chunk_size 4096;
buflen 5s;
# Connection management
max_streams 32;
max_message 1M;
# Application-specific tuning
application live {
live on;
# GOP cache for faster initial connections
wait_key on;
wait_video on;
# Sync settings
sync 10ms;
# Drop slow subscribers
drop_idle_publisher 10s;
}
}
}
Implement comprehensive monitoring to track streaming performance:
# Enable statistics
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
}
# Custom metrics endpoint
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
For production environments, integrate with monitoring tools like Prometheus and Grafana to visualize stream health, viewer counts, and bandwidth utilization in real-time.
When OBS or other encoders fail to connect, systematically check these common issues:
rtmp://server-ip:1935/live/streamkey
Viewers experiencing buffering or playback failures often indicate:
If streaming quality degrades over time, investigate these potential causes:
# Check system resource usage
htop
iostat -x 1
nload
# Monitor Nginx error logs
tail -f /usr/local/nginx/logs/error.log
# Test stream health
ffplay rtmp://localhost/live/test
ffprobe -v quiet -print_format json -show_streams rtmp://localhost/live/test
As your viewer base grows, implement these scaling strategies:
Streamline your streaming infrastructure with automation:
# Sample systemd service file
[Unit]
Description=Nginx RTMP Streaming Server
After=network.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Protect your streaming infrastructure with robust backup procedures:
Congratulations on completing this comprehensive Nginx RTMP guide! You've learned how to build a professional live streaming server from the ground up—covering everything from initial installation to production-grade optimization and security.
The streaming landscape continues to evolve, but the fundamentals you've mastered here will serve as a solid foundation. Whether you're streaming gaming content, corporate events, or educational materials, your Nginx RTMP server provides the reliability and performance needed for professional results.
Remember that successful streaming infrastructure requires ongoing attention—monitor your server metrics, stay updated with security patches, and continuously optimize based on viewer feedback and analytics. The difference between a good stream and a great one often comes down to these details.
Ready to expand your streaming capabilities? Consider exploring these advanced topics:
If you found this guide helpful, check out our latest post on CSS vendor prefixes and how to use them. For professional streaming infrastructure consulting or custom development, feel free to contact our team at Red Surge Technology.