73

How To Set Up a Video Streaming Server

Nginx-RTMP Video Streaming Server on Ubuntu 20.04 Streaming video in-house gives you full control over your content. In this guide,…

Nginx-RTMP Video Streaming Server on Ubuntu 20.04

Streaming video in-house gives you full control over your content. In this guide, we’ll show how to install and configure Nginx with the RTMP module on Ubuntu 20.04 to create a self‑hosted live-streaming server. We assume you have a basic Ubuntu server set up (with a sudo user) and Nginx installed. You’ll learn to compile or enable the RTMP module, configure streaming applications, and send video streams (via tools like FFmpeg or OBS Studio). We’ll also cover how to monitor the stream with the built‑in statistics page, and suggest where to insert visuals (architecture diagram, OBS screenshot, stats page) for clarity. Finally, we’ll discuss common issues (firewall, codecs, etc.), security best practices (IP restrictions, stream keys), and future enhancements (SSL/RTMPS, multi-streaming, CDN integration).

1. Install the Nginx RTMP Module

Ubuntu 20.04 includes an Nginx RTMP package in its repositories, so you don’t need to compile from source. Update your package list and install the RTMP module:

sudo apt update
sudo apt install libnginx-mod-rtmp -y   # Install Nginx RTMP module

This installs or updates Nginx (if not already present) and enables the ngx_rtmp_module (which adds the rtmp{} block syntax to Nginx). Confirm that Nginx can start without errors:

sudo nginx -t    # Check Nginx config syntax
sudo systemctl reload nginx

No stream will start automatically yet; we need to add an RTMP configuration block next.

2. Configure the RTMP Application

Open Nginx’s main configuration file (/etc/nginx/nginx.conf) in your favorite editor (e.g. nano):

sudo nano /etc/nginx/nginx.conf

At the end of the file (outside any existing { } blocks), add an rtmp section like this:

rtmp {
    server {
        listen 1935;                  # Standard RTMP port
        chunk_size 4096;              # Data chunk size (4K, standard)
        allow publish 127.0.0.1;      # Only allow local streams by default
        deny publish all;             # Deny other (external) sources

        application live {
            live on;                  # Enable live streaming
            record off;               # Disable recording to disk
            # (Optional: HLS/DASH settings can go here later)
        }
    }
}
  • listen 1935: Nginx will accept RTMP connections on port 1935, the default for RTMP.
  • chunk_size 4096: Sets the data chunk size (4KB is standard) for smoother streaming.
  • allow publish 127.0.0.1 and deny publish all: Restricts who can publish (push) streams to this server. By default only the local host (127.0.0.1) is allowed, and all other sources are denied. This helps prevent unauthorized users from pushing streams.
  • application live: Defines an application named live. Streams sent to rtmp://your_server_IP/live/[stream_name] will go here.
  • live on: Enables multi-user live streaming (so multiple viewers can connect).
  • record off: Disables automatic recording of streams to disk. (You can turn this on if you want to save every broadcast.)

Save and close the file (e.g. Ctrl+X, then Y, Enter in nano).

Now reload Nginx to apply the new config:

sudo systemctl reload nginx

At this point, your Nginx-RTMP server is listening on port 1935, but it’s not yet accessible if a firewall is blocking it. If you’re using UFW (Uncomplicated Firewall), allow the RTMP port:

sudo ufw allow 1935/tcp

Figure: (Insert RTMP architecture diagram here: show a video source streaming to Nginx on port 1935, with clients pulling RTMP/HLS streams.)

3. Streaming Video to the Server

You can now send video streams to your server. Two common methods are:

  1. Using FFmpeg on the server (for pre-recorded video files).
  2. Using OBS Studio from a desktop (for live capture).

3.1. Pushing a Video File with FFmpeg

If you have a video file (or download one), you can stream it in real time. First, make sure ffmpeg is installed:

sudo apt install ffmpeg -y

To experiment, you can download a public-domain video. For example, use youtube-dl (or yt-dlp) to grab a sample:

sudo apt install python3-pip -y
sudo pip3 install youtube-dl  # or yt-dlp
youtube-dl https://www.youtube.com/watch?v=iom_nhYQIYk

The above command fetches a video (DigitalOcean’s App Platform intro) into the current directory. Once you have a .mkv or .mp4 file, stream it with ffmpeg:

ffmpeg -re -i "video_filename.mkv" -c:v copy -c:a aac -ar 44100 -ac 1 -f flv rtmp://localhost/live/stream
  • -re tells ffmpeg to read the input at its native frame rate (so playback is real-time).
  • -i "video_filename.mkv" is your input file.
  • -c:v copy copies the video codec (no re-encode), assuming it’s compatible with FLV/RTMP.
  • -c:a aac -ar 44100 -ac 1 re-encodes audio to a single-channel AAC @ 44.1kHz (a safe format for RTMP).
  • -f flv wraps the output in an FLV container (required by RTMP).
  • The URL rtmp://localhost/live/stream uses our live application; here stream is an arbitrary stream name.

FFmpeg will show progress in the terminal. Once it starts, the video is live on your RTMP server under the path /live/stream. (You can stop it anytime with Ctrl+C.)

3.2. Streaming from OBS Studio

For true live streaming (webcams, screen capture, etc.), OBS Studio is a popular open-source tool. After installing OBS on your desktop, set up a simple scene (e.g. Display Capture) and configure the stream settings as follows:

  • Service: Custom
  • Server: rtmp://your_server_IP/live
  • Stream Key: obs_stream (you can choose any name)
Streaming Service: Custom
Server:            rtmp://your_domain/live
Stream Key:        obs_stream

(Instructive image: insert an OBS stream settings screenshot here, showing the “Custom” RTMP server entry.)

In the Nginx config, this means OBS will publish to rtmp://your_server_IP/live/obs_stream. Before starting in OBS, allow your client’s IP in the RTMP allow publish list. On the Nginx server, edit /etc/nginx/nginx.conf and add your workstation’s IP:

allow publish 127.0.0.1;
allow publish 192.0.2.5;        # Replace with your OBS machine’s IP
deny publish all;

Reload Nginx again:

sudo systemctl reload nginx

Now go back to OBS and click Start Streaming. OBS should connect to Nginx and begin streaming live video to the RTMP server.

4. Viewing the Stream

Once a stream is live, you can play it with any compatible player. For example, VLC can open RTMP URLs. In VLC, select Media → Open Network Stream, enter rtmp://your_server_IP/live/stream_name and click Play. The stream you pushed (via FFmpeg or OBS) should now play in VLC.

(Figure: insert screenshot of VLC’s “Open Network Stream” dialog.)

Alternatively, you can use other RTMP-capable players or integrate an RTMP player into a webpage.

5. Monitoring: the RTMP Stats Page

Nginx’s RTMP module can generate a simple HTML stats page showing current streams, viewers, etc. To enable it, create a new Nginx site config. For example, in /etc/nginx/sites-available/rtmp, add:

server {
    listen 8080;  # HTTP port for stats
    server_name _;

    # RTMP stats and control
    location /stat {
        rtmp_stat all;
        rtmp_stat_stylesheet stat.xsl;
    }
    location /stat.xsl {
        root /var/www/html/rtmp;
    }
    location /control {
        rtmp_control all;
    }
}

This defines an HTTP endpoint on port 8080. Now create the directory and XSL stylesheet that come with libnginx-mod-rtmp:

sudo mkdir -p /var/www/html/rtmp
sudo gunzip -c /usr/share/doc/libnginx-mod-rtmp/examples/stat.xsl.gz \
    > /var/www/html/rtmp/stat.xsl

Enable the new site and reload:

sudo ln -s /etc/nginx/sites-available/rtmp /etc/nginx/sites-enabled/
sudo systemctl reload nginx

Open port 8080 in the firewall (restricted to your IP if desired):

sudo ufw allow 8080/tcp

Now browse to http://your_server_IP:8080/stat. You’ll see a live stats page (refresh to update) showing active applications, publishers, and viewers.

(Figure: place an example screenshot of the RTMP stats page here.)

6. (Optional) HLS/DASH for Browser Playback

Nginx-RTMP can also generate HLS (HTTP Live Streaming) and DASH streams, which work in most modern browsers. This involves adding a few directives under the application live block in nginx.conf:

application live {
    live on;
    record off;

    hls on;
    hls_path /var/www/html/stream/hls;
    hls_fragment 5s;
    hls_playlist_length 30;

    dash on;
    dash_path /var/www/html/stream/dash;
    dash_fragment 5s;
    dash_playlist_length 30;
}

Then configure a simple HTTP server block (or expand the 8080 server) to serve /var/www/html/stream/ with appropriate CORS headers and MIME types for HLS/DASH. (For brevity, the details are omitted here, but DigitalOcean’s guide has a complete example.) After reloading Nginx and opening the new HTTP port, your streams will be available at URLs like http://your_server_IP:8080/hls/stream.m3u8 and .../dash/stream.mpd. These can be embedded in a <video> tag or played with JS players.

7. Troubleshooting & Tips

  • Firewall and Ports: Double-check that port 1935 (RTMP) and any HTTP ports (8080/8088) are open in UFW or your cloud firewall. If streams aren’t connecting, use ss -antpl | grep 1935 to see if Nginx is listening.
  • Stream Key Mistakes: Ensure the OBS or FFmpeg stream key/path (/live/obs_stream or /live/stream) matches the application name and any Nginx rules. A typo will result in no stream.
  • Codec Errors: If VLC/players report “unsupported codec”, ensure you used a compatible video codec (H.264) and audio codec (AAC) for RTMP. In the FFmpeg command, we copied the video stream (-c:v copy) assuming it was H.264. If not, you may need -c:v libx264.
  • No Audio: If you hear no sound, check that -c:a aac -ar 44100 -ac 1 was included. RTMP often requires AAC audio; formats like MP3 or AC3 might not play correctly.
  • OBS Connection Issues: If OBS won’t connect, try replacing your_domain with the server’s IP in OBS settings, and verify the port (use 1935 or 443). Also ensure you added the OBS machine’s IP to the allow publish list.
  • Stats Page Access: If you get 403 on /stat, ensure the stat.xsl file was properly copied (permissions should be world-readable) and that Nginx has access. The site block must match your URL/port.
  • Logs: Check Nginx error logs (/var/log/nginx/error.log) for any startup errors or permission issues.

8. Security and Best Practices

  • Restrict Publishing: We already used allow publish/deny publish to restrict stream ingestion to trusted IPs. In production, you might require a VPN or only allow connections from your OBS box/IP.
  • Stream Keys: Treat your stream keys (like obs_stream) as passwords. Do not use simple names on public servers. OBS lets you use complex keys; be sure to reflect them in Nginx’s allow publish or auth logic.
  • RTMP over TLS (RTMPS): The Nginx-RTMP module doesn’t natively support RTMPS (encrypted RTMP). If you need an encrypted stream to your server (for example, if OBS requires it), you can tunnel RTMP over SSL using a tool like stunnel or Nginx proxying on port 443. Alternatively, you can terminate SSL at Nginx by listening on 443 with SSL certificates (as with normal HTTP) and forwarding to rtmp://127.0.0.1:1935 internally.
  • Secure OBS Streams: If you expose the server to the public Internet, consider using OAuth tokens or Nginx’s on_play/on_publish hooks to require authentication. At minimum, use strong keys and rotate them periodically.
  • HTTPS for HLS/DASH: If serving HLS/DASH over HTTP, use TLS (HTTPS) to protect content and to avoid mixed-content issues in browsers. You can use Let’s Encrypt certificates in Nginx’s HTTP server blocks.
  • Server Hardening: Since this is a streaming server, keep Nginx and the system updated. Disable unused Nginx modules and services. If running on the same host as your web server, consider using worker_processes auto; multi_accept on; in Nginx for better performance under load.
  • Monitoring and Logging: Monitor your streams and server load. The RTMP access log (enabled by default) can be directed to a separate file with access_log logs/rtmp_access.log rtmp_access; in the rtmp {} section. Watch CPU and network usage if many viewers connect.

9. Future Enhancements

  • Load Balancing & CDN: For large audiences, you could push your RTMP output to multiple servers (using exec_push in nginx-rtmp or FFmpeg with -f tee), or convert to HLS and front it behind a CDN like CloudFront or Cloudflare Stream. This offloads bandwidth.
  • Multi-Platform Streaming: Use ffmpeg to duplicate streams: for example, restream your live feed simultaneously to YouTube, Twitch, etc., by specifying multiple output URLs.
  • Authentication Module: Explore the nginx-rtmp secure token module or auth_request for stream-level auth.
  • Recording: If you want to record streams, remove record off or use the exec_record_done hook to post-process archives.
  • Reverse Proxy: If you already have an Nginx web server, you can reverse-proxy some of these streams or stats pages under your domain (e.g. stream.example.com/live).
  • Transcoding: For multi-bitrate streaming, add additional application blocks or use FFmpeg to create lower-resolution streams in parallel.

Conclusion

By following these steps, you now have a working Nginx-RTMP streaming server on Ubuntu 20.04. You can ingest streams from local tools or OBS, and deliver them to viewers over RTMP (and optionally HLS/DASH). The RTMP stats page gives live monitoring, and you have a foundation to secure and extend your setup. With this knowledge, you could build custom streaming workflows, integrate with web players, or scale to larger deployments as needed.

Sources: DigitalOcean’s tutorial on Nginx-RTMP installation/configuration, and the official nginx-rtmp-module documentation for reference.

CB Editor