Self-hosted game streaming for Linux.
Stream your PC games to Moonlight clients without wrecking your desktop layout. Polaris combines an isolated compositor runtime, GPU-aware capture, a modern web UI, and clear runtime telemetry so you can see what the host is actually doing.
Quick Start · Install · Compatibility · Known Limitations · Roadmap · Why Polaris · Use with Nova · How It Works · Configuration · Client Apps · Security · Changelog · FAQ
Support: Issues · Discussions
Important
Polaris is a Linux host today. Fedora 42, Fedora 43, and Arch Linux are the most validated direct v1.0.4 release package paths. Bazzite and Ubuntu 24.04 packages exist for testing, but they are extremely experimental, less validated on real hardware, and more prone to breaking across distro, compositor, driver, and GPU combinations. Other Debian-family distros remain source-build oriented for now.
Note
v1.0.4 is the current public Polaris release line. The host, web console, Fedora RPMs, and Arch package are ready for broader testing. The Bazzite rpm-ostree path and Ubuntu DEB are earlier validation paths and should be treated as much more fragile.
fedora_version="$(rpm -E %fedora)"
wget "https://github.com/papi-ux/polaris/releases/latest/download/Polaris-fedora${fedora_version}-x86_64.rpm"
sudo dnf install "./Polaris-fedora${fedora_version}-x86_64.rpm"
sudo polaris --setup-host
polarisOpen https://localhost:47990, create your web UI password, and pair a client.
wget https://github.com/papi-ux/polaris/releases/latest/download/Polaris-arch-x86_64.pkg.tar.zst
sudo pacman -U ./Polaris-arch-x86_64.pkg.tar.zst
sudo polaris --setup-host
polarisfedora_version="$(rpm -E %fedora)"
wget "https://github.com/papi-ux/polaris/releases/latest/download/Polaris-fedora${fedora_version}-x86_64.rpm"
sudo rpm-ostree install "./Polaris-fedora${fedora_version}-x86_64.rpm" labwc wlr-randr
systemctl reboot
# After reboot:
sudo polaris --setup-host
polarisBazzite is Fedora-based but immutable, so Polaris is installed as a layered RPM and requires a reboot before the command is available. This path is extremely experimental and more likely to break than Fedora or Arch because Game Mode, Desktop Mode, rpm-ostree layering, and GPU capture all need separate real-hardware validation. See the Bazzite install guide for caveats, rollback, and validation notes.
wget https://github.com/papi-ux/polaris/releases/latest/download/Polaris-ubuntu24.04-x86_64.deb
sudo apt install ./Polaris-ubuntu24.04-x86_64.deb
sudo polaris --setup-host
polarisThe Ubuntu DEB asset is published with v1.0.3 and later, but it is extremely experimental and more prone to breaking than the Fedora and Arch package paths. See the Ubuntu install guide for package status, source build fallback, and validation notes.
git clone --recursive https://github.com/papi-ux/polaris.git
cd polaris
cmake -B build -DCMAKE_BUILD_TYPE=Release -DPOLARIS_ENABLE_CUDA=ON
cmake --build build -j$(nproc)
sudo cmake --install build
sudo polaris --setup-host
polaris- Open the Polaris web UI at https://localhost:47990.
- Confirm the recommended Linux path:
headless_mode = enabledlinux_use_cage_compositor = truelinux_prefer_gpu_native_capture = enabled
- Pair a client:
- Trusted Pair (TOFU) on a trusted LAN subnet
- QR pairing for Nova
- Manual PIN for standard Moonlight clients
- Start a game from the Polaris library or from Nova.
- Watch the live runtime path in the dashboard to confirm the active capture and encode path.
Tip
If you changed port in ~/.config/polaris/polaris.conf, the web UI is at https://localhost:<port + 1>. If you want background autostart, enable the user service with systemctl --user enable --now polaris.
If you are on Fedora or Arch and just want Polaris running, use the GitHub release package for your distro before considering source builds. Bazzite and Ubuntu packages are available for testers, but they are extremely experimental and more prone to breaking. These package paths install the host binary, web console assets, desktop metadata, and user service file; host integration remains explicit so the installer does not silently change input or KMS permissions.
| Public release asset | Use it for |
|---|---|
Polaris-fedora42-x86_64.rpm |
Fedora 42 x86_64 hosts |
Polaris-fedora43-x86_64.rpm |
Fedora 43 x86_64 hosts |
Polaris-fedora42-x86_64.rpm or Polaris-fedora43-x86_64.rpm via rpm-ostree |
Bazzite x86_64 hosts, extremely experimental |
Polaris-ubuntu24.04-x86_64.deb |
Ubuntu 24.04 x86_64 hosts, extremely experimental |
Polaris-arch-x86_64.pkg.tar.zst |
Arch Linux x86_64 hosts |
fedora_version="$(rpm -E %fedora)"
wget "https://github.com/papi-ux/polaris/releases/latest/download/Polaris-fedora${fedora_version}-x86_64.rpm"
sudo dnf install "./Polaris-fedora${fedora_version}-x86_64.rpm"
sudo polaris --setup-hostwget https://github.com/papi-ux/polaris/releases/latest/download/Polaris-arch-x86_64.pkg.tar.zst
sudo pacman -U ./Polaris-arch-x86_64.pkg.tar.zst
sudo polaris --setup-hostwget https://github.com/papi-ux/polaris/releases/latest/download/Polaris-ubuntu24.04-x86_64.deb
sudo apt install ./Polaris-ubuntu24.04-x86_64.deb
sudo polaris --setup-hostfedora_version="$(rpm -E %fedora)"
wget "https://github.com/papi-ux/polaris/releases/latest/download/Polaris-fedora${fedora_version}-x86_64.rpm"
sudo rpm-ostree install "./Polaris-fedora${fedora_version}-x86_64.rpm" labwc wlr-randr
systemctl reboot
# After reboot:
sudo polaris --setup-hostUse the source build when:
- you are on Debian or another distro without a direct package
- you want a local/custom build
- you are developing Polaris
- you need to regenerate packages yourself
If you are on Arch today, Polaris can be installed from the GitHub release asset, from source, or from a locally generated package built from the current commit.
| Package | Why it matters |
|---|---|
| CMake 3.20+ | Build system |
| Boost 1.80+ | Core libraries |
| OpenSSL | TLS and pairing crypto |
| libevdev | Virtual input handling |
| PipeWire | Audio capture |
| wayland-client | Compositor integration |
| CUDA toolkit | NVENC hardware encoding |
| Node.js 18+ | Web UI build |
| labwc | Isolated stream compositor |
Fedora
Run this from the cloned Polaris checkout so dnf builddep can read the packaged build requirements.
sudo dnf install dnf-plugins-core git
sudo dnf builddep -y packaging/linux/fedora/Polaris.specArch
sudo pacman -S --needed base-devel git cmake ninja appstream appstream-glib \
desktop-file-utils boost boost-libs curl openssl libevdev pipewire wayland \
wayland-protocols libdrm libcap libnotify libayatana-appindicator \
libpulse libva libx11 libxcb libxfixes libxi libxrandr libxtst \
miniupnpc nlohmann-json numactl avahi opus libmfx mesa which nodejs npm \
labwc cudaIf you prefer an installable Arch package over a raw cmake --install, Polaris can generate a local PKGBUILD and build a pkg.tar.zst from the current commit. This is mainly for packagers and local release validation; most users should start with the GitHub release asset.
BUILD_VERSION="$(grep -Pom1 '^project\(Polaris VERSION \K[^ ]+' CMakeLists.txt)"
BRANCH="$(git branch --show-current)"
COMMIT="$(git rev-parse HEAD)"
env BRANCH="$BRANCH" BUILD_VERSION="$BUILD_VERSION" CLONE_URL="file://$PWD" COMMIT="$COMMIT" \
cmake -S . -B arch-pkgbuild -DPOLARIS_CONFIGURE_PKGBUILD=ON -DPOLARIS_CONFIGURE_ONLY=ON
env GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=protocol.file.allow GIT_CONFIG_VALUE_0=always \
bash -lc 'cd arch-pkgbuild && makepkg -si'That local package path builds from the current committed state. The GitHub release asset is the easiest install path; the local package path is still useful when you want to package the exact current checkout.
git clone --recursive https://github.com/papi-ux/polaris.git
cd polaris
cmake -B build -DCMAKE_BUILD_TYPE=Release -DPOLARIS_ENABLE_CUDA=ON
cmake --build build -j$(nproc)
sudo cmake --install build
sudo polaris --setup-hostOptional DRM/KMS setup:
sudo polaris --setup-host --enable-kmsOptional autostart:
systemctl --user enable --now polarisWarning
Only grant cap_sys_admin when you actually need DRM/KMS capture. Polaris works fine without it on the default compositor and portal paths.
| Area | Status | Notes |
|---|---|---|
| Linux host OS | Supported | Polaris is Linux-first today |
| Fedora 42 | Recommended | Official release asset: Polaris-fedora42-x86_64.rpm |
| Fedora 43 | Recommended | Official release asset: Polaris-fedora43-x86_64.rpm |
| Bazzite | Extremely experimental | Use the matching Fedora RPM through rpm-ostree; see Bazzite install guide |
| Ubuntu 24.04 | Extremely experimental | Official release asset: Polaris-ubuntu24.04-x86_64.deb; source build also works, but this path needs more real-hardware validation |
| Arch Linux | Recommended | Official release asset: Polaris-arch-x86_64.pkg.tar.zst; source and local PKGBUILD generation are also supported |
| Debian-family distros | Supported from source | Less turnkey than Fedora right now |
| NVIDIA / NVENC | Best-tested | Main fast path and most validated encoder/runtime combination |
| VAAPI / software encode | Supported | Works, but is less battle-tested than NVENC |
| Nova for Android | Best experience | Full launch contract, watch mode, tuning, and richer live state |
| Standard Moonlight clients | Compatible | Core streaming works without Nova-specific UX |
- Polaris is not a Windows host today. Linux is the supported platform.
- Bazzite support is extremely experimental until Desktop Mode, Game Mode, AMD/NVIDIA, and Steam Deck client flows are validated on real hardware.
- Ubuntu 24.04 DEB packaging is extremely experimental and needs broader real-hardware validation; other Debian-family distros are still source-build oriented.
- Fedora 42, Fedora 43, Ubuntu 24.04, and Arch Linux have direct x86_64 release package assets today.
- NVIDIA/NVENC is the most heavily validated hardware path. Other encode backends work, but they are not equally battle-tested.
- Some UX surfaced in Nova, such as explicit launch recommendations, watch mode polish, and live tuning, depends on the Nova client.
- MangoHud can still be risky on Steam Big Picture and some Steam/Proton launches.
Traditional Linux streaming hosts often treat your real desktop as disposable: mode switches, broken layouts, portal prompts, and post-session cleanup are all your problem.
Polaris takes a different route:
- Desktop-safe streaming: games run in a dedicated compositor instead of hijacking your normal desktop layout
- Runtime transparency: the dashboard shows the real backend, transport, frame residency, and format
- Headless-first Linux path: designed to avoid HDMI dummy plugs, display scripts, and manual compositor surgery
- Practical control surface: live preview, telemetry, quality controls, library management, and pairing in one UI
- Shared viewing: additional clients can watch an active stream without stealing ownership
| Area | What You Get |
|---|---|
| Runtime | Isolated labwc streaming compositor |
| Capture | GPU-native capture when available, clear fallback visibility when not |
| Dashboard | Preview, charts, runtime path, controls, and diagnostics |
| Library | Steam, Lutris, Heroic imports, SteamGridDB art, and Linux Steam launch handling that keeps Gamepad UI inside the isolated stream runtime |
| Pairing | Trusted Pair (TOFU), QR, manual PIN |
| Sessions | Ownership, viewers, watch mode, session state, target-relative quality grading, and client-report aware feedback |
| Optimization | Adaptive bitrate, AI optimizer, confidence/cache state, recovery invalidation, per-game tuning, and live host controls |
Nova is the Polaris-aware Android client and the best way to experience the newer host features.
| Polaris + Nova capability | What it means |
|---|---|
| Launch contract | Polaris tells Nova which launch modes are preferred, recommended, and currently allowed |
| Headless vs Virtual Display | Nova can present both choices directly in the library instead of silently guessing |
| 10-bit SDR | Nova can explicitly request a Main10 stream even on SDR handheld panels when the host supports it |
| Watch Stream | A second device can join as a viewer without taking over the owner session |
| AI recommendations | Nova can distinguish baseline device tuning, live AI, cached AI, recovery tuning, and host-adjusted runtime notes |
| Live tuning | Adaptive Bitrate, AI Optimizer, and MangoHud can be surfaced directly in Nova’s quick menu |
| Session truth | HUD and quick menu can show live server-backed mode, role, shutdown state, and tuning state |
Polaris is built around a dashboard that answers the questions stream hosts usually have to reverse-engineer from logs: what runtime is active, what capture path is in use, whether the GPU-native path survived, and how much headroom remains.
When a stream is active, Polaris shifts from setup to operations: preview, charts, runtime-path telemetry, recording controls, and recommendations are visible in one place.
Game library |
Pairing |
More screens
Configuration |
Troubleshooting |
Polaris launches a dedicated compositor runtime for the stream, captures frames from that runtime instead of your desktop session, then routes those frames into the encoder path best suited to the hardware and current Linux stack.
flowchart TB
subgraph labwc ["labwc (isolated stream compositor)"]
game["Game / Steam / Wine\nXWayland + Vulkan"]
end
subgraph desktop ["Your desktop session"]
apps["Browser, IDE, chat, etc.\nNo display switching"]
end
game -->|"wlr-screencopy\n(DMA-BUF when available)"| encoder
encoder["Capture import -> encoder\nNVENC / VAAPI / software"] -->|"Moonlight protocol\nencrypted + FEC"| client
client["Nova / Moonlight\nAndroid · iOS · PC"]
style labwc fill:#7c73ff15,stroke:#7c73ff,color:#c8d6e5
style desktop fill:#4c526515,stroke:#4c5265,color:#687b81
style encoder fill:#1a1a2e,stroke:#7c73ff,color:#c8d6e5
style client fill:#1a1a2e,stroke:#4ade80,color:#c8d6e5
style game fill:transparent,stroke:none,color:#a8b0b8
style apps fill:transparent,stroke:none,color:#687b81
Linux runtime notes
headless_moderequests an invisiblelabwcruntime.linux_prefer_gpu_native_capture=enabledkeeps the intent to prefer DMA-BUF and GPU-native capture, but Polaris will surface SHM fallback explicitly when the current stack cannot hold the fast path.- Deferred headless encoder capabilities are primed before first launch negotiation so Main10 support is advertised correctly on the first real launch.
- Runtime stats surface the requested mode, effective mode, capture transport, frame residency, and frame format.
- AI recovery stores both latest-session results and rolling trend data, grades sessions against the actual target FPS, and invalidates poor cached recommendations automatically.
- Steam library launches use an isolated Linux Gamepad UI bootstrap/cleanup path so Steam titles stay in-stream instead of bouncing back to the host desktop.
- On Linux, Polaris uses RealtimeKit when available so thread-priority elevation can still succeed even when the user service inherits conservative limits.
Session lifecycle notes
- MangoHud is isolated from the compositor and only re-injected into the game launch path when requested.
- Steam Big Picture and Steam/Proton helper paths are treated conservatively because MangoHud can crash Proton helpers before a usable frame exists.
- Owner and viewer roles are tracked explicitly.
- Watch mode is passive by design and uses the active owner profile instead of silently renegotiating a different stream.
- Deferred headless launches cache encoder capabilities so cold-launch negotiation stays accurate.
Config file: ~/.config/polaris/polaris.conf
# Isolated compositor path
headless_mode = enabled
linux_use_cage_compositor = true
linux_prefer_gpu_native_capture = enabled
# Pairing on your trusted LAN
trusted_subnets = ["10.0.0.0/24"]
# Encoding
encoder = nvenc
# Optional
adaptive_bitrate_enabled = enabled
max_sessions = 2Tip
In headless mode you generally do not need KDE window rules, kscreen-doctor scripts, HDMI dummy plugs, or manual portal juggling. Turn on the isolated compositor path and let Polaris manage the runtime.
AI provider examples
Use the AI tab in the web UI if you want a draft connection test before saving. If you prefer direct config edits, these are the working shapes Polaris expects.
Anthropic / Claude
ai_enabled = enabled
ai_provider = anthropic
ai_model = claude-haiku-4-5-20251001
ai_auth_mode = subscriptionOpenAI
ai_enabled = enabled
ai_provider = openai
ai_model = gpt-5.4-mini
ai_auth_mode = api_key
ai_api_key = sk-proj-...Gemini
ai_enabled = enabled
ai_provider = gemini
ai_model = gemini-2.5-flash
ai_auth_mode = api_key
ai_api_key = YOUR_GEMINI_KEYOllama / LM Studio
ai_enabled = enabled
ai_provider = local
ai_model = gpt-oss
ai_auth_mode = none
ai_base_url = http://127.0.0.1:11434/v1Common options
| Key | Default | Description |
|---|---|---|
headless_mode |
disabled |
Request an invisible labwc runtime |
linux_use_cage_compositor |
false |
Enable the isolated compositor runtime |
linux_prefer_gpu_native_capture |
enabled |
Prefer DMA-BUF and GPU-native capture when the stack supports it |
trusted_subnets |
[] |
CIDR blocks that enable Trusted Pair (TOFU) |
encoder |
nvenc |
Encoder: nvenc, vaapi, software |
ai_enabled |
disabled |
Enable AI-assisted stream optimization |
ai_provider |
anthropic |
AI backend: anthropic, openai, gemini, or local |
ai_model |
provider default | Model identifier for the selected provider |
ai_auth_mode |
provider default | Auth mode: api_key, subscription, or none |
ai_api_key |
- | Provider API key for api_key mode |
ai_base_url |
provider default | Override the provider endpoint for local servers |
adaptive_bitrate_enabled |
disabled |
Enable mid-stream bitrate adjustment |
max_sessions |
2 |
Simultaneous sessions/viewers, 0 means unlimited up to the current hard cap of 8 |
enable_pairing |
enabled |
Accept new client pairing |
enable_discovery |
enabled |
Advertise over mDNS |
stream_audio |
enabled |
Enable audio capture |
steamgriddb_api_key |
- | Fetch cover art for non-Steam games |
The Polaris-aware Android client: Trusted Pair, explicit launch modes, watch mode, live HUD, quick tuning, gyro aim, and handheld-first UI.
The Obtainium shortcut is prefiltered to Nova's public app-nonRoot_game-arm64-v8a-release.apk asset so updates resolve cleanly. The GitHub Store shortcut opens the same public release repo in GitHub Store.
Also compatible with standard Moonlight clients on any platform.
Do I need an NVIDIA GPU?
No, but NVENC is the most heavily tested path today. VAAPI and software encode paths are supported, but current Linux compositor and DMA-BUF work has been tuned most heavily around NVIDIA.
Does Polaris work with Moonlight on iOS, macOS, and PC?
Yes. Polaris speaks the Moonlight protocol. Any Moonlight client can connect. Polaris-specific features such as launch-mode selection, watch mode UX, optimization guidance, and richer session state require Nova on Android.
Does headless mode work on Hyprland, Sway, or GNOME?
The headless labwc runtime creates its own Wayland instance, so it is not tied to one desktop environment. Polaris has been tested most heavily on KDE Plasma Wayland, but the model is not KDE-specific.
How does Trusted Pair work?
Trusted Pair is Polaris’ TOFU flow. If the client is on a configured trusted subnet, Polaris can auto-approve first pairing. You can still use QR or manual PIN pairing if you want a stricter or more traditional flow.
Can Polaris stream 10-bit to an SDR handheld screen?
Yes, if the client explicitly requests a 10-bit path and the active encoder/runtime support Main10. This is especially useful with Nova: enabling HDR in Nova can request a 10-bit SDR stream even when the handheld panel itself is not HDR10-capable.
Can multiple people watch the same stream?
Yes. Set max_sessions above 1. Polaris tracks owner vs viewer roles explicitly, and passive watch mode is designed so a second client can observe without taking over the session. Viewers must match the active owner profile rather than silently creating a different downgraded stream.
My KDE layout gets corrupted after streaming
That failure mode is the reason Polaris exists. Enable headless_mode = enabled and linux_use_cage_compositor = true, and Polaris will stop treating your physical displays as the stream path.
Steam Big Picture shows a black screen or tiny window
First clear Steam’s HTML cache:
rm -rf ~/.local/share/Steam/config/htmlcache/Then avoid MangoHud on Steam Big Picture and Steam/Proton launches. Polaris and Nova now warn more aggressively there because MangoHud can crash helper processes before the session gets a usable frame.
How does the AI optimizer work?
The AI optimizer is optional and disabled by default. When enabled, it sends device specs, app metadata, and recent session history to the provider you configure: Anthropic, OpenAI, Gemini, or a local OpenAI-compatible endpoint such as Ollama or LM Studio. Results are cached locally.
Polaris is built by me and only me, with help from tools like ClaudeCode 4.7, OpenAI Codex 5.5, and local models.
I use them as a sounding board and look for ways to cut a lot of fat from the debugging process. I also use it to compare approaches, draft tests and docs, research the headless-first components, and spot things I might have missed. They do not decide what Polaris is or what ships. I have been around engineering and IT for a while, I'm not a vibe-coder, but as we all know in this industry, the capabilites of these tools definitely have solid pratical use cases for working with them. Regardless, I still am adament and always careful about validation, trust boundaries, and release quality. I review the work, test the pieces I can test, and own the final decisions.
Contributions are welcome, especially focused fixes, docs, translations, packaging improvements, and careful feature work. Polaris is still a small maintainer-led project, so the easiest pull requests to review are the ones that explain the problem clearly and keep the change scoped.
- Fork the repo and branch from
master. - Make your changes and test them locally.
- For web UI changes, run
npm run lint,npm test, andnpm run buildin the repo root. - For browser-facing changes, run
npm run test:e2eagainst a local Polaris instance when possible. - Open a pull request that explains what changed, why it helps, and what you were able to test.
Note
The web UI lives in src_assets/common/assets/web/ and uses Vue 3 with Tailwind CSS v4. The backend lives in src/. CMake builds both together.
Polaris is a fun project I build in my spare time simply because I want more people to make the switch to Linux gaming while making users safer, clearer, and easier to trust. If it becomes part of your setup, that alone makes my day, donations are appreciated but never expected. They help with my actual coffee budget, which coffee obviously keeps the project moving. Bug reports, testing notes, and thoughtful feedback help too.
Polaris is licensed under the GNU General Public License v3.0. See LICENSE for the full text.
Polaris builds on Apollo and Sunshine under GPLv3 lineage, and remains compatible with Moonlight clients.