webstation-broker
Container

Running the container

The linuxserver/webstation:romm image that ships the broker, how to start it, and what it needs from the host.

The broker is not run on its own. It ships inside linuxserver/docker-webstation on the romm branch, published as lscr.io/linuxserver/webstation:romm. The image is a selkies desktop with every supported emulator installed, nginx in front, and the broker registered as an s6 service that starts once the selkies control plane is up.

The image only runs in Wayland mode and is meant to be run with a GPU. Software rendering works for the desktop but not for most emulators.

docker-compose

---
services:
  webstation:
    image: lscr.io/linuxserver/webstation:romm
    container_name: webstation
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - SUBFOLDER=/streaming/
      - BROKER_SECRET=change-me
    volumes:
      - /path/to/config:/config
      - /path/to/roms:/romm
    ports:
      - 3000:3000
      - 3001:3001
    shm_size: "1gb"
    restart: unless-stopped

docker cli

docker run -d \
  --name=webstation \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Etc/UTC \
  -e SUBFOLDER=/streaming/ \
  -e BROKER_SECRET=change-me \
  -p 3000:3000 \
  -p 3001:3001 \
  -v /path/to/config:/config \
  -v /path/to/roms:/romm \
  --shm-size="1gb" \
  --restart unless-stopped \
  lscr.io/linuxserver/webstation:romm

Parameters

ParameterFunction
-p 3000HTTP. Must be reverse proxied; see Reverse proxy.
-p 3001HTTPS with a self-signed certificate, for direct access while testing.
-v /configThe user's home directory in the container: emulator configs, BIOS and firmware, save data, the broker's pid record and export directory.
-v /rommThe ROM library, mounted read-only if you like. Activate rejects any rom path outside ROM_ROOT (default /romm), and RomM's library_path for the container must point here.
--shm-size=1gbRecommended for all desktop images.
-e PUID / -e PGIDThe uid and gid the desktop, the emulators and the broker run as. Match them to the owner of the mounted directories.
-e SUBFOLDERURL prefix the whole app is served under, default /streaming/. Must equal the path the reverse proxy mounts the container at, trailing slash included.
-e BROKER_SECRETShared secret RomM sends as X-Broker-Secret on the lifecycle endpoints. Unset disables the check.
-e BROKER_DEV_MODEtrue runs the broker from source mounted at /broker; see Dev mode.

Every other broker and emulator variable is optional and listed under Configuration.

GPU

Mount the GPU into the container and the base image configures it for both rendering and encoding on its own; no extra variables are needed. The full guide, including multi-GPU pinning, hardware encoders and debugging, is the selkies GPU acceleration page. The minimal additions to the examples above:

Open source drivers only need the render node passed through.

docker-compose
    devices:
      - /dev/dri:/dev/dri
docker cli
  --device /dev/dri \

On a multi-GPU host, pin the node the container should use:

    environment:
      - DRINODE=/dev/dri/renderD129
      - DRI_NODE=/dev/dri/renderD129

Several launchers pin a renderer that is known to work on the integrated AMD parts the image is tested on (DOLPHIN_VIDEO_BACKEND, XEMU_RENDERER); change them if your driver prefers Vulkan.

First run

The container boots to the webstation desktop. Before launching games through RomM, every emulator you plan to use needs its BIOS, firmware or keys and a quick controller check. Launch a desktop session from RomM (or open https://yourhost:3001/streaming/ directly) and follow Emulator setup.

Wiring it into RomM

RomM talks to the container over REST and embeds its room in an iframe. In RomM's config.yml:

streaming:
  containers:
    - platform: ps2
      host: /streaming
      broker_host: http://10.0.1.56:3000
      subfolder: /streaming
      broker_secret: "change-me"
      protocol: webstation
      emulator: pcsx2
      library_path: /romm
      label: WEBSTATION

host is where the browser goes, broker_host is where RomM's backend goes server to server, and subfolder is the container's SUBFOLDER. The full story, including why host is a path, is in Reverse proxy.

On this page