Run a persistent Oryx media server, verify it locally, and publish its browser interface without router port forwarding
Oryx, formerly called SRS Stack, is an open-source video platform for live streaming, WebRTC, recording, transcoding, virtual live events, and related media workflows. This guide installs the repository's current Docker quick-start image, preserves application data on the host, verifies the local browser interface, and explains routine operations and troubleshooting. We then connect the verified HTTP endpoint to Localtonet as a separate remote-access step. The resulting HTTP tunnel covers Oryx web traffic only, so RTMP, WebRTC media, and SRT require separate protocol-appropriate planning.
๐ What's in this guide
What we are building
Oryx is an all-in-one video solution built with components including Go, React, SRS, FFmpeg, WebRTC, and Redis. It supports protocols such as RTMP, WebRTC, HLS, HTTP-FLV, and SRT, while providing browser-based management and features including authentication, recording, forwarding, transcoding, virtual live events, and automatic HTTPS.
The repository's Docker quick start runs Oryx in one container. Docker publishes selected container ports on the host, while a bind-mounted /data directory keeps Oryx configuration, Redis data, recordings, uploads, and other state outside the container's writable layer. After startup with the default mapping, the documented local management endpoint is http://localhost.
Remote access is intentionally the second phase. First, Oryx must work directly on its host. We then configure a Localtonet HTTP tunnel whose local target is the published host-side HTTP port. The Localtonet client establishes an outbound connection to one of our relay servers, so this workflow does not require an inbound router port-forwarding rule, a public IP address, VPN setup, or an inbound firewall change.
ossrs/oryx:5 image and publishes the documented web and media ports.
/data directory is bind-mounted to a host directory so state can survive container replacement.
How Docker forwards traffic to Oryx
In the repository command, requests sent to host TCP port 80 are forwarded to container TCP port 2022. That is why http://localhost reaches Oryx even though the internal HTTP listener uses port 2022. Docker port mappings use the form host-port:container-port.
| Host port | Container port | Transport | Purpose |
|---|---|---|---|
80 |
2022 |
TCP | Oryx HTTP interface and HTTP-based services |
443 |
2443 |
TCP | Oryx HTTPS service |
1935 |
1935 |
TCP | RTMP stream publishing |
8000 |
8000 |
UDP | WebRTC media traffic such as RTP packets |
10080 |
10080 |
UDP | SRT stream publishing |
This guide publishes the service listening on host TCP port 80 or an alternate HTTP host port. RTMP uses raw TCP, while the documented WebRTC media and SRT listeners use UDP. Those protocols do not travel through the same Localtonet HTTP tunnel. If your deployment requires remote RTMP or UDP transport, evaluate a separate Localtonet TCP or UDP tunnel with the matching local listener.
Understand the Oryx documentation and release channels
Oryx currently presents several version signals that should not be treated as interchangeable. The repository quick start uses ossrs/oryx:5. That makes :5 the repository's current quick-start reference, but it does not mean it is the newest exact release tag.
The available Oryx documentation page is explicitly labeled as unreleased SRS 8.0 unstable documentation and directs readers to SRS 6.0 stable for up-to-date stable documentation. At the same time, the GitHub releases channel identifies Oryx v7.15.26 as the latest release in the evidence reviewed for this revision. That release provides the exact image reference ossrs/oryx:v7.15.26.
| Channel | Observed reference | How to use it |
|---|---|---|
| Repository quick start | ossrs/oryx:5 |
Use it to reproduce the repository's documented introductory Docker workflow. |
| Documentation site | SRS 8.0 unstable, with a link to 6.0 stable | Check the version banner before applying instructions to a production Oryx installation. |
| GitHub release | v7.15.26 |
Use the release page and changelog when evaluating an exact pinned version. |
This tutorial retains ossrs/oryx:5 in its installation command because that is what the current repository quick start shows. It does not claim that :5 is equivalent to v7.15.26, that every instruction from the unstable 8.0 documentation applies to it, or that changing between those tags is automatically compatible with an existing data directory.
Back up the persistent data directory, read the changelog for the exact target version, and test the upgrade with non-production data or a recoverable copy. The available evidence does not establish one risk-free upgrade procedure across the quick-start tag, the latest exact release, and unreleased documentation.
Prerequisites and deployment decisions
Prepare a machine with Docker installed and its service running. The Oryx documentation strongly recommends Docker and advises Ubuntu 20 for its documented environment because other systems may encounter issues. The project lists other installation routes, including Helm, an Ubuntu archive, cloud marketplace options, and an aaPanel plugin, but this tutorial is scoped to the single-container Docker workflow.
You need permission to run Docker, create a persistent directory, and bind the selected host ports. Existing web servers, reverse proxies, or containers may already occupy TCP ports 80, 443, or 1935. UDP ports 8000 and 10080 can also conflict with existing services.
Decide where Oryx data should live before starting the container. The repository command uses $HOME/data, which is a data directory under the current shell user's home directory. You can choose another appropriate host path, but it must remain mapped to /data inside the container.
Docker describes this arrangement as a bind mount because an existing host path is mounted into the container. Review the operational and security implications in Docker's bind-mount documentation, especially if the host path contains credentials or valuable recordings.
What Oryx stores under /data
The persistent tree can include configuration, Redis state, recordings, uploads, virtual-live files, transcription data, cache files, ACME challenge material, and other application state. Documented directories include config, dvr, record, redis, signals, upload, vlive, transcript, nginx-cache, and srs-s3-bucket.
The config directory contains Oryx configuration and SSL-related files. The redis directory contains Redis data such as publishing secrets and recording configuration. Recordings, uploaded media, caches, and generated assets can consume substantial capacity, so select a suitable filesystem and monitor both free space and inode usage.
Oryx explicitly warns that /data should be mounted to a host location. Without that mount, data remains in the container's writable layer and can be lost when the container is removed or replaced. A restart policy is not a substitute for persistent storage or backups.
Choose the host-side HTTP port
The default command claims host ports 80, 443, 1935, 8000/udp, and 10080/udp. If another process already uses one of them, Docker will normally fail to publish that port and the container may not start.
Oryx permits publishing the HTTP listener on host port 2022 instead of port 80, using -p 2022:2022. It likewise permits host port 2443 for the container's HTTPS listener. The browser URL and Localtonet target must always use the host-side port you selected.
Install Oryx with Docker
The commands below follow the repository's current Docker quick start. The shell syntax is intended for a Linux-style shell in which $HOME refers to the current user's home directory.
Confirm Docker is available
Verify that the Docker client can communicate with the Docker service. If it cannot, install or start Docker using the supported procedure for the host operating system.
Create the persistent directory
Create $HOME/data so the source path is deliberate and can be inspected, protected, monitored, and backed up.
Run the repository quick-start container
Create a detached container named oryx, apply the always-restart policy, mount persistent storage, and publish the documented web and media ports.
Inspect startup instead of assuming readiness
Oryx initializes several components. Check the container state and logs before relying on the browser interface.
docker --version
mkdir -p "$HOME/data"
docker run --restart always -d -it --name oryx \
-v "$HOME/data:/data" \
-p 80:2022 \
-p 443:2443 \
-p 1935:1935 \
-p 8000:8000/udp \
-p 10080:10080/udp \
ossrs/oryx:5
Docker prints a container identifier if creation succeeds. The --restart always option applies Docker's always restart policy. The -d option runs the container in the background, while --name oryx gives later maintenance commands a stable target.
The image reference ossrs/oryx:5 is retained specifically because it appears in the current repository quick start. If you instead choose an exact release such as ossrs/oryx:v7.15.26, treat that as a separate version-selection decision and validate it against its release notes and your existing data.
Use alternate HTTP and HTTPS host ports
If ports 80 or 443 are unavailable, the Oryx material documents host ports 2022 and 2443 as alternatives:
docker run --restart always -d -it --name oryx \
-v "$HOME/data:/data" \
-p 2022:2022 \
-p 2443:2443 \
-p 1935:1935 \
-p 8000:8000/udp \
-p 10080:10080/udp \
ossrs/oryx:5
With this mapping, open http://localhost:2022. Later, configure Localtonet to connect to host port 2022, not port 80.
Both commands create a container named oryx and claim the same RTMP and UDP ports. Select the mapping appropriate for your host and run only that command. If an earlier failed attempt created the named container, inspect it before removing or replacing it.
Verify Oryx before enabling remote access
Local verification separates Oryx and Docker problems from Localtonet configuration problems. Do not create the public route until the host-side HTTP endpoint responds and you know which port is active.
Check the container and its logs
docker ps --filter name=oryx
Confirm that the container appears as running and that its port listing reflects the command you selected. If it is absent from the running list, inspect stopped containers and read the logs:
docker ps -a --filter name=oryx
docker logs oryx
docker logs --tail 100 oryx
A container can be created successfully and then exit during application startup. Investigate the actual error. Common categories include a host-port collision, inability to access the bind-mounted directory, insufficient disk capacity, or an image startup failure.
Open the local browser interface
For the default mapping, open:
http://localhost
For the alternate mapping, open:
http://localhost:2022
A response confirms that Docker is forwarding the selected host TCP port to Oryx's internal port 2022. Complete any setup or sign-in flow presented by the installed version. Browser screens can change between releases, so this guide does not assume fixed labels for first-run controls.
When testing from another computer on the same LAN, replace localhost with the Oryx host's private address and retain the host-side port. This test depends on the Docker publishing mode, host firewall, and network policy. It will intentionally fail if you later adopt the loopback-only hardening variation.
Separate web verification from media verification
Loading the management interface proves that the HTTP listener works. It does not prove that RTMP publishing, WebRTC media, SRT publishing, recording, restreaming, or transcoding is configured correctly. Those workflows can introduce additional protocol, encoder, certificate, browser, authentication, and addressing requirements.
Oryx specifically warns that browser-based WebRTC WHIP should not use localhost or 127.0.0.1. Its documentation calls for a private IP, public IP, or domain and points users toward HTTPS setup. That requirement is separate from opening the management interface over HTTP.
Configuration, persistence, and routine operations
Set and protect the management password
Oryx documents the MGMT_PASSWORD environment variable for setting the management administrator password. It also saves that value in /data/config/.env. Because /data persists on the host, treat the source directory as sensitive application state and restrict it to authorized administrators.
Do not place a real password in shared documentation, screenshots, issue reports, or source repositories. Supplying a secret directly on a command line can leave it in shell history and may expose it to users with Docker inspection access. Choose a secret-handling method appropriate for your environment.
Oryx also documents REACT_APP_LOCALE for the interface language, with en and zh as documented values and en as the default. Take any additional environment variables from documentation that matches the installed release rather than copying options from a different channel.
A user who can inspect or control Docker containers may be able to view configuration, change mounts, replace images, or access persistent Oryx data. Limit Docker and filesystem permissions to trusted administrators.
Start, stop, restart, and inspect Oryx
docker stop oryx
docker start oryx
docker restart oryx
docker logs oryx
docker logs --tail 100 oryx
Stopping the container makes Oryx unavailable locally and through any tunnel targeting it. A Localtonet tunnel configuration may remain present, but it cannot produce a working Oryx response while the target is down. Starting or restarting the container should preserve mounted data because /data points to the host directory.
Understand container replacement
Removing a container is not the same as deleting the bind-mounted host directory. Files in $HOME/data remain unless an administrator explicitly removes them. That separation makes container replacement practical, but only when the mount is correct and the host directory is included in a tested backup process.
Before changing image tags, back up the persistent directory and review the release-specific changelog. The available Oryx channels do not establish one universal upgrade sequence, so avoid assuming that pulling a newer image and reusing the same data directory is always safe.
Back up data with application awareness
The data directory can contain configuration, Redis state, recordings, uploaded files, cache data, credentials, and generated media. A filesystem copy taken while services are actively writing may not provide an application-consistent recovery point. For an important deployment, determine an appropriate quiescing or backup procedure for the installed Oryx version and test restoration on a separate system.
Monitor storage growth. DVR recordings, uploads, virtual-live assets, transcription output, and caches can grow independently. A full filesystem can prevent Oryx from recording or updating state even when the container still appears to be running.
Access the Oryx web interface remotely with Localtonet
Continue only after http://localhost or http://localhost:2022 works. The Localtonet client can run directly on the Oryx host or on another device that can reach the selected host IP address and port.
Our client establishes an outbound connection to a Localtonet relay server. The HTTP tunnel then provides a public HTTPS address for the local HTTP target. The tunnel remains available only while the selected client device is connected and the tunnel is running.
Operating-system-specific Localtonet installation commands are not established by the evidence available for this revision, so we do not invent commands or package names. Install the current Localtonet client using the supported download and installation flow presented for your operating system, then run it on the device that can reach Oryx. After installation, follow the sequence below and consult the official Localtonet HTTP tunnel documentation for the current interface.
Install and run the Localtonet client
Install the supported client for the device's operating system and keep it running. The client must be on the Oryx host or another device with network access to the Oryx host-side HTTP listener.
Open the HTTP tunnel configuration
In the Localtonet dashboard, begin a new HTTP tunnel configuration for the Oryx browser endpoint.
Select the Process Type
Choose Random Sub Domain, Custom Sub Domain, or Custom Domain as appropriate and available. All three process types serve the configured local content at a public HTTPS address. Check current documentation before making custom-domain DNS changes.
Select the device-specific AuthToken
Select the AuthToken belonging to the Localtonet client device that will run this tunnel. Tokens identify devices and must not be guessed, published, or copied into examples.
Select a currently available relay server
Choose a relay server or region shown in the current dashboard. Do not copy a hardcoded server code because availability can vary by account, plan, region, or product state.
Enter the local IP address and host-side port
When Localtonet runs on the Oryx host, use 127.0.0.1 with port 80 for -p 80:2022, or port 2022 for -p 2022:2022. If Localtonet runs on another device, use an Oryx host address reachable from that device.
Create the HTTP tunnel
Save or create the tunnel configuration after reviewing the selected Process Type, AuthToken, relay server, local IP address, and local port. Creation records the configuration but does not mean the tunnel is running.
Press Start and verify the public URL
Press Start, wait for the client and tunnel to show as connected, and open the assigned public HTTPS address. Test from an external network and confirm that Oryx's normal authentication boundary remains active.
The local target is the Docker host endpoint, not an arbitrary container address. With -p 80:2022, Localtonet targets host port 80. With -p 2022:2022, it targets host port 2022. The container-side value on the right of the Docker mapping does not replace the host-side port.
127.0.0.1 means the device or network namespace making the connection. It is appropriate when Localtonet runs directly on the Oryx Docker host. If Localtonet runs on another computer, use the Oryx host's reachable private address. A Localtonet client running inside its own container requires additional container-network planning that is outside this evidenced workflow.
What the HTTP tunnel covers
| Oryx traffic | Protocol | Covered by this HTTP tunnel? | Remote-access consideration |
|---|---|---|---|
| Browser interface | HTTP | Yes | Targets the published Oryx HTTP host port. |
| HTTP API or HTTP delivery | HTTP | Potentially | Behavior depends on Oryx authentication, routes, generated URLs, and configuration. |
| RTMP publishing | TCP | No | Requires separate raw TCP planning if remote publishing is needed. |
| WebRTC media | UDP on the documented media port | No | Requires separate UDP and WebRTC-aware addressing, negotiation, and HTTPS planning. |
| SRT publishing | UDP | No | Requires separate UDP planning if remote publishing is needed. |
Browser pages may reference additional endpoints or advertise media addresses based on Oryx configuration. A successfully loaded console therefore does not prove that every player, publisher, callback, or WebRTC negotiation path works remotely. Validate the exact feature being deployed and add only the protocol listeners it actually needs.
Harden a remotely accessible Oryx deployment
A public URL changes the threat model. A service previously limited to a host or private network can receive internet traffic while the tunnel runs. Localtonet removes the need for inbound router configuration, but it does not replace application authentication, authorization, updates, safe Docker configuration, backups, or least-privilege administration.
Protect Oryx authentication
Set a strong, unique management password and do not share administrator credentials with viewers or stream publishers. Oryx documents built-in authentication for its console and proxied SRS HTTP API. It also generates and stores stream tokens in Redis and verifies publishing tokens for RTMP, SRT, and WHIP/WebRTC workflows.
Keep authentication enabled even if the public URL appears difficult to guess. A URL is an address, not an authorization boundary. After upgrades, test both permitted and rejected requests rather than assuming the authentication behavior is unchanged.
Understand Docker's default port publishing behavior
Docker's port-publishing documentation explains that a published port is exposed on host addresses by default unless a specific host address is supplied. As a result, -p 80:2022 can make Oryx's HTTP listener reachable beyond loopback, subject to the host, firewall, cloud, and network configuration. This is separate from the Localtonet tunnel.
If Localtonet runs on the same host and your goal is to access only the Oryx HTTP interface through the tunnel, you can deliberately bind the HTTP publication to loopback. The following is an optional hardened variation, not the Oryx repository's official quick-start command:
docker run --restart always -d -it --name oryx \
-v "$HOME/data:/data" \
-p 127.0.0.1:80:2022 \
ossrs/oryx:5
In this variation, Localtonet on the same host targets 127.0.0.1:80. Binding to loopback reduces direct HTTP exposure through the host's LAN or public interfaces. It also means another LAN device, including a Localtonet client on another machine, cannot reach that HTTP listener through the host's private IP.
This minimal variation omits the repository's HTTPS, RTMP, WebRTC UDP, and SRT UDP publications and restricts HTTP to loopback. Do not assume every Oryx feature will work with it. Test the management interface and every required streaming workflow. Add only the specific mappings your deployment needs, using deliberate host bindings and appropriate access controls.
If you prefer host port 2022, the same loopback principle can be applied as -p 127.0.0.1:2022:2022. Localtonet would then target 127.0.0.1:2022. Do not combine this with a requirement for direct LAN access unless you provide a separately controlled access path.
Protect persistent data and tokens
Protect the bind-mounted directory because it may contain administrator settings, publishing secrets, Redis state, certificates, recorded media, and uploaded content. Restrict filesystem permissions, include the directory in a controlled backup policy, and avoid placing it inside a broadly synchronized or publicly shared path.
Localtonet AuthTokens are device-specific. Do not put them in Docker commands, screenshots, support posts, source repositories, or examples. If a token is disclosed, replace it through the appropriate account workflow rather than continuing to use it.
Stop access when it is no longer needed
Stop the Localtonet tunnel when remote access is not required, and delete obsolete tunnel configurations that no longer have an operational owner. Stopping the tunnel removes the public route but does not stop Oryx. Stopping Oryx makes the local target unavailable but does not necessarily delete or stop the tunnel configuration.
Test the public URL from a separate network. Confirm the sign-in boundary, verify that unauthenticated users cannot reach protected functions, and make sure Docker-published ports have not also been exposed through a router, cloud firewall, or host policy.
Troubleshooting Oryx and Localtonet
The container name is already in use
Docker requires unique container names. Inspect the existing object before taking action:
docker ps -a --filter name=oryx
docker logs oryx
If it is the intended deployment, start or repair it rather than creating a duplicate. If it is a failed disposable attempt and its important data is safely stored in the bind mount, remove the stopped container before retrying:
docker rm oryx
Do not remove it if you are uncertain where its data resides. Confirm the mount first, particularly if the original command may have omitted /data.
Docker reports that a port is already allocated
Another process or container is using a requested port. Determine whether the conflict affects TCP 80, TCP 443, TCP 1935, UDP 8000, or UDP 10080. Stop or reconfigure the conflicting service only when it is operationally safe.
For web-port conflicts, use the documented alternate mapping 2022:2022 and, if required, 2443:2443. Update both the browser URL and Localtonet local port to match the host-side mapping.
The container starts and then exits
Run docker ps -a and docker logs oryx. Confirm that the host data directory exists, Docker can access it, the filesystem has space, and the image initialized successfully. The available Oryx release evidence includes version-specific startup fixes, which is another reason to review the exact release notes before changing tags.
Localhost does not open Oryx
-p 80:2022means browse tohttp://localhost.-p 2022:2022means browse tohttp://localhost:2022.-p 127.0.0.1:80:2022limits access to processes connecting through the Oryx host's loopback interface.
If the browser runs on another device, its own localhost does not refer to the Oryx host. Use the Oryx host's private address only when the Docker mapping listens beyond loopback and applicable firewall policy permits the connection.
The Localtonet public URL returns an error
- Confirm that the Oryx container is running.
- Open the Oryx endpoint locally on the Docker host.
- Confirm that the selected Localtonet client device is connected.
- Verify that the HTTP tunnel uses the intended Process Type.
- Verify that the selected AuthToken belongs to the device running the tunnel.
- Confirm that the selected relay server is currently available.
- Check the local IP address from the Localtonet client's perspective.
- Check the host-side port, either
80or2022in these examples. - Confirm that the tunnel was created and then started.
If Localtonet runs on another machine, test the Oryx target directly from that machine. A loopback-only Docker binding, host firewall, incorrect private address, or unavailable LAN route can prevent access even when Oryx works on its own host.
The console works remotely, but streaming does not
This is expected when the streaming path uses a protocol outside HTTP. RTMP uses TCP port 1935, WebRTC media uses the documented UDP port 8000, and SRT uses UDP port 10080. An HTTP tunnel to port 80 or 2022 does not carry those connections.
Identify the protocol used by the publisher and player, then evaluate a separate Localtonet tunnel of the matching family. WebRTC can additionally require appropriate addressing, HTTPS, browser permissions, and negotiation behavior.
WebRTC WHIP fails with localhost
Oryx warns against using localhost or 127.0.0.1 for browser-based WebRTC WHIP. Use an appropriate private IP, public IP, or domain and configure HTTPS according to documentation that matches the selected Oryx version. A working public console URL does not automatically complete WebRTC media configuration.
Settings or recordings disappear after recreation
Confirm that the container was created with -v "$HOME/data:/data" and that the expected files exist in that host directory. Possible causes include using a different operating-system account, changing $HOME, mistyping the source path, or recreating the container with another mount.
Stop making changes until the previous data directory is located. Once recovered, document its absolute host path and include it in backup, capacity-monitoring, and recovery procedures.
Frequently asked questions
Which Docker image does this tutorial use?
It uses ossrs/oryx:5 because that is the current repository quick-start reference. It is not presented as the newest exact release. The reviewed GitHub release channel identifies v7.15.26 as the latest release, and upgrades or tag changes require release-specific validation.
Why is the /data bind mount required?
Oryx stores configuration and operational data under /data. Mapping it to a host directory allows the data to survive container replacement. Without the mount, deleting the container can remove data stored in its writable layer.
Can I use port 2022 instead of port 80?
Yes. Use -p 2022:2022, open http://localhost:2022, and configure the Localtonet HTTP tunnel to target host port 2022.
Can I restrict Oryx HTTP access to the same host?
Yes. A mapping such as -p 127.0.0.1:80:2022 publishes Oryx HTTP on loopback rather than all host interfaces. This is an optional hardening variation, not the official Oryx quick-start command. It prevents direct LAN access and requires Localtonet to run on the same host.
Does the Localtonet HTTP tunnel expose RTMP, WebRTC, and SRT?
No. The tunnel in this guide targets Oryx's HTTP listener. RTMP is raw TCP, while the documented WebRTC media and SRT listeners use UDP. Each non-HTTP service requires separate protocol-appropriate planning and, when needed, a separate matching tunnel.
Does Localtonet require router port forwarding?
No. Our client establishes an outbound connection to a Localtonet relay server. The configured local service can then receive traffic through its assigned public address without an inbound router port-forwarding rule, public IP address, VPN setup, or inbound firewall change.
Must the Localtonet client run on the Oryx host?
No. It can run on another device that can reach the Oryx host and port. Use 127.0.0.1 only when the client runs directly on the Oryx host. A loopback-only Docker mapping also requires same-host tunneling.
Is creating a Localtonet tunnel enough to make it available?
No. Creation saves the configuration. You must press Start, and the selected Localtonet client must be connected. The public route remains available only while the client is connected and the tunnel is running.
Does the public URL replace Oryx authentication?
No. Keep Oryx authentication enabled, use a strong management password, protect publishing credentials, and apply least privilege. Localtonet provides connectivity to the configured target, not permission to use Oryx.
Connect your verified Oryx HTTP service with Localtonet
Start Oryx locally, confirm its browser interface on the selected host port, and then create an HTTP tunnel using the correct Process Type, device AuthToken, relay server, local IP address, and port. Keep Oryx authentication enabled and add separate protocol-specific tunnels only when your streaming workflow requires them.
Get Started Free โ