
How to Set Up a Video Streaming Server Using Nginx RTMP on Ubuntu 24
Setting up a video streaming server with Nginx RTMP on Ubuntu 24 opens up powerful possibilities for live streaming, video-on-demand services, and custom streaming solutions. Whether you’re building a gaming stream platform, educational content delivery system, or corporate video distribution network, understanding how to configure and optimize an RTMP server gives you complete control over your streaming infrastructure. This guide will walk you through the entire process from installation to production deployment, covering performance optimization, security considerations, and troubleshooting common issues that trip up even experienced system administrators.
How Nginx RTMP Works
Nginx RTMP is a module that extends the standard Nginx web server to handle Real-Time Messaging Protocol streams. Unlike basic HTTP streaming, RTMP provides low-latency bidirectional communication between clients and servers, making it ideal for interactive streaming applications.
The module works by creating RTMP applications that can accept incoming streams from encoders like OBS Studio or FFmpeg, then redistribute those streams to viewers in various formats including HLS, DASH, or direct RTMP playback. The server acts as a central hub, handling stream authentication, recording, transcoding, and distribution all within a single process.
Here’s the basic flow:
- Encoder connects to RTMP endpoint and pushes stream
- Nginx RTMP module receives and processes the stream
- Server can simultaneously record, transcode, and redistribute
- Viewers connect via web players, mobile apps, or RTMP clients
- Optional CDN integration for global distribution
Prerequisites and System Requirements
Before diving into the installation, let’s cover what you’ll need for a solid streaming server setup:
Component | Minimum Requirement | Recommended | Notes |
---|---|---|---|
CPU | 2 cores, 2.5GHz | 4+ cores, 3.0GHz+ | Transcoding is CPU-intensive |
RAM | 2GB | 8GB+ | More RAM helps with concurrent streams |
Storage | 20GB SSD | 100GB+ NVMe | Fast I/O crucial for recording |
Network | 100Mbps | 1Gbps+ | Upload bandwidth = bitrate × viewers |
You’ll also need root access to your Ubuntu 24 system and a basic understanding of Linux command line operations.
Step-by-Step Installation Guide
Ubuntu 24’s default repositories don’t include the RTMP module, so we’ll need to compile Nginx from source or use a pre-compiled version with RTMP support.
Method 1: Installing via PPA (Recommended for beginners)
First, update your system and install the necessary repository:
sudo apt update && sudo apt upgrade -y
sudo apt install software-properties-common -y
sudo add-apt-repository ppa:nginx/stable
sudo apt update
Install Nginx with RTMP module:
sudo apt install nginx-full nginx-module-rtmp -y
Load the RTMP module by editing the main Nginx configuration:
sudo nano /etc/nginx/nginx.conf
Add this line at the very beginning of the file, before any other directives:
load_module modules/ngx_rtmp_module.so;
Method 2: Compiling from Source (For advanced users)
If you need the latest features or want more control, compile from source:
sudo apt install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev -y
wget http://nginx.org/download/nginx-1.24.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
tar -zxvf nginx-1.24.0.tar.gz
unzip master.zip
cd nginx-1.24.0
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
make -j$(nproc)
sudo make install
Basic RTMP Configuration
Now comes the fun part – configuring your streaming server. Create a dedicated RTMP configuration file:
sudo nano /etc/nginx/nginx.conf
Add this RTMP block at the end of the main configuration file, outside the http block:
rtmp {
server {
listen 1935;
chunk_size 4096;
allow publish all;
application live {
live on;
record off;
# Enable HLS
hls on;
hls_path /var/www/hls;
hls_fragment 3;
hls_playlist_length 60;
# Enable DASH
dash on;
dash_path /var/www/dash;
# Push to multiple destinations
# push rtmp://backup-server/live;
}
application playback {
live on;
play /var/recordings;
}
}
}
Create the necessary directories:
sudo mkdir -p /var/www/hls
sudo mkdir -p /var/www/dash
sudo mkdir -p /var/recordings
sudo chown -R www-data:www-data /var/www/hls /var/www/dash /var/recordings
sudo chmod -R 755 /var/www/hls /var/www/dash /var/recordings
Configure the HTTP server to serve HLS and DASH streams:
server {
listen 80;
server_name your-domain.com;
# Serve HLS fragments
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /var/www;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
# Serve DASH fragments
location /dash {
root /var/www;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
# RTMP statistics
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root /var/www/html;
}
}
Test your configuration and restart Nginx:
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl enable nginx
Advanced Configuration Options
Here’s a production-ready configuration with authentication, recording, and multiple quality streams:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
# Authentication
on_publish http://localhost/auth;
on_publish_done http://localhost/auth_done;
# Recording
record all;
record_path /var/recordings;
record_unique on;
record_suffix .flv;
# Multiple quality streams
exec ffmpeg -i rtmp://localhost/live/$name
-c:v libx264 -c:a aac -b:v 1000k -b:a 128k -vf "scale=1280:720" -f flv rtmp://localhost/hls/$name_720p
-c:v libx264 -c:a aac -b:v 500k -b:a 96k -vf "scale=854:480" -f flv rtmp://localhost/hls/$name_480p;
# HLS settings
hls on;
hls_path /var/www/hls;
hls_fragment 2;
hls_playlist_length 10;
hls_continuous on;
hls_cleanup on;
hls_nested on;
hls_variant _720p BANDWIDTH=1152000,RESOLUTION=1280x720;
hls_variant _480p BANDWIDTH=596000,RESOLUTION=854x480;
}
application hls {
live on;
allow publish 127.0.0.1;
deny publish all;
hls on;
hls_path /var/www/hls;
hls_fragment 2;
hls_playlist_length 10;
}
}
}
Real-World Use Cases and Examples
Let’s look at some practical applications and how to configure them:
Gaming Stream Platform
For a Twitch-like platform, you’ll want low latency and chat integration:
application gaming {
live on;
# Ultra-low latency settings
hls_fragment 1;
hls_playlist_length 3;
# Notify your application of stream events
on_publish http://your-app.com/api/stream/start;
on_unpublish http://your-app.com/api/stream/end;
on_play http://your-app.com/api/viewer/join;
on_play_done http://your-app.com/api/viewer/leave;
# Push to backup servers
push rtmp://backup1.yoursite.com/gaming;
push rtmp://backup2.yoursite.com/gaming;
}
Educational Content Delivery
For educational platforms, focus on reliability and recording:
application education {
live on;
# Always record lectures
record all;
record_path /var/recordings/lectures;
record_append on;
# Generate thumbnails every 30 seconds
exec_record_done ffmpeg -i $path -vf fps=1/30 /var/www/thumbnails/$basename_%03d.jpg;
# Higher quality HLS for better viewing experience
hls_fragment 6;
hls_playlist_length 30;
}
Corporate Live Events
Enterprise streaming often requires authentication and geographic distribution:
application corporate {
live on;
# JWT-based authentication
on_publish http://auth.company.com/validate_publisher;
on_play http://auth.company.com/validate_viewer;
# Push to CDN endpoints
push rtmp://us-east.cdn.company.com/live;
push rtmp://eu-west.cdn.company.com/live;
push rtmp://asia-pacific.cdn.company.com/live;
# Enable secure HLS
hls_keys on;
hls_key_path /etc/nginx/hls_keys;
hls_fragments_per_key 5;
}
Performance Optimization and Monitoring
Monitor your streaming server performance with these key metrics:
Metric | Good | Warning | Critical | Command to Check |
---|---|---|---|---|
CPU Usage | <70% | 70-85% | >85% | htop or top |
Memory Usage | <80% | 80-90% | >90% | free -h |
Disk I/O Wait | <5% | 5-15% | >15% | iostat -x 1 |
Network Throughput | Varies | 80% of capacity | >90% of capacity | iftop or nethogs |
Add these optimizations to your Nginx configuration:
# In the main context
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
# In http context
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 30;
keepalive_requests 100;
# Buffer sizes
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 1 32k;
postpone_output 1460;
Security Best Practices
Securing your streaming server is crucial, especially for public-facing deployments:
# Restrict publishing to authenticated users
application secure_live {
live on;
# Only allow publishing from your application servers
allow publish 192.168.1.0/24;
allow publish 10.0.0.0/8;
deny publish all;
# Rate limiting
max_connections 1000;
# Webhook-based authentication
on_publish http://127.0.0.1:8080/rtmp/auth;
# Prevent unauthorized playback
on_play http://127.0.0.1:8080/rtmp/play_auth;
}
Implement SSL/TLS for your web interface:
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
}
Set up a firewall to restrict access:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 1935/tcp
sudo ufw enable
Troubleshooting Common Issues
Here are the most frequent problems you’ll encounter and their solutions:
Streams Won’t Start or Connect
Check if Nginx is running and listening on the correct ports:
sudo systemctl status nginx
sudo netstat -tlnp | grep :1935
sudo tail -f /var/log/nginx/error.log
Common fixes:
- Verify RTMP module is loaded:
nginx -V 2>&1 | grep -o with-rtmp
- Check firewall settings:
sudo ufw status
- Ensure directories exist and have proper permissions
- Validate Nginx configuration:
sudo nginx -t
High CPU Usage During Transcoding
If FFmpeg processes are consuming too much CPU:
# Limit FFmpeg CPU usage in your RTMP application
exec ffmpeg -i rtmp://localhost/live/$name
-threads 2 -preset ultrafast -tune zerolatency
-c:v libx264 -c:a aac -f flv rtmp://localhost/hls/$name;
HLS Playback Issues
When viewers can’t play HLS streams:
- Check CORS headers are properly set
- Ensure playlist files (.m3u8) are being generated
- Verify web server can serve the HLS directory
- Test with VLC or another HLS-compatible player first
# Debug HLS generation
ls -la /var/www/hls/
curl -I http://your-domain.com/hls/stream.m3u8
Comparison with Alternative Solutions
Solution | Pros | Cons | Best For |
---|---|---|---|
Nginx RTMP | Free, lightweight, highly configurable | Manual setup, limited GUI | Custom solutions, high control needed |
Wowza Streaming Engine | Enterprise features, GUI, support | Expensive licensing | Enterprise deployments |
Simple Relay Server (SRS) | Modern, WebRTC support, easier setup | Newer, smaller community | Modern streaming requirements |
FFmpeg + Apache/Nginx | Maximum flexibility | Complex setup, manual scripting | Specialized use cases |
Integration with Popular Streaming Tools
Your RTMP server works seamlessly with various broadcasting software:
OBS Studio Configuration
- Server:
rtmp://your-server.com/live
- Stream Key:
your_stream_name
- Recommended bitrate: 2500 kbps for 1080p30
FFmpeg Command Line
# Stream a video file
ffmpeg -re -i input.mp4 -c copy -f flv rtmp://your-server.com/live/stream_name
# Stream webcam (Linux)
ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -preset ultrafast -f flv rtmp://your-server.com/live/webcam
# Re-stream from another RTMP source
ffmpeg -i rtmp://source-server.com/live/input -c copy -f flv rtmp://your-server.com/live/restream
Mobile App Integration
For mobile applications, consider these libraries:
- iOS: HaishinKit.swift for RTMP publishing
- Android: rtmp-rtsp-stream-client-java
- React Native: react-native-rtmp-publisher
Scaling and Load Balancing
As your streaming platform grows, you’ll need to distribute load across multiple servers:
# Load balancer configuration
upstream rtmp_backend {
least_conn;
server stream1.yourdomain.com:1935 weight=3;
server stream2.yourdomain.com:1935 weight=3;
server stream3.yourdomain.com:1935 weight=2;
}
server {
listen 1935;
proxy_pass rtmp_backend;
proxy_timeout 1s;
proxy_responses 1;
}
For geographic distribution, implement edge servers that pull from your origin:
application edge {
live on;
# Pull from origin server
pull rtmp://origin.yourdomain.com/live/;
# Local HLS generation
hls on;
hls_path /var/www/hls;
hls_fragment 2;
}
Setting up an Nginx RTMP server on Ubuntu 24 provides a solid foundation for any streaming project. The flexibility and performance make it an excellent choice for everything from small personal streams to large-scale broadcasting platforms. Remember to monitor your server performance, implement proper security measures, and test thoroughly before going live with any production streams. The official Nginx RTMP module documentation contains additional configuration options and advanced features worth exploring as your streaming requirements evolve.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.