An Nginx RTMP server is a standard Nginx web server with a module added. The module accepts live video over RTMP and republishes it as HLS for viewers. In practice, one encoder sends one stream, and the server fans it out to many people. This guide gives a working configuration, locks it down, and sizes the machine it runs on.
The module is old and widely used, and it has real limits: no native TLS and a long backlog of open issues. This guide says so plainly. It also covers FFmpeg transcoding and the hardware that suits each job.
📖 Sizing the viewer side first?
Read Dedicated Server for Streaming for the bandwidth maths behind concurrent viewers.
What Does an Nginx RTMP Server Do?
An Nginx RTMP server takes one live stream from an encoder and sends it on in three ways: as RTMP, as HLS for browsers and phones, and as a copy pushed to other platforms. The encoder is usually OBS or FFmpeg. It then connects to port 1935 and publishes to an application, which is a named stream route in the configuration.
How an Nginx RTMP server moves one stream
OBS or FFmpeg
port 1935
FFmpeg can also sit in the middle, to build the quality ladder.
Flow diagram of an Nginx RTMP server: an encoder such as OBS or FFmpeg sends one stream to Nginx RTMP on port 1935, which outputs HLS for viewers over HTTP, a push to other platforms, and a recording to disk.
Besides relaying, the module can record streams and run FFmpeg on each one. It can also call your own web service before it accepts a publisher. In short, the README lists live RTMP, HLS and MPEG-DASH output, relay, recording, FFmpeg transcoding, HTTP callbacks and statistics.
What the module does, and the directive behind it
| What you want | Directive |
|---|---|
| Accept and relay live streams | live on |
| Package HLS for browsers and phones | hls on |
| Package MPEG-DASH | dash on |
| Restream to other platforms | push |
| Record streams to files | record all |
| Transcode with FFmpeg | exec |
| Check publishers against your own service | on_publish |
| Read live statistics | rtmp_stat |
Table matching eight things an Nginx RTMP server can do to the directive that enables them: live on for relay, hls on for HLS, dash on for MPEG-DASH, push for restreaming, record all for recording, exec for FFmpeg transcoding, on_publish for publisher checks, and rtmp_stat for statistics.
Is the Nginx RTMP Module Still Maintained?
It still works, but treat it as slow-moving software. For example, the repository lists 1.1k open issues and 97 open pull requests. Its README still describes builds for Nginx 1.3.14 to 1.5.0. The wiki’s directive reference was also last edited in November 2024.
Debian also ships the module as the libnginx-mod-rtmp package, so you do not have to compile it. Even so, pin your Nginx version, test upgrades on a copy, and do not count on fast fixes.
What Are the Alternatives to the Nginx RTMP Module?
If you need protocols beyond RTMP and HLS, look at newer open-source servers such as MediaMTX, which also handles SRT, WebRTC and RTSP. Nginx RTMP stays the simplest choice if you already run Nginx and only need RTMP in and HLS out.
📖 What comes after a single server?
Read Streaming Server Architecture: From Single Server to Cluster for how origin, transcoding and edge nodes fit together as an audience grows.
How Do You Set Up an Nginx RTMP Server?
Install Nginx with the RTMP module, add an rtmp block on port 1935, and point your encoder at it. Four steps cover it:
- Install the module. On Debian or Ubuntu, run
sudo apt install nginx libnginx-mod-rtmp. Elsewhere, build Nginx with--add-module=/path/to/nginx-rtmp-module, as the README describes. - Add the configuration below to
nginx.conf, replace 203.0.113.10 with your encoder’s public address, then reload Nginx. - Point the encoder at it. In OBS, choose a custom service and set the server to
rtmp://your-server-ip/live. Then enter any stream key. Note that the README’s URL format isrtmp://host/app/name, so the app must match an application block. - Test it. Push a file with FFmpeg, then open
http://your-server-ip:8080/hls/test.m3u8in a player.
# nginx.conf: ingest on 1935, HLS on 8080
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
allow publish 203.0.113.10;
deny publish all;
hls on;
hls_path /tmp/hls;
hls_fragment 3s;
hls_playlist_length 12s;
}
}
}
http {
server {
listen 8080;
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
location /stat {
rtmp_stat all;
allow 127.0.0.1;
deny all;
}
}
}
# Test push from any machine that has FFmpeg (the address allowed above)
ffmpeg -re -i sample.mp4 -c:v libx264 -c:a aac -f flv rtmp://your-server-ip/live/test
In short, three lines do the security work. allow publish admits one encoder address, deny publish all refuses everyone else, and rtmp_stat answers only on localhost. The README also asks for the HLS directory to sit in tmpfs, so fragments stay in memory. Check that /tmp is a tmpfs on your system, and mount one at /tmp/hls if it is not.
Why Is HLS Always Behind Live?
HLS keeps viewers at least three fragments behind live, so the fragment length sets the minimum latency. The HLS specification sets the default hold-back at three times the target duration. If that matches the fragment length, the default 5-second fragments put viewers about 15 seconds behind. The 3-second fragments above cut that to about 9 seconds.
~Minimum HLS delay by fragment length
Default hold-back of three target durations, assuming the target matches the fragment.
2-second fragments
3-second fragments (the configuration above)
5-second fragments (the module default)
10-second fragments
Source: HLS specification, June 2026 draft. Real delay also includes encoding and network time.
Horizontal bar chart of the minimum HLS delay by fragment length, using the specification’s default hold-back of three target durations: 6 seconds for 2-second fragments, 9 seconds for 3-second fragments, 15 seconds for the module’s default 5-second fragments, and 30 seconds for 10-second fragments.
Shorter fragments trim the delay. However, the specification warns that they also shrink the buffer and raise the risk of stalls. Also, set your encoder’s keyframe interval to match, because the specification expects each H.264 segment to contain a keyframe.
How Do You Lock Down an Nginx RTMP Server?
Restrict who can publish, check every stream key, and put TLS in front, because the module speaks plain RTMP only. The module’s issue tracker has a long thread on RTMPS. The workaround is a TLS proxy, such as HAProxy or stunnel, in front of port 1935.
Six exposure points on an Nginx RTMP server, and the fix for each
| Exposure | Risk | Fix |
|---|---|---|
| Port 1935 | Anyone can publish a stream | allow publish and deny publish all, plus a firewall rule |
| Stream keys | A leaked key lets others publish | on_publish callback: your service answers 2xx to accept, anything else drops the connection |
| RTMP in transit | Plain text, keys readable on the path | HAProxy or stunnel in front, for RTMPS |
| Stats and control | Anyone can read stats or drop clients | allow 127.0.0.1; deny all; on those locations |
| HLS playback | Anyone with the URL can watch | hls_keys on encrypts fragments with AES-128, with the key URL over HTTPS |
| Idle or abusive connections | Sockets pile up | max_connections and drop_idle_publisher 10s |
Table of six exposure points on an Nginx RTMP server with the risk and fix for each: port 1935 needs allow and deny publish rules, stream keys need an on_publish callback, plain RTMP needs a TLS proxy, stats and control need localhost-only access, HLS playback can use AES-128 encryption, and idle connections need connection limits.
If your encoder’s address changes often, rely on an on_publish check instead of allow publish.
Several platforms, including YouTube and Facebook, offer RTMPS endpoints. The same proxy therefore lets you push streams out to them. The directives above come from the module’s wiki.
How Do You Transcode With FFmpeg and Nginx RTMP?
Use the exec directive: Nginx starts FFmpeg for each published stream, and the renditions go out to a second application. The wiki describes the same pattern. FFmpeg acts as a client, reads the stream from the server, and publishes the result back to Nginx.
# Two-rung ladder: add “env PATH;” at the very top of nginx.conf
rtmp {
server {
listen 1935;
application src {
live on;
allow publish 203.0.113.10;
deny publish all;
exec ffmpeg -i rtmp://localhost/src/$name
-c:v libx264 -preset veryfast -b:v 3000k -s 1280x720 -c:a aac -b:a 128k -f flv rtmp://localhost/hls/${name}_720
-c:v libx264 -preset veryfast -b:v 1500k -s 854x480 -c:a aac -b:a 96k -f flv rtmp://localhost/hls/${name}_480;
}
application hls {
live on;
allow publish 127.0.0.1;
deny publish all;
hls on;
hls_path /tmp/hls;
hls_nested on;
hls_variant _720 BANDWIDTH=3200000;
hls_variant _480 BANDWIDTH=1600000;
}
}
}
The bitrates are examples, so use your own ladder. The hls application accepts publishers from localhost only, so only FFmpeg can feed it. With hls_nested on, each stream gets its own folder under /tmp/hls, so look there for the master playlist. Set each BANDWIDTH to the real peak bitrate of its rung. The HLS specification warns that an inaccurate value can stall playback. Nginx also restarts FFmpeg if it dies mid-stream, since the wiki lists respawn as on by default.
Every published stream starts its own FFmpeg process. CPU therefore grows with the number of channels multiplied by the rungs. So measure it with FFmpeg’s speed figure before you promise a channel count.
📖 Sizing the FFmpeg side?
Read Video Transcoding Server: CPU, GPU, and What to Check Before You Rent for how to measure capacity and which plans fit.
How Much Bandwidth Does an Nginx RTMP Server Need?
A 1 Gbps streaming server serves about 166 viewers of a 6 Mbps stream, because every viewer pulls their own copy. That is the worst case, with everyone on the top rung. By contrast, restreaming costs far less: … Meanwhile, a recording at the same bitrate fills about 2.7 GB of disk an hour.
Viewers a 1 Gbps port can serve, by stream bitrate
Every viewer pulls their own copy of the stream. Port speed divided by bitrate.
4 Mbps stream
6 Mbps stream
10 Mbps stream
14 Mbps stream (YouTube’s H.264 1080p30 ingest)
Arithmetic on the port speed alone. Real capacity is lower, because of protocol overhead and the ingest.
Horizontal bar chart of how many viewers a 1 Gbps port can serve by stream bitrate: 250 viewers at 4 Mbps, 166 at 6 Mbps, 100 at 10 Mbps, and 71 at 14 Mbps, which is YouTube’s recommended H.264 1080p30 ingest bitrate.
However, ingest is a separate, smaller load, and delivery is what fills the port. Past that point, you add servers or a cache layer, which the architecture guide above explains.
Why Does Unmetered Bandwidth Matter for Live Streaming?
Live streaming moves more data than it looks, because a full 1 Gbps port moves 450 GB an hour. A provider that bills per gigabyte charges for every one of those bytes.
What a full 1 Gbps port moves
| Period | Data moved at full speed |
|---|---|
| One hour | 450 GB |
| A three-hour event | 1.35 TB |
| Three hours every day for a month | 40.5 TB |
Table of the data a fully used 1 Gbps port moves: 450 gigabytes in one hour, 1.35 terabytes in a three-hour event, and 40.5 terabytes for three hours every day over a month.
By contrast, every Swify plan includes a 1 Gbps unmetered port, and prices carry no egress fees.
Need a Port Bigger Than 1 Gbps?
Ports of 2, 5, 10 and 25 Gbps are priced in the custom builder, from €60 to €1,320 a month. Pick the port, the cores and the drives that fit your channels.
→ Configure Your ServerWhat Server Does an Nginx RTMP Server Need?
A relay and HLS packager is bandwidth-bound, while FFmpeg ladders are CPU-bound, so size the server for the heavier job. Relaying and packaging do no encoding. They therefore use far less CPU than transcoding, though you should measure both.
Where to start with an Nginx RTMP server on a Swify plan
| Job | Starting point | Why |
|---|---|---|
| Relay and HLS for a few channels | Dedicated 1: 10 cores, 64GB, €120/mo | No encoding, so the port is the limit |
| A few FFmpeg ladders | Dedicated 5: 20 cores, 128GB, €175/mo | Each rung is an x264 encode |
| Many ladders | Dedicated 7: 40 cores, 128GB, €260/mo | Cores decide the channel count |
| A recording library | 26TB HDD in the builder, €50/mo each | €1.92 per TB, with RAID 1 to mirror a pair |
Table of where to start with an Nginx RTMP server on a Swify plan: Dedicated 1 with 10 cores for relay and HLS, Dedicated 5 with 20 cores for a few FFmpeg ladders, Dedicated 7 with 40 cores for many ladders, and 26TB hard drives from the custom builder for a recording library.
These are starting points, not benchmarks, so run your own ladder and read FFmpeg’s speed figure. Swify servers are unmanaged with full root access, which is what you need to install Nginx, the module and FFmpeg. Meanwhile, GPU servers are quoted to order.
📖 Comparing every plan side by side?
Read Swify Dedicated Server Plans: Which Is Right for You? for all eight configurations and the workloads each one suits.
Nginx RTMP Server: The Short Version
An Nginx RTMP server relays one live stream to many viewers. It needs three things you add yourself: access control, a TLS proxy and a server sized for the heavier job. Treat the module as slow-moving software, and measure before you promise a channel count.
- Lock down publishing with
allow publish, anon_publishcallback and a TLS proxy. - Count 166 viewers per 1 Gbps at 6 Mbps, and plan the port before the CPU.
- Transcode with
execand FFmpeg, and read the speed figure before you size the cores.
Host Your Nginx RTMP Server on 1 Gbps Unmetered Bandwidth
Swify dedicated servers start at €120 a month, with 1 Gbps unmetered bandwidth, full root access and up to 40 physical cores for FFmpeg ladders. Hosted in the Netherlands on AMS-IX, with monthly billing and no long contracts.
→ Explore Swify Dedicated ServersFrequently Asked Questions
What is an Nginx RTMP server?
An Nginx RTMP server is an Nginx web server with the nginx-rtmp-module added. It accepts live video over RTMP on port 1935. It can relay, record and republish the stream as HLS or MPEG-DASH. The module is open source. It can also run FFmpeg on each stream to transcode it.
Read Streaming Server Architecture: From Single Server to Cluster for where it fits in a platform.
What port does an Nginx RTMP server use?
By default, it listens on TCP port 1935 for RTMP ingest. Meanwhile, viewers get HLS or DASH over normal HTTP. The port is whichever your http block uses, such as 8080 in the example above. Open 1935 only to the encoder addresses you trust.
Read Best Security Practices for Dedicated Server Environments for a checklist before going live.
Is the nginx-rtmp-module still maintained?
It still works, but it moves slowly. For example, the GitHub repository lists 1.1k open issues and 97 open pull requests. The wiki’s directive reference was also last edited in November 2024. Pin your Nginx version, test upgrades before you apply them, and keep your own security controls.
Does Nginx RTMP support RTMPS?
Not natively. The module speaks plain RTMP. Instead, its issue tracker points to HAProxy or stunnel in front of it for TLS. In practice, the proxy terminates TLS on port 443 and forwards plain RTMP to localhost on port 1935.
Can an Nginx RTMP server transcode video?
Yes, through the exec directive. Nginx then starts FFmpeg for each published stream, and FFmpeg publishes the renditions back to a second application. Each stream starts its own FFmpeg process, so CPU grows with channels times rungs. However, a hardware encoder can change the maths.
Read Hardware Transcoder: GPU, ASIC or CPU? How to Compare Them for when a GPU or ASIC pays off.
How many viewers can a 1 Gbps Nginx RTMP server handle?
About 166 viewers of a 6 Mbps stream, and about 250 of a 4 Mbps stream. Each viewer pulls their own copy. That is arithmetic on the port speed alone, so real capacity is lower. Past that point, add servers or a cache layer in front of the HLS files.
Read Dedicated Server for Streaming for the full bandwidth maths.
What is the difference between RTMP and HLS?
RTMP keeps one live connection open, and it is mostly used to send video from an encoder to a server. HLS cuts video into short files that players fetch over ordinary HTTP, so browsers, phones and caches handle it well. However, HLS adds delay by design: the specification keeps players at least three segments behind live by default.
Read What Is Video Transcoding? A Complete Beginner’s Guide for how the video itself is prepared.

