Moonlight Web
An unofficial Moonlight Client allowing you to stream your pc to the Web. It hosts a Web Server which will forward Sunshine traffic to a Browser using the WebRTC Api.!An image displaying: PC with sunshine and moonlight web installed, a browser making requests to it
Overview
- Manual Installation - Docker Installation - Streaming over the Internet - Configuring https - Proxying via Apache 2 - Authentication with a Reverse Proxy - Using Web Socket TransportLimitations
- Features that only work in a Secure Context -> How to configure a Secure Context / https
Installation
You can install it manually or with docker
Install Manually
- Install Sunshine
- Download the compressed archive for your platform and uncompress it or build it yourself
- Run the "web-server" executable
- Go to
localhost:8080and view the web interface. You can also the change bind address.
NOTE
A config.json file is not generated automatically on first startup.
If you plan to follow the configuration guides below, you will need to create a config.json with ./web-server config generate
Setup
- Add a new user by typing in your name and password. The first user to login will be created and will be the admin.
- Add a new pc (
) with the address as
localhostand leave the port empty (if you've got the default port)
- Pair your pc by clicking on the host (
). Then enter the code in sunshine
- Launch an app
Streaming over the Internet
- Forward the web server port on your router (default is
8080; HTTP is80, HTTPS is443).
bind_address option.
When running on a local network, WebRTC peers usually negotiate connections without any issues.
When streaming over the Internet, the built-in STUN servers will attempt to establish a direct peer-to-peer WebRTC connection. This works for most home networks, but may fail in more restrictive environments (for example, corporate firewalls or strict NAT configurations).
If a direct WebRTC connection cannot be established, you have a few options:
- Use a TURN server (recommended)
- Forward ports directly
- Use WebSocket transport as a fallback
Configure a turn server
- Host and configure a turn server like coturn or use other services to host one for you.
- Add your turn server to your WebRTC Ice Server list
{
"webrtc": {
"ice_servers": [
{
"urls": [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:3478",
"stun:stun.l.google.com:5349"
]
},
{
"urls": [
"turn:yourip.com:3478?transport=udp",
"turn:yourip.com:3478?transport=tcp",
"turn:yourip.com:5349?transport=tcp"
],
"username": "your username",
"credential": "your credential"
}
]
}
}
Some (business) firewalls might be very strict and only allow tcp on port 443 for turn connections if that's the case also bind the turn server on port 443 and add "turn:yourip.com:443?transport=tcp" to the url's list.
Port forward
- Set the WebRTC Port Range to a fixed range
{
"webrtc": {
"port_range": {
"min": 40000,
"max": 40010
}
}
}
- Forward the port range specified in the previous step as
udp.
- Configure WebRTC Nat 1 To 1 to advertise your public ip (Optional: WebRTC stun servers can usually automatically detect them):
{
"webrtc": {
"nat_1to1": {
"ice_candidate_type": "host",
"ips": [
"74.125.224.72"
]
}
}
}
It might be helpful to look what kind of nat your pc is behind:
Configuring https
You can configure https directly with the Moonlight Web Server.- You'll need a private key and a certificate.
pip install pyOpenSSL
python ./generate_certificate.py
- Copy the files
server/key.pemandserver/cert.peminto yourserverdirectory.
- Configure the private key and certificate https using the certificates
{
"web_server": {
"certificate": {
"private_key_pem": "./server/key.pem",
"certificate_pem": "./server/cert.pem"
}
}
}
Proxying via Apache 2
It's possible to proxy the Moonlight Website using Apache 2.Note: When you want to use https, the Moonlight Website should use http so that Apache 2 will handle all the https encryption.
- Enable the modules
mod_proxy,mod_proxy_wstunnel
sudo a2enmod mod_proxy mod_proxy_wstunnel
- Create a new file under
/etc/apache2/conf-available/moonlight-web.confwith the content:
# Example subpath "/moonlight" -> To connect you'd go to "http://yourip.com/moonlight/"
Define MOONLIGHT_SUBPATH /moonlight
The address and port of your Moonlight Web server
Define MOONLIGHT_STREAMER YOUR_LOCAL_IP:YOUR_PORT
ProxyPreserveHost on
Important: This WebSocket will help negotiate the WebRTC Peers
<Location ${MOONLIGHT_SUBPATH}/api/host/stream/web_socket>
ProxyPass ws://${MOONLIGHT_STREAMER}${MOONLIGHT_SUBPATH}/api/host/stream/web_socket
ProxyPassReverse ws://${MOONLIGHT_STREAMER}${MOONLIGHT_SUBPATH}/api/host/stream/web_socket
</Location>
ProxyPass ${MOONLIGHT_SUBPATH}/ http://${MOONLIGHT_STREAMER}${MOONLIGHT_SUBPATH}/
ProxyPassReverse ${MOONLIGHT_SUBPATH}/ http://${MOONLIGHT_STREAMER}${MOONLIGHT_SUBPATH}/
- Enable the created config file
sudo a2enconf moonlight-web
- Change config to include the prefixed path
{
"web_server": {
"url_path_prefix": "/moonlight"
}
}
- Use https with a certificate (Optional)
Authentication using a Reverse Proxy
Authentication with a reverse proxy works by the proxy adding custom headers to the request of the user. In this example the username header is namedX-Forwarded-User.
Make sure that the header is not changeable by any external request and only the proxy can set this header.
Enable proxy authentication by setting the forwarded header username option. By default the auto create missing user option is turned on even if it's not specified in the config.
{
"web_server": {
"forwarded_header": {
"username_header": "X-Forwarded-User",
"auto_create_missing_user": true
}
}
}
If auto_create_missing_user is enabled, newly created users will be assigned the role configured as the default in the Admin Panel.
Using WebSocket Transport
In some networks (for example, corporate or highly restricted environments), establishing a WebRTC connection can be difficult or may not work at all. To support these cases, you can stream data over WebSockets using the same HTTP or HTTPS port that your server already exposes.
You can force the Web Sockets by setting the Data Transport option to Web Sockets.
There are a few important things to be aware of when using WebSockets for streaming:
- The browser’s
VideoDecoderAPI is only available when your site is served over HTTPS (a secure context).
- If the application is not running in a secure context, it will fall back to an older video playback API, which may introduce noticeable latency.
Config
The config file is underserver/config.json relative to the executable.
Here are the most important settings for configuring Moonlight Web.
Most options have command line arguments or environment variables associated with them.
./web-server help
Generate the config with:
./web-server config generate
For a full list of values look into the Rust Config module.
Bind Address
The address and port the website will run onEnvironment Variable: BIND_ADDRESS=0.0.0.0:8080
{
"web_server": {
"bind_address": "0.0.0.0:8080"
}
}
Default User
The user id which is selected by default when providing no login. Go into the Admin Panel and look for the user id of the user you want to make the default.{
"web_server": {
"default_user_id": 1284358932
}
}
Https Certificates
If enabled the web server will use https with the provided certificate dataEnvironment Variables:
SSL_PRIVATE_KEY=./server/key.pemSSL_CERTIFICATE=./server/cert.pem
{
"web_server":{
"certificate": {
"private_key_pem": "./server/key.pem",
"certificate_pem": "./server/cert.pem"
}
}
}
WebRTC Port Range
This will set the port range on the web server used to communicate when using WebRTCEnvironment Variable: WEBRTC_PORT_RANGE=40000:40010
{
"webrtc": {
"port_range": {
"min": 40000,
"max": 40010
}
}
}
WebRTC Ice Servers
A list of ice servers for webrtc to use.{
"webrtc": {
"ice_servers": [
{
"urls": [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:3478",
"stun:stun.l.google.com:5349"
]
}
]
}
}
You can also set ice servers with environment variables:
ENV WEBRTC_ICE_SERVER_0_URL=stun:stun.l.google.com:5349
ENV WEBRTC_ICE_SERVER_0_USERNAME=name
ENV WEBRTC_ICE_SERVER_0_CREDENTIAL=cred
ENV WEBRTC_ICE_SERVER_1_URL=stun:stun1.l.google.com:5349
will currespond to the ice server
{
"webrtc": {
"ice_servers": [
{
"urls": [
"stun:stun.l.google.com:19302",
],
"username": "name",
"credential": "cred"
},
{
"urls": [
"stun:stun1.l.google.com:5349"
]
}
]
}
}
You can disable all default ice servers with the cli argument --disable-default-webrtc-ice-servers or the environment variable DISABLE_DEFAULT_WEBRTC_ICE_SERVERS.
WebRTC Ice Server Script
The given script will be executed on every stream start to dynamically generate ice servers.{
"webrtc": {
"ice_server_script": "./server/ice_server_script.sh"
}
}
The script must return a json list that follows the same structure as the WebRTC Ice Servers config option.
Linux example using a bash script:
#!/bin/bash
Assign arguments to variables
username="user"
credential="cred"
Output the json into stdout
echo "[
{
\"urls\": [
\"turn:example.com\"
],
\"username\": \"$username\",
\"credential\": \"$credential\"
}
]"
Windows example using a batch script:
@echo off
:: Assign arguments to variables
set "username=user"
set "credential=cred"
:: Output the JSON with dynamic values
echo [
echo {
echo "urls": [
echo "turn:example.com"
echo ],
echo "username": "%username%",
echo "credential": "%credential%"
echo }
echo ]
WebRTC Nat 1 to 1 ips
This will advertise the ip as an ice candidate on the web server. It's recommended to set this but stun servers should figure out the public ip.ice_candidate_type:
host-> This is the ip address of the server and the client can connect tosrflx-> This is the public ip address of this server, like an ice candidate added from a stun server.
{
"webrtc": {
"nat_1to1": {
"ice_candidate_type": "host",
"ips": [
"74.125.224.72"
]
}
}
}
You can also use the cli argument --webrtc-nat-1to1-host or environment variable WEBRTC_NAT_1TO1_HOST to use a ip as a host candidate type. This will do the same as the json above.
ENV WEBRTC_NAT_1TO1_HOST=74.125.224.72
Url Path Prefix
This is useful when rerouting the web page using services like Apache 2. Will always append the prefix to all requests made by the website.Environment Variable: PATH_PREFIX=/moonlight
{
"web_server": {
"url_path_prefix": "/moonlight"
}
}
Forwarded Header Username
The header that will give the authenticated username to this web server.{
"web_server": {
"forwarded_header": {
"username_header": "X-Forwarded-User"
}
}
}
Forwarded Header Auto Create Missing User
Automatically create a new user when the requested user specified in the username_header is not found.{
"web_server": {
"forwarded_header": {
"auto_create_missing_user": true
}
}
}
Forwarded Header Ignore Case
Perform a case-insensitive lookup for the user in the in the username_header. If multiple users match the given name, the request will fail.{
"web_server": {
"forwarded_header": {
"ignore_case": true
}
}
}
Migrating to v2
- Some config options have changed so backup your old config by renaming it to something like
old_config.json.
- Start the web server which will generate the new config.
- Move your configurations to the new config
- The first user to login will be created and will be an admin. All previously stored hosts will be moved to this user.
- Proxy path changed:
ProxyPass ${MOONLIGHT_SUBPATH}/ http://${MOONLIGHT_STREAMER}/to
ProxyPass ${MOONLIGHT_SUBPATH}/ http://${MOONLIGHT_STREAMER}${MOONLIGHT_SUBPATH}/
- Proxying via Apache 2
Migrating to v3
Changes:- replaced openssl by rustls
- replaced moonlight-common-c by moonlight-common-rust
- moved web socket endpoint from
/api/host/streamto/api/host/stream/web_socket
config.jsonis not generated at first startup and can optionally be used for more granular control
./web-server config generate, if required
- moved
default_user_idanddefault_role_idfrom theconfig.jsoninto thedata.jsonfile
- removed old unused
default_settingsvalue in the config - removed
webrtc.network_typessetting in the config
Contributors
Thanks to everyone who contributed to make this software better :).Building
Clone this repository:git clone https://github.com/MrCreativ3001/moonlight-web-stream.git
A Rust installation is required.
Moonlight Web consists the web server binary and a web frontend:
Building the Web Server
Runcargo build --release
.
You can use Cargo Cross for cross compilation:
cross build --release --target YOUR_TARGET
Note: windows only has the gnu target x86_64-pc-windows-gnu. macOS is built natively for aarch64-apple-darwin and x86_64-apple-darwin.
Building the Frontend
Build the web frontend with npm.To generate bindings to rust code it is using Uniffi Bindgen React Native. This has a dependency on wasm-bindgen.
cargo install wasm-bindgen-cli
npm install
npm run build
The build output will be in dist/.
If you're compiling in:
- debug mode -> the folder needs to be called
dist/ - release mode -> the folder needs to be called
static/