Skip to content
streamneo.
Setup Guides12 min read

Nginx RTMP Docker Setup for a Continuous YouTube Stream

Build an NGINX RTMP Docker relay for YouTube Live, with practical guidance on modules, configuration, credentials and recovery.

sn.
StreamNeoPublished 7 October 2026
Worth sharing?

A Docker relay can accept a continuous RTMP feed from an encoder and forward it to YouTube Live, but the container needs an RTMP-capable NGINX build. NGINX Open Source does not include the third-party RTMP module by default, so you must choose an image that supplies it or build a compatible image yourself.

The relay is only one part of a continuous channel: your source must keep producing audio and video, the host and network must remain available, and YouTube must continue receiving a healthy feed. This guide covers the container path, the configuration decisions and the checks that help distinguish a relay problem from a source or platform problem.

How a Docker relay fits together

Think of the setup as three separate stages. A source process—such as OBS or another encoder—publishes an RTMP stream to a Docker host. NGINX with an RTMP module accepts that incoming connection, then relays it to the ingest address and stream key supplied for your YouTube broadcast.

The word “relay” matters. NGINX is not automatically creating your programme from a folder of videos. Something must generate and publish the audio and video continuously. If OBS is the source, OBS must stay running and keep its input active; if a separate encoder or file-playback process publishes, that process needs its own restart and monitoring plan. A container restart cannot recreate a source that has stopped producing frames.

A typical path looks like this:

video/audio source → RTMP publisher → Docker host port → NGINX RTMP application → YouTube ingest

The publisher connects to a local address such as rtmp://relay-host/live/channel, where live is the RTMP application and channel is a stream name you choose. The module’s push directive sends that incoming stream onward. The YouTube stream key is part of the outbound destination path, not a value to share in a screenshot or commit to a public repository.

This architecture is useful when you need an intermediate point for accepting a source or forwarding it to a destination. It also adds another component to diagnose: if the YouTube preview goes black, you now need to check the source, the inbound connection to NGINX, the outbound connection to YouTube, and the host’s network. For a channel whose main requirement is simply to repeat a prepared programme, compare the operational burden with a managed approach in how cloud services can stream a YouTube playlist continuously after upload.

Choose an image and module approach

The main choice is whether to use a prebuilt community image or build an image that includes the module. The module project, arut/nginx-rtmp-module, documents RTMP publishing and relay features. NGINX Open Source can be built with a third-party module, but the module has to be supplied and compiled or otherwise included in the image. The NGINX Open Source installation documentation describes building Open Source with a third-party module using an --add-module=<PATH> option.

A separate NGINX product page discusses installing nginx-plus-module-rtmp for NGINX Plus. That is a Plus module package, not an RTMP feature bundled into NGINX Open Source, and it should not be presented as a free Open Source package. For a Docker deployment, check that the image’s NGINX version and its RTMP module build are compatible with one another.

A prebuilt image can get you to a first test quickly. The community project tiangolo/nginx-rtmp-docker, for example, documents a basic container start command:

docker run -d -p 1935:1935 --name nginx-rtmp tiangolo/nginx-rtmp

Treat this as a demonstration, not a blanket production recommendation. It is a community image rather than an official NGINX image, so review its maintenance, the image’s base and module compatibility, and how you will receive updates. For a longer-lived channel, pin a specific image version or digest rather than relying on an unchanging-looking tag whose contents could change. Document the version you deploy so that, if a later update changes behaviour, you have a known point of comparison.

Building your own image gives you more control over the NGINX and module versions and the configuration bundled with them, but you own the build and update process. You need a reproducible way to rebuild when a security update or compatibility change matters. If your team is not comfortable maintaining that chain, a prebuilt image may be easier to operate, provided its owner’s maintenance status and update path are acceptable to you.

Create the RTMP application configuration

An RTMP configuration defines the application that publishers connect to and the destination to which the accepted stream is pushed. The module README’s basic pattern uses an application block with live on; and one or more push targets. A deliberately incomplete example shows the shape without exposing a YouTube key:

rtmp {
    server {
        listen 1935;

        application live {
            live on;
            push rtmp://INGEST-HOST/APP/REDACTED-STREAM-KEY;
        }
    }
}

Replace the placeholder with the exact destination information shown in YouTube Live Control Room. The server URL and stream key are provided there for your stream; do not assume that an ingest hostname copied from an old tutorial is correct for your current broadcast. If the service gives a URL with an application path, preserve that path and add the key as required by the selected endpoint and relay’s syntax.

The key is a credential. Avoid placing a real value in a public compose file, source repository, support ticket, terminal recording or shared chat. Use an environment-specific secret mechanism or a configuration file with restricted access, and take care that rendered configuration and process logs do not expose it. If the key is disclosed, replace it in the platform’s controls and update the relay configuration before resuming.

The example uses an RTMP destination to show the module’s push pattern. It does not imply encryption. YouTube recommends RTMPS, but a plain rtmp:// push does not become encrypted because the destination is YouTube. Verify that the relay client and destination setup actually support and negotiate TLS before using an RTMPS URL; do not merely change a scheme string without confirming the selected module can handle it. YouTube’s live streaming guidance explains the supplied stream URL and key workflow and its recommended connection approach.

For an unattended source, the module also documents static pulls that can begin when NGINX starts and external program execution on events. Those are building blocks, not a complete always-on programme system. Confirm that your source can reconnect, that any event hooks do not spawn duplicate processes, and that errors are visible to an operator. Keep the first configuration small: establish one publisher and one destination, then add complexity only when you can test it.

Map ports and provide configuration

The example maps host port 1935 to the container’s RTMP listening port. A publisher on the same host can often address the published port through the host’s local interface; a publisher on another machine needs a route to that host and a firewall rule that permits the connection. Do not expose the relay port to the public internet without considering who can publish to it. At minimum, restrict network access to the source hosts that need it and use whatever authentication controls your selected module and deployment support.

A container also needs to receive the configuration you intend to run. You can bake it into a custom image, or mount a host configuration file into the container at the path expected by that image. The exact path and entrypoint differ between images, so check the image documentation instead of assuming that every NGINX container reads the same file location. Keep the configuration under version control only after removing secrets; preserve a separate, access-controlled mechanism for secret values.

Before relying on a host, check the practical constraints that are easy to miss in a quick local test: does the host start Docker after reboot, does the container restart under the policy you chose, is there enough available upload capacity for the outbound stream, and can you tell when the source or destination has stopped? The research sources do not establish a minimum hardware specification or a performance benchmark, so choose based on your own source format, encode workload and measured network behaviour rather than assuming a particular small computer is required.

For an initial test, the Docker project’s README demonstrates publishing from OBS to the container and playing the local stream in VLC. That makes a useful smoke test: it isolates source-to-container ingest before you add YouTube to the path. If that local playback fails, resolve the publisher URL, application name, port mapping and module configuration first. The separate Nginx publishing error 403 guide is relevant when the publisher is rejected, though an error may also come from a mismatch in application or stream naming.

Connect the publishing source

Configure the source to publish to the relay, not directly to YouTube. If the container host is reachable at 192.0.2.20 on the source network, for example, a publisher URL might be rtmp://192.0.2.20/live/channel; use your actual host address and the application name in your configuration. The example address is reserved for documentation and is not a real deployment address. The stream name after the application can be a simple channel label, as long as the configuration and publisher agree.

Start by publishing a representative source and verify that the relay accepts it. Then play the local relay output in a compatible player or inspect the module’s available status information, if enabled. A successful connection from OBS only shows that the inbound path works; it does not prove that YouTube is receiving the outbound push. Similarly, successful local playback does not prove that your outbound key is current or that the destination URL is right.

Once the local path works, observe what happens when the publisher disconnects and reconnects. Some source applications retry, while others wait for manual intervention or require a restart. A continuous channel needs a defined recovery path for each stage: source generation, publishing client, NGINX container and host. The guide on keeping a YouTube stream online while replacing source files covers a related operational concern: changing programme inputs without treating the source as an invisible detail.

Push the stream to YouTube

In Live Control Room, create or select the broadcast and copy the server URL and stream key for that stream. Use the exact ingest details provided there. The module’s push destination must match the endpoint and application path that YouTube supplied, with the key inserted in the location required by that destination format. Keep the key private during setup and testing.

YouTube recommends RTMPS, the encrypted extension to RTMP. Confirm support for the encrypted destination in the actual relay path before choosing it. If your module configuration only supports a plain RTMP push in the way you have deployed it, do not describe that connection as secure; select a compatible relay method or reassess where the outbound connection is made. After connecting, use the Live Control Room preview and stream-health notices to verify that frames and audio arrive as expected.

Encoding settings still matter even when NGINX is only forwarding the stream. YouTube’s current guidance covers H.264, H.265/HEVC and AV1 among its protocol and codec options, recommends constant bitrate, supports frame rates up to 60 fps, and recommends a two-second keyframe interval that should not exceed four seconds. Its advanced settings recommend stereo AAC audio at 128 Kbps and 44.1 kHz. Bitrate guidance varies by resolution, frame rate and codec, so choose a row in YouTube’s current table for the actual output rather than treating one bitrate as universal. The YouTube Help page on recommended encoder settings is the place to check current details.

Test with the content you will really broadcast. A mostly static devotional image with steady music has different motion and audio characteristics from a local news loop with footage and voice. Watch the preview, listen for missing or distorted sound, and read any health warnings before leaving the channel unattended. If a loop is built from a playlist or repeated file, ensure the source itself keeps generating output at transitions; a relay cannot repair a gap where its publisher stops sending media.

A relay can make it easier to separate the source from the destination, but it also leaves you responsible for the source process, host, container, secret handling and network path. If the pain is specifically keeping a desktop or local machine running only to maintain the broadcast, StreamNeo removes that machine from the publishing path by taking an uploaded video and keeping the YouTube stream running from the cloud, with restart monitoring if it drops.

Test persistence and restart behaviour

A successful first broadcast is not evidence that the setup will recover after an ordinary interruption. Test each boundary deliberately while you can watch it: stop and restart the publishing source, restart the container, and, if your operating procedure permits, reboot the host. Check whether the source reconnects, whether the module resumes the outbound push, and whether YouTube shows a recovered feed or requires action in Live Control Room. Record what happened rather than assuming that a restart policy covers the whole chain.

Docker restart behaviour applies to the container process, not to every dependency. If NGINX exits and Docker restarts it, a source may still need to retry its connection; if the host loses internet access, restarting the container may not help; if the source encoder exits, a healthy NGINX process can remain idle. Define who receives an alert for each failure and how they can tell whether the channel is actually live. A brief check after any image or configuration update is more useful than relying on a remembered successful test.

Also test the operational details around updates and secrets. Confirm that the intended configuration is present after a container recreation, that a redeploy does not silently revert a secret, and that logs do not print the full outbound stream URL. Keep a copy of the known-good configuration without the key so that recovery does not depend on finding a value in an old terminal history. These are deployment responsibilities, not features guaranteed by the RTMP module.

For long continuous broadcasts, account for YouTube’s archive behaviour as well as the relay. YouTube Help says streams under 12 hours are automatically archived; do not assume a single archive will cover a stream that runs longer than that. Check the current official page before planning recording or replay around a long-running event, particularly if viewers need the full programme afterwards.

Before committing, compare the operating options on the pricing page. When the file and channel are ready, start free — 24-hour trial, no card.

FAQ

Does NGINX Open Source include RTMP support?

No. RTMP functionality in this setup comes from a third-party module that must be built or otherwise supplied with the NGINX image. NGINX’s separate nginx-plus-module-rtmp package is for NGINX Plus, not a free Open Source module.

Can this relay create a 24/7 video programme by itself?

No. It accepts and forwards a stream, but a source still has to generate and publish the audio and video. Plan recovery for that source as well as for the container, host and network.

Is the sample push configuration encrypted?

Not as written: its rtmp:// destination illustrates the relay pattern, not an encrypted connection. YouTube recommends RTMPS, so verify that your selected relay path supports TLS and connects to the exact endpoint supplied for the broadcast.

What should I check before leaving it unattended?

Confirm that the local publisher-to-relay path and the relay-to-YouTube path both work, then test source reconnection and container or host restart behaviour. Check Live Control Room health, protect the key, and arrange a way to notice and respond when the stream stops.

YOU’VE REACHED THE END

Keep the ideas coming.

More guides, useful tools and a little help for your next broadcast.

Back to the journal ↗
YOUR NEXT READ

A little more to explore.

More Setup Guides guides ↗ · All topics ↗