Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nestrilabs/nestri/llms.txt

Use this file to discover all available pages before exploring further.

Nestri runner containers bundle everything needed to stream a game: the nestri-server streaming binary, a full GStreamer pipeline with hardware encoding plugins, Gamescope compositor, PipeWire audio, and a game launcher. Each container starts nestri-server, which creates a Wayland display, captures it via GStreamer, and streams it to a connected browser over WebRTC.

Container image hierarchy

Runner images are built in layers. Each layer adds only what its stage needs:
1

runner-base

Built from CachyOS (docker.io/cachyos/cachyos:latest). Installs the minimal runtime dependencies shared by all stages: gstreamer, gst-plugins-base, curl, libevdev, and a few system libraries.
2

runner-common

Adds the full GPU and streaming stack on top of runner-base: Vulkan drivers for NVIDIA, AMD, and Intel; Mesa; VA-API plugins (gst-plugin-va, gst-plugin-qsv); WebRTC plugins (gst-plugin-rswebrtc, gst-plugin-webrtchttp); Gamescope compositor; PipeWire and WirePlumber; MangoHUD; and the nestri-server binary plus the vimputti-manager input shim. It also creates the nestri user (UID/GID 1000) that runs the game process.
3

Flavor image (steam / heroic / minecraft)

Adds a single game launcher on top of runner-common and sets NESTRI_LAUNCH_CMD to the correct launch command for that launcher. The entrypoint is supervisord, which manages the full service tree.
runner-base  →  runner-common  →  steam-runner
                               →  heroic-runner
                               →  minecraft-runner

Available flavors

ImageLauncherNESTRI_LAUNCH_CMD
ghcr.io/nestrilabs/nestri/runner:nightly-steam-v3Steamsteam -tenfoot -cef-force-gpu
ghcr.io/nestrilabs/nestri/runner:nightly-heroic-v3Heroic Games Launcherheroic
ghcr.io/nestrilabs/nestri/runner:nightly-minecraft-v3Minecraft Launcherminecraft-launcher

Environment variables

The nestri-server binary (written in Rust, defined in packages/server/src/args.rs) reads all configuration from environment variables.

Required

env.RELAY_URL
string
required
WebSocket URL of the relay server this runner connects to. Example: ws://relay.example.com:8088 or wss://relay.example.com when behind a TLS proxy.
env.NESTRI_ROOM
string
required
Room identifier for this streaming session. The browser client uses the same value to locate the stream. Must be unique per active session on a given relay.

Display and encoding

env.RESOLUTION
string
default:"1280x720"
Stream resolution in WIDTHxHEIGHT format. The compositor (Gamescope) and nestri-server both read this value. Example: 1920x1080, 2560x1440.
env.FRAMERATE
number
default:"60"
Stream framerate in frames per second. Accepted range is 5–240. The default Gamescope launch command passes this as -r ${FRAMERATE}.
env.VIDEO_CODEC
string
default:"h264"
Preferred video codec. Accepted values: h264, h265, av1. The server picks the best available hardware encoder for the selected codec.
env.VIDEO_BITRATE
number
default:"6000"
Target video bitrate in kbps. Used in CBR (constant bitrate) mode by default.
env.VIDEO_BITRATE_MAX
number
default:"8000"
Maximum video bitrate in kbps. Applied as a ceiling in CBR and VBR modes.
env.VIDEO_ENCODER_TYPE
string
default:"hardware"
Encoding backend. hardware uses VA-API, NVENC, or QSV depending on the detected GPU. software falls back to CPU encoding (not suitable for real-time gaming).
env.VIDEO_RATE_CONTROL
string
default:"cbr"
Rate control method: cbr (constant bitrate) or vbr (variable bitrate).
env.VIDEO_LATENCY_CONTROL
string
default:"lowest-latency"
Encoder latency preset. lowest-latency minimizes buffering at the cost of some quality.
env.VIDEO_BIT_DEPTH
number
default:"8"
Video bit depth. 8 or 10. 10-bit is only effective with DMA-BUF capture and a non-H264 codec.
env.KEYFRAME_DIST_SECS
number
default:"1"
Distance between keyframes in seconds. Lower values allow faster seeking and recovery from packet loss but increase bandwidth usage.

Audio

env.AUDIO_CODEC
string
default:"opus"
Audio codec. opus is the default and best choice for WebRTC.
env.AUDIO_BITRATE
number
default:"128"
Target audio bitrate in kbps.
env.AUDIO_BITRATE_MAX
number
default:"192"
Maximum audio bitrate in kbps.
env.AUDIO_CAPTURE_METHOD
string
default:"pipewire"
Audio capture backend. pipewire is the default. The container runs WirePlumber and PipeWire services via supervisord.

GPU selection

env.GPU_VENDOR
string
Select the GPU by vendor name (e.g., nvidia, amd, intel). Leave unset to use the first detected GPU.
env.GPU_NAME
string
Select the GPU by name substring match.
env.GPU_INDEX
number
Select the GPU by index when multiple GPUs are present.
env.GPU_CARD_PATH
string
Force a specific GPU by /dev/dri/card* or /dev/dri/renderD* path. Cannot be used together with GPU_VENDOR, GPU_NAME, or GPU_INDEX.

Launcher

env.NESTRI_LAUNCH_CMD
string
The command run inside Gamescope to launch the game or launcher. Set by the flavor image. Override this to launch a different application. See custom launcher below.

GPU passthrough

Runner containers need access to the host GPU for hardware encoding. The method differs by vendor:
Use --gpus all (requires the NVIDIA Container Toolkit).
docker run -d \
  --name nestri-steam \
  --gpus all \
  -e RELAY_URL="wss://relay.example.com" \
  -e NESTRI_ROOM="my-room" \
  -e RESOLUTION="1920x1080" \
  -e FRAMERATE="60" \
  -e VIDEO_CODEC="h264" \
  -e VIDEO_BITRATE="6000" \
  --restart unless-stopped \
  ghcr.io/nestrilabs/nestri/runner:nightly-steam-v3
The container’s entrypoint script (packages/scripts/entrypoint.sh) detects the host NVIDIA driver version from /proc/driver/nvidia/version or nvidia-smi, downloads the matching installer, and installs the userspace driver components inside the container at startup.
Without GPU access, nestri-server falls back to software encoding (VIDEO_ENCODER_TYPE=software). CPU encoding is not suitable for real-time gaming — you will see very high CPU usage and high latency.

Launcher examples

The Steam runner installs Steam from the Arch Linux package repositories and sets NESTRI_LAUNCH_CMD="steam -tenfoot -cef-force-gpu". This opens Steam in Big Picture mode with GPU-accelerated CEF rendering.
docker run -d \
  --name nestri-steam \
  --gpus all \
  -e RELAY_URL="wss://relay.example.com" \
  -e NESTRI_ROOM="steam-session-01" \
  -e RESOLUTION="1920x1080" \
  -e FRAMERATE="60" \
  -e VIDEO_CODEC="h264" \
  -e VIDEO_BITRATE="8000" \
  -v nestri-steam-home:/home/nestri \
  --restart unless-stopped \
  ghcr.io/nestrilabs/nestri/runner:nightly-steam-v3
Mount a volume at /home/nestri to persist your Steam library and login credentials across restarts.

Persistent storage

Mount a named volume at /home/nestri to preserve game library files, saves, and launcher configuration across container restarts:
-v nestri-steam-home:/home/nestri
Without this, every container restart starts from a clean home directory and Steam/Heroic will need to re-download games.

SSH access

The runner supports optional SSH access for debugging. Set SSH_ENABLE_PORT to a port number and SSH_ALLOWED_KEY to a public key to enable it:
-e SSH_ENABLE_PORT=2222 \
-e SSH_ALLOWED_KEY="ssh-ed25519 AAAA..." \
-p 2222:2222 \
The entrypoint configures sshd with public-key authentication only (no passwords) and starts the SSH daemon before launching the game session.

Build docs developers (and LLMs) love