Node-Media-Server Live Streaming on AWS User Guide
Overview
This image runs Node-Media-Server, a lightweight open source live media streaming server written in Node.js. It ingests an RTMP feed from any publisher, such as OBS Studio, ffmpeg, a hardware encoder or a mobile app, and republishes that feed in real time as HTTP-FLV, WebSocket-FLV and HLS for low latency playback in browsers and native players. A JSON admin API reports live stream and session statistics.
The stable open source 2.x line is shipped here (version 2.7.4), which is MIT licensed and freely redistributable. The server is installed from npm into /opt/node-media-server on a Node.js 20 runtime and runs as the unprivileged nms system user under systemd, so it restarts automatically and logs cleanly through the journal.
RTMP ingest listens on port 1935. HTTP-FLV, WebSocket-FLV, HLS playback and the admin API all listen on port 8000.
Secure by default
Upstream Node-Media-Server ships with no authentication at all: anyone who can reach it could publish to your server, play from it, or read the admin API. This image does not ship that way. It enables authentication for the admin API, for publishing and for playback, and generates two independent secrets on the first boot of every deployed instance:
- An admin API credential (HTTP Basic auth, user
admin) that protects the statistics API at/api/*. - A stream signing secret that every publish and playback URL must be signed with.
Both secrets are unique to each instance, so two instances launched from the same AMI never share them, and neither is baked into the image. They are written to /root/node-media-server-credentials.txt with mode 0600, readable only by root. The server refuses to start if either secret is missing or too short, so the image can never boot into the insecure open mode.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network, and ports 1935 and 8000 from the networks that will publish and play streams
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line, and ffmpeg on any machine you intend to publish from
Connecting to your instance
Connect over SSH as the default login user for your operating system variant. The recommended instance type is m5.large or larger.
| OS variant | SSH login user | Example |
|---|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i your-key.pem ubuntu@<instance-public-ip> |
Replace <instance-public-ip> with the public IPv4 address of your instance and your-key.pem with your EC2 private key.
Launching from the AWS Marketplace
- Open the product page in the AWS Marketplace and choose Continue to Subscribe, then Continue to Configuration.
- Select the software version and your Region, then Continue to Launch.
- Choose an instance type of
m5.largeor larger, select your VPC, subnet and key pair, and attach a security group that allows inbound 22, 1935 and 8000 as described above. - Launch the instance and wait for the status checks to pass.
Launching from the AWS CLI
# from your workstation
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name your-key \
--security-group-ids <sg-id> \
--subnet-id <subnet-id> \
--count 1
The <ami-id> is shown on the Marketplace launch page for your Region.
Retrieving your per-instance secrets
Every instance generates its own admin credential and stream signing secret on first boot and writes them to a root only file, along with the ready to use endpoint URLs. SSH in and read it:
sudo cat /root/node-media-server-credentials.txt
You will see the admin user and password, the signing secret, and the RTMP, HTTP and admin API URLs already filled in with the instance public address. Keep this file secret.
Verifying the service
Confirm the service is running and both ports are listening:
systemctl is-active node-media-server
ss -tlnp | grep -E ':1935|:8000'
The unauthenticated health endpoint returns a small static response and is handy for load balancer health checks:
curl -fsS http://127.0.0.1:8000/health

The authenticated admin API
The admin API reports live streams and sessions as JSON. It is protected: an unauthenticated request is refused with HTTP 401.
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8000/api/streams
Supply the per instance admin credential and it returns the live stream statistics as JSON. Read the password straight from your root only credentials file so it never appears on the command line history:
API_PASS=$(sudo grep -m1 '^NMS_API_PASS=' /root/node-media-server-credentials.txt | cut -d= -f2-)
curl -s -u "admin:${API_PASS}" http://127.0.0.1:8000/api/streams | jq .

Signing a stream URL
Because publishing and playback are authenticated, every publish and play URL must carry a signature derived from your instance signing secret. The bundled nms-signurl helper computes it for a stream path. To publish or play the stream key mystream under the default live application:
sudo nms-signurl /live/mystream
This prints a sign=<expire>-<md5> query string. Append it to the RTMP publish URL or the HTTP-FLV or HLS playback URL. Signatures are time limited (one hour by default), so generate a fresh one when you start a new session.
Publishing a stream
Publish an RTMP feed to rtmp://<instance-public-ip>:1935/live/mystream, appending the signature. From any machine with ffmpeg installed:
# from your workstation: publish a test pattern to the server
SIGN="sign=<expire>-<md5>" # from: sudo nms-signurl /live/mystream
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
-c:v libx264 -preset veryfast -tune zerolatency -f flv \
"rtmp://<instance-public-ip>:1935/live/mystream?${SIGN}"
To publish from OBS Studio, set the stream Server to rtmp://<instance-public-ip>:1935/live and the Stream Key to mystream?sign=<expire>-<md5> using a signature from nms-signurl. See the OBS project documentation at obsproject.com for encoder settings.
Playing back a stream
While a stream is publishing, play it back over signed HTTP-FLV or HLS on port 8000. Generate a fresh signature for playback with sudo nms-signurl /live/mystream, then:
- HTTP-FLV:
http://<instance-public-ip>:8000/live/mystream.flv?sign=<expire>-<md5> - HLS:
http://<instance-public-ip>:8000/live/mystream/index.m3u8?sign=<expire>-<md5>
Open either URL in a compatible player such as ffplay, VLC, or an flv.js or hls.js web player. The following retrieves the first bytes of a signed HTTP-FLV stream and confirms the FLV header:
# from your workstation, while a stream is publishing
curl -s "http://<instance-public-ip>:8000/live/mystream.flv?sign=<expire>-<md5>" | head -c 3
End-to-end self test
The image bakes a self test that exercises the whole pipeline: it publishes a short signed test pattern, pulls it back over signed HTTP-FLV, queries the admin API, and proves that an unauthenticated admin request, an unsigned publish and an unsigned play are all rejected. Run it any time to confirm the deployment is healthy:
sudo nms-selftest
It prints an OK line on success or a FAIL: line describing the first failing check.

Enabling HTTPS and a custom domain
For public deployments, terminate TLS in front of Node-Media-Server with a reverse proxy such as nginx or a load balancer, and front RTMP with your own edge if required. A common pattern is to obtain a certificate with certbot for your-domain.example.com and proxy https://your-domain.example.com/ to http://127.0.0.1:8000/. cloudimg support can provide a worked reverse proxy and TLS configuration for your environment.
Maintenance
- Service control: manage the server with
systemctl(node-media-server). Logs are in the journal:journalctl -u node-media-server. - Configuration: the runtime configuration lives in
/opt/node-media-server/app.js; the per instance secrets are in the systemd EnvironmentFile/etc/node-media-server/nms.env(0640 root:root). - Rotating secrets: to force fresh per instance secrets, remove
/var/lib/cloudimg/node-media-server-firstboot.doneand restart thenode-media-server-firstbootservice, then restart the server. - OS updates: apply operating system security updates through your normal patch process (
apt-get updateand upgrade on Ubuntu).
Support
Every deployment is backed by 24/7 cloudimg support via email and live chat at support@cloudimg.co.uk. Support covers deployment and instance sizing, publisher and player integration, URL signing and authentication, TLS termination and custom domains, reverse proxy and CDN fronting, and version upgrades within the stable line. Include your instance ID and AWS Region to expedite troubleshooting.