Headless streaming server for Moonlight clients, written in Rust.
翻译准备中
媒体Rust · NixGitHub @hgaiser自行安装运营者未确认
试用过了吗? 点一下就好,无需登录。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Moonshine lets you stream games from your PC to any device running Moonlight. Your keyboard, mouse, and controller inputs are sent back to the host so you can play games remotely as if you were sitting in front of it.
.deb, .rpm, Nix, AUR, and an install script for SteamOS. Tested on Arch Linux, but reported to work on other distributions too.The recommended method is to install through the AUR using:
yay -S moonshine-bin
After installing, follow the distro-agnostic Enable the service steps below.
Download the latest .deb from the releases page and install it:
sudo apt install ./moonshine_*.deb
After installing, follow the Enable the service steps below.
Download the latest .rpm from the releases page and install it:
sudo dnf install ./moonshine-*.rpm
The package's post-install scripts set up udev rules, kernel modules, and the moonshine group automatically.
After installing, follow the Enable the service steps below.
This repository is also a nix flake, providing a package and a NixOS module that sets up the service for you. See nix/README.md for instructions, or install just the package on any distro with:
nix profile install github:hgaiser/moonshine
After installing, follow the Enable the service steps below (the NixOS module handles this for you when enabled).
Moonshine is now directly packaged in nixpkgs, you can add it to your system packages or enable the module directly:
environment.systemPackages = with pkgs; [ moonshine ];
services.moonshine = {
enable = true;
# Checkout more settings at https://search.nixos.org/options?query=moonshine
};
On Fedora Atomic distros, download the .rpm from the releases page and layer it:
sudo rpm-ostree install ./moonshine-*.rpm
sudo systemctl reboot
After reboot, follow the Enable the service steps below.
Use the installer script:
curl -fsSL https://github.com/hgaiser/moonshine/releases/latest/download/moonshine-install.sh | bash
This deploys moonshine to /opt/moonshine/ and configuration drop-ins to /etc/. The installer registers these files with SteamOS so they persist across atomic updates.
These steps apply to every installation method above (the service is a systemd unit).
Enable user lingering:
sudo loginctl enable-linger $USER
This allows Moonshine to run applications in the user's session even when the user is not logged in (when running headless).
If your user is always logged in when you want to stream, you can skip this step.
Enable the service to start on boot and run immediately:
sudo systemctl enable --now moonshine@$USER
Gamepad support when streaming headless (no active desktop session): add your user to the input group, then log out and back in (or reboot) for it to take effect:
sudo usermod -aG input $USER
Moonshine creates a virtual gamepad per streamed controller, and the streamed game must be able to read it. When streaming while a desktop session is active, your user is already granted access to input devices as the active seat, so this step is not needed there. Run moonshine healthcheck to verify — it reports an input group warning if the group is missing.
The following dependencies are required to build and run:
# Build dependencies
sudo pacman -S --asdeps \
clang \
cmake \
jq \
libc++ \
rust
# Runtime dependencies
sudo pacman -S \
gcc-libs \
glibc \
libevdev \
libxkbcommon \
mesa \
opus \
wayland \
xorg-xwayland
Then build:
cargo build --release --workspace
Set up the environment:
# Install uinput/uhid kernel modules
sudo install -Dm644 dist/moonshine-modules.conf /usr/lib/modules-load.d/moonshine.conf
sudo modprobe uinput uhid
# Install udev rules for input device access
sudo install -Dm644 dist/60-moonshine.rules /usr/lib/udev/rules.d/60-moonshine.rules
sudo udevadm control --reload-rules
# Install ferriscope's Vulkan WSI layer for game rendering
dist/install-wsi.sh # builds as you, asks for sudo only to install
Then run:
cargo run --release -- /path/to/config.toml
A configuration file is created automatically if the path you provide doesn't exist.
When using the AUR package, it defaults to $XDG_CONFIG_HOME/moonshine/config.toml.
When you connect with Moonlight for the first time, it will show a PIN. A notification will appear on the host that you can click to open the pairing page, or you can visit it manually at http://localhost:47989/pin .
You can also pair from the command line:
curl -X POST "http://localhost:47989/submit-pin" -d "uniqueid=0123456789ABCDEF&pin=<PIN>"
Each application runs in its own isolated streaming session. Add them to config.toml like this:
[[application]]
title = "Steam"
boxart = "/path/to/steam.png" # optional
command = ["/usr/bin/steam", "steam://open/bigpicture"]
steam_integration = true
title: The name shown in Moonlight.boxart (optional): Path to a cover image.command: The command to run. First entry is the executable, the rest are arguments.pre_command (optional): Commands to run before launching the application. Each entry is a separate command, executed in order. Runs synchronously — the session waits for all to finish.steam_integration (optional): Steam integration, as gamescope's -e; off by default. Turn it on for Steam (Big Picture), so its overlay and focus work. With it on, only Steam and Steam game windows can take focus, so leave it off for anything launched directly. Games from the Steam application scanner have it on.post_command (optional): Commands to run after the streaming session ends. Each entry is a separate command, executed in order. Runs synchronously — the server waits for all to finish.Example:
[[application]]
title = "Steam"
command = ["/usr/bin/steam", "steam://open/bigpicture"]
steam_integration = true
pre_command = [
["/usr/bin/systemctl", "stop", "conflicting.service"],
]
post_command = [
["/usr/bin/systemctl", "start", "conflicting.service"],
]
Scanners automatically detect installed applications so you don't have to add them manually.
Steam scanner — finds all installed Steam games:
[[application_scanner]]
type = "steam"
library = "$HOME/.local/share/Steam"
command = ["/usr/bin/steam", "-bigpicture", "steam://rungameid/{game_id}"]
Desktop scanner — finds applications from .desktop files:
[[application_scanner]]
type = "desktop"
directories = [
"$HOME/.local/share/applications",
"/usr/share/applications",
]
include_terminal = false
resolve_icons = true
Lutris scanner — finds all installed Lutris games:
[[application_scanner]]
type = "lutris"
command = ["/usr/bin/lutris", "lutris:rungame/{slug}"]
Games are matched by their Lutris slug.
Box art is automatically loaded from Lutris's coverart/ directory when available.
The default database path is ~/.local/share/lutris/pga.db.
You can override it with the pga_db option to point at a custom database location.
Heroic scanner — finds all installed Heroic Games Launcher games (Epic, GOG, Amazon and manually added games):
[[application_scanner]]
type = "heroic"
command = ["heroic", "--no-gui", "heroic://launch?appName={app_name}&runner={runner}"]
If you installed Heroic from Flathub, launch it through Flatpak instead:
[[application_scanner]]
type = "heroic"
command = [
"dbus-run-session", "--",
"flatpak", "run", "com.heroicgameslauncher.hgl",
"--no-gui", "heroic://launch?appName={app_name}&runner={runner}",
]
The dbus-run-session prefix keeps the game inside Moonshine's compositor instead of on your desktop.
See TIPS.md for why Flatpak needs it.
{app_name} is Heroic's internal game id and {runner} is the store it came from (legendary for Epic, gog for GOG, nile for Amazon, sideload for manually added games).
Commands are resolved against Moonshine's own PATH, which under the packaged systemd service is systemd's default rather than your login shell's.
A bare heroic therefore works for packages that install into /usr/bin, but not for an AppImage or anything under ~/.local/bin; use an absolute path in those cases.
Box art is automatically loaded from Heroic's images-cache/ directory for any art Heroic has already downloaded.
The default configuration directory is ~/.config/heroic, falling back to ~/.var/app/com.heroicgameslauncher.hgl/config/heroic when only the Flatpak is installed.
You can override it with the config_dir option.
Bottles scanner — finds games and applications in the Bottles Library tab:
[[application_scanner]]
type = "bottles"
command = ["bottles-cli", "run", "-b", "{bottle}", "--program-id", "{program_id}"]
umu_command = ["bottles-cli", "umu", "run", "--game", "{umu_game}"]
Only entries you added to Bottles' Library ("Add to Library" on a program) are exposed — not every program Bottles discovers. UMU entries appear once Bottles reports them as ready, and Steam shortcuts in the Library are skipped. umu_command is optional: without it, UMU entries are skipped.
Limitation: Bottles launches executables that live outside the bottle (e.g. on a separate game drive) through
wine start, which exits immediately, so Moonshine ends the session shortly after launch. Games installed inside the bottle prefix are unaffected.
{bottle} is the bottle's name, {program_id} the program's internal id, {name} the entry's display name, and {umu_game} the id of a game managed through Bottles' UMU integration.
Commands are resolved against Moonshine's own PATH, so a bare bottles-cli only works for a natively installed Bottles. For Flatpak Bottles, see TIPS.md.
The default data directory is the first of ~/.local/share/bottles and ~/.var/app/com.usebottles.bottles/data/bottles that contains a library.yml — leftover data from an uninstalled native Bottles does not shadow the Flatpak install.
You can override it with the data_dir option.
Box art is automatically loaded from Bottles' grid images when available, falling back to the program's icon.
See TIPS.md for practical recipes and workarounds.
How does this compare to Sunshine?
Can I use Moonshine to stream to two clients simultaneously?
This is currently not a supported feature and not a focus of Moonshine. If you are interested in adding support for this, feel free to open an issue or discuss on Discord.
How do I run the healthcheck?
Run moonshine healthcheck to check GPU capabilities, codec support, and port availability. Pass --config <path> to also check configured ports and GPU preferences.
Moonshine is not designed for use on public networks. The underlying GameStream protocol has limitations that mean traffic is not fully encrypted at the application level.
If you need to stream over the internet, use a VPN such as Tailscale, WireGuard, or ZeroTier.
Do not expose Moonshine ports directly to the internet.
This wouldn't have been possible without the incredible work by the people behind the following projects: