Centos 8 To Stream

Centos 8 To Stream

Reading time1 min
#Streaming#Linux#OpenSource#CentOS8#NginxRTMP#LiveStreaming

CentOS 8: Deploying a Production Streaming Server with Nginx and RTMP

Monolithic streaming platforms come with steep costs and buried restrictions. When requirements demand control, transparency, or low-level tuning, running your own infrastructure is the answer. Here’s a stepwise deployment of a streaming server stack on CentOS 8, using Nginx compiled with the RTMP module—a practical approach favored when vendor lock-in and pricing headaches become blockers.


Scenario

Suppose your organization needs to livestream internal events for hundreds of remote employees. Commercial solutions quote $500+/mo for white-label, predictable latency, and simple HLS delivery—yet you have a robust CentOS 8 VM with unmetered bandwidth. Building your own stack is not just a cost optimization, it’s an architectural win.


Pre-Deployment

  • System: CentOS 8 (any recent minor version, e.g. 8.8)
  • Privileges: root or sudoer
  • Network: Open TCP/1935 (RTMP), TCP/8080 (HTTP), or alternative ports as per your firewall policy

Verify initial state:

$ uname -r
4.18.0-477.21.1.el8_8.x86_64
$ sudo firewall-cmd --add-port=1935/tcp --add-port=8080/tcp --permanent && \
  sudo firewall-cmd --reload

System Patch and Toolchain Setup

This deployment hinges on building Nginx with a third-party RTMP module. Stock repo packages don’t offer this by default.

sudo dnf update -y
sudo dnf install -y epel-release
sudo dnf groupinstall "Development Tools" -y
sudo dnf install -y gcc make pcre-devel openssl-devel git wget

Note: Missing development libraries will produce configure-time errors like:

./configure: error: the HTTP rewrite module requires the PCRE library.

Always resolve these before continuing.


Nginx + RTMP: Source Build

Choose stable, not too old, not bleeding edge. 1.22.1 is a known baseline for compatibility.

export NGINX_VERSION=1.22.1
wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
tar xf nginx-${NGINX_VERSION}.tar.gz
git clone https://github.com/arut/nginx-rtmp-module.git
cd nginx-${NGINX_VERSION}

./configure --with-http_ssl_module --add-module=../nginx-rtmp-module
make -j$(nproc)
sudo make install

Default install path remains /usr/local/nginx. For most admins, systemd integration is manual. Consider creating a custom unit file later if persistent service management is required.


Core Configuration: Nginx RTMP Integration

Edit /usr/local/nginx/conf/nginx.conf. Append the RTMP block and extend HTTP for HLS endpoint exposure.

rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        application live {
            live on;
            record off;
            # Optional: on_publish or on_play hooks for auth/naming
        }
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    server {
        listen       8080;
        server_name  _;

        location / {
            root   html;
            index  index.html;
        }

        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /tmp;
            add_header Cache-Control no-cache;
            # Note: /tmp is used for HLS segments. Consider storage with adequate IOPS.
        }
    }
}

Tip: Multiple application blocks for parallel channels are supported, but plan chunk sizes based on bandwidth/load.


Launch Nginx

sudo /usr/local/nginx/sbin/nginx

Check endpoints:

ss -ntlup | grep 1935
# Example output:
# tcp  LISTEN 0  128 0.0.0.0:1935  0.0.0.0:* users:(("nginx",pid=4152,fd=7))

For config reload, use:

sudo /usr/local/nginx/sbin/nginx -s reload

First Stream: OBS to RTMP Endpoint

Open broadcasters (OBS, ffmpeg) can push to this endpoint. With OBS Studio (v29+):

  • Settings → Stream
    • Service: Custom...
    • Server: rtmp://<server_ip>/live
    • Stream Key: any identifier (e.g., internal)
  • Start Streaming

Monitor logs in /usr/local/nginx/logs/error.log for connection details and errors, e.g.:

[info] 4206#0: connect: app='live' name='internal' args='' ...

Option: HLS Publishing for Browser Playback

Activate HLS (HTTP Live Streaming) for compatibility with HTML5 video players:

Append inside application live:

hls on;
hls_path /tmp/hls;
hls_fragment 3s;

Prepare storage:

sudo mkdir -p /tmp/hls
sudo chown nginx:nginx /tmp/hls
sudo chmod 750 /tmp/hls

Reload and test. Watch via:

http://<server_ip>:8080/hls/<stream_key>.m3u8

Example with video.js:

<video id="example" controls>
  <source src="http://server_ip:8080/hls/internal.m3u8" type="application/x-mpegURL">
</video>

Gotcha: Serving HLS via /tmp is merely expedient for initial setups; production deployments should mount HLS segments on dedicated storage or RAM disk to avoid disk I/O contention.


Security and Observability

  • Authentication: Nginx RTMP lacks out-of-box authentication. Use on_publish hooks with custom scripts or front it with additional auth middleware if necessary.
  • TLS: Consider terminating SSL using a reverse proxy (nginx mainline, Caddy, or HAProxy) if HLS will be public.
  • Firewalls: Limit 1935/8080 to required IP scopes.
  • Monitoring: Scrape and review /usr/local/nginx/logs/ for failed publishes or unexpected load spikes; integrate with Prometheus exporters if feasible.

Note on CentOS 8 Lifecycle

CentOS 8 has reached EOL. Stream or Rocky Linux 8 are alternatives with better support for future migrations. This guide remains valid for legacy systems; for fresh deployments, map the steps to equivalent RHEL-compatible environments.


Practical Troubleshooting

  • Failed to bind port 1935: Already in use. Validate no other media services are running.
  • HLS segment errors: Permissions or storage exhaustion in /tmp/hls.
  • Dropped connections: Observe CPU and network usage; RTMP is sensitive to jitter—disable power-saving modes if on virtualized hardware.

Closing Remarks

This setup delivers a self-hosted, scalable streaming foundation. For multi-site delivery or high concurrency, layer a CDN or video edge cache after stabilizing the core pipeline. Adaptive bitrate (ABR) transcoding is possible but was omitted here—reference ffmpeg-on-the-fly workflows for that extension.

For long-term maintainability, script the build as an Ansible role or containerize the deployment. Gaps exist—expect to revisit auth, monitoring, and storage as real-world usage ramps.

Critically, you now own the pipeline end-to-end. No hidden costs, no vendor throttling—just system-level control, ready for workload growth.