linux vr setup

#author_luna #vr #linux #living_article

initally written %at=2025-02-07T14:29:30.123Z
current version %at=2025-09-25T01:24:25.499Z

world in picture: Umbra by Blue Cat

assuming:

if flatpak:

flatpak install flathub io.github.wivrn.wivrn
flatpak run io.github.wivrn.wivrn

if envision:

get wlxoverlay-s while at it

get xrgears while at it so you can test your setup. there's no specific appimage or whatever so you'll need to build it. link is for void-packages (i use void linux, you may be able to find it on AUR if arch)

then pair the headset (get wivrn app from meta quest store) to the server, and connect to it. you aren't dropped to vr until there's a vr client, so open another terminal and ./wlxoverlay-s-whatever-version-u-got.appimage

i recommend looking over wlxoverlay-s' readme to see controller mappings. i also recommend configuring it such that show/hide follows your HMD center (xsoverlay-style behavior, i know)

audio #

#!/bin/sh
set -eux
pactl set-default-sink wivrn.sink
pactl set-default-source wivrn.source

full body tracking #

currently https://lvra.gitlab.io/docs/slimevr/ gives 3 options for full body tracking:

vrchat osc with slimevr sucks if your trackers are using cheap IMUs like mine (my bad experience with ozivr), since osc does not give HMD position, slimevr has to assume HMD is always upright, which requires you to always stay upright on any reset (yaw, full, mounting), which i have to do every 10 minutes or so. makes for good exercise i guess, but for me it's unusable.

relevant prs:

no need to build slimevr! appimage exists for the currently WIP version that contains solarxr support: https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.14.0-rc1. you may need tricks for nvidia though:

env WEBKIT_DISABLE_DMABUF_RENDERER=1 ./SlimeVR-amd64.appimage

video games #

IMPORTANT the LVRA DB is now a thing: https://respuit.github.io/VRDB/, prefer going to it to find out compatibility information for your preffered vr apps.

generally, copy the environment variables from wivrn into the steam game's launch options and it'll mostly likely work (test results as of %at=2025-02-07T14:09:18.224Z):


random notes #

avahi on void linux #

need avahi on void

need dbus fixed on void

2025-01-25T01:04:55.77879 daemon.warn: Jan 24 22:04:55 avahi-daemon[21245]: WARNING: No NSS support for mDNS detected, consider installing nss-mdns!
2025-01-25T01:04:55.77935 daemon.err: Jan 24 22:04:55 avahi-daemon[21245]: dbus_bus_request_name(): Connection ":1.12091" is not allowed to own the service "org.freedesktop.Avahi" due to security policies in the configuration file
2025-01-25T01:04:55.77939 daemon.warn: Jan 24 22:04:55 avahi-daemon[21245]: WARNING: Failed to contact D-Bus daemon.

need to restart dbus methinks. avahi package installs avahi.conf into dbus settings so it has perms
NOTE: need to restart entire system after restarting dbus system bus. everything explodes otherwise
https://stackoverflow.com/questions/4560877/dbus-bus-request-name-connections-are-not-allowed-to-own-the-service

wivrn can't start due to unknown error (999) in nvenc encoder #

following https://github.com/obsproject/obs-studio/issues/11381, i did this:

also https://github.com/tensorflow/tensorflow/issues/53341#issuecomment-1166532019

desktop mode #

while vrchat mainly targets windows, and its status is steam deck verified, that doesn't mean that you're guaranteed to work in all scenarios. there's various things specific to the VR setup (explained throughout this article), but there are some tips for desktop mode as well (which also apply to VR!)

main one being to use a custom Proton version for vrc. due to shenanigans with windows media apis, the way to map these APIs is not straightforward back to linux (especially when most vrchat worlds depend on AVPro, which is a proprietary component). we heavily recommend the proton-ge-rtsp patches by SpookySkeletons, most specifically GE-Proton9-20-rtsp15:

wget 'https://github.com/SpookySkeletons/proton-ge-rtsp/releases/download/GE-Proton9-20-rtsp15-1/GE-Proton9-20-rtsp15.tar.gz'
tar -xvf ./GE-Proton9-20-rtsp15.tar.gz -C ~/.steam/steam/compatibilitytools.d/

# restart steam!!!! then use it as the compat tool on vrchat

this seems to be the version that works the MOST in terms of youtube playback. however, there is one caveat. due to even more shenanigans with how youtube has been doing anti-bot and anti-adblock efforts, i have this small flowchart in terms of recommendations:

NOTE: if you want to experiment, i am in the process of validating this version: GE-Proton10-15-rtsp18 with VRCVideoCacher, if things remain stable i'll promote them as my recommendations

face tracking #

THIS SECTION IS VERY WIP. the face tracking system is not finished until i can use it consistently, that's not the case yet. this is already a living article after all.

I DO NOT GUARANTEE THIS GUIDE TO WORK. on any system, for any user. no warranty is provided by me. this is a reference for my linux vr setup

firstly thank you very much to dfgHiatus and frozenreflex for helping me guide into a functional setup, answering my questions and in general working on the software powering all of this!

i've preordered Project Babble's official tracker and have been working on getting things running ON VOID LINUX (this means other distros MAY JUST BE EASIER LMAO!!!), here's how my setup went, in the hopes that others that don't have as many builtin components can start "from the ground up":

  1. setup the tracker firmware connect to wifi
    1. you may need udev rules so that the tracker is detected via usb
      1. https://docs.platformio.org/en/stable/core/installation/udev-rules.html
    2. can only continue if plugging the tracker to the computer gives you /dev/ttyACM0 and dmesg output about the device
    3. currently, baballonia does not support setting up the firmware via usb on linux by itself, so don't setup it yet
    4. you'll have to use a separate tool as a workaround that talks through the serial openiris protocol to make the tracker join wifi:
    5. https://github.com/SummerSigh/OpenIris-ESPIDF/tree/mutimodal, cd tools, get a python venv (i am not providing python support: my python packaging patterns)
    6. run openiris_setup.py, it should detect the tracker and you can use its TUI to put wifi credentials and make it join the network. after it joins wifi you can ping it to validate it works
    7. to get mdns working:
      1. assert avahi can resolve the mdns of the tracker: avahi-resolve --name openiristracker.local should return the LAN IP for it
      2. get nss-mdns installed (depends on avahi, which should be setup already in this setup! avahi on void linux is a subsection of this very article!)
      3. open http://openiristracker.local/ on firefox, it takes some seconds but afterwards you'll get an mjpeg stream and you SHOULD be able to see yourself, etc
  2. from-source build of baballonia
    1. why?
      1. baballonia does ship appimages on its CI, but currently the appimages are broken. due to issues with velopack flattening the internal dll structure it leads to startup failures
      2. you can absolutely do --appimage-extract and mess around the appimage root so you can add the missing paths and restore a functional structure, but that path is absurdly hacky and not super reproducible. source builds should generally work better
    2. dependencies:
      1. gstreamer
      2. dotnet8 sdk, i have to do it on bespoke paths because of custom sdk packages i made. i am NOT good at csharp, and am not going to get an ide just for an end-user build
    3. after cloning the repo, it's mainly a process of building things in order as talked about in the README of baballonia, example:
      1. cd src/Baballonia.OpenCVCapture
      2. env "PATH=/opt/dotnet8/target DOTNET_ROOT=/opt/dotnet8/target" /opt/dotnet8/target publish
      3. repeat for 7 other modules
    4. keep going all the way to Baballonia.Desktop, build that too
    5. get model files (currently it depends on those files existing in CWD)
      1. cp ./src/Baballonia/faceModel.onnx ./src/Baballonia.Desktop
      2. cp ./src/Baballonia/eyeModel.onnx ./src/Baballonia.Desktop
    6. start baballonia cd ./src/Baballonia.Desktop && env .. path/to/dotnet run
    7. set face tracker address of http://openiristracker.local
    8. IMPORTANT on linux, OpenCVCapture basically does not work, prefer IpCameraCapture for much better stability (hopefully ipcamera can be set as default on linux)
    9. starting the tracker should connect to the stream and show it inside Baballonia
  3. VRCFaceTracking.Avalonia
    1. VRCFaceTracking is a primarily Windows-only application. VRCFT is a bridge between various face tracking hardware/software and VRChat itself
      1. why not wine?
        1. breaks. you can make it start but it'll attempt to get VRC OSC files from inside the wineprefix and simply explode
    2. thankfully, VRCFT.Avalonia is a cross-platform port of it by dfgHiatus
    3. this one is much more standard. version v1.1.1.0 contains a ready-to-use appimage. you should be able to start it, install the babble module, and enjoy
  4. workflow to link everything together
    1. START IN A SPECIFIC ORDER
      1. VRChat
        1. OSC mode on VRChat must be enabled already, see its docs:
        2. https://docs.vrchat.com/docs/osc-overview
      2. VRCFT.Avalonia
        1. it should be able to detect VRC running and get a hold of the current avatar you're using already (even if it doesn't support face tracking), would prove the two are communicating
      3. Baballonia
        1. Baballonia contacts with VRCFT.Avalonia via ports 8888 (send) and 8889 (receive), not 9000/9001 (an unfortunate catch that I misconfigured due to trying to fix other problems, like the startup order, thank you dfgHiatus for catching that)
    2. swap to an avatar with face tracking support, the babble documentation goes on more detail: https://docs.babble.diy/docs/software/integrations/vrc

changelog #

%at=2025-09-25T01:26:53.948Z

%at=2025-09-20T02:01:54.044Z

%at=2025-06-08T20:44:38.417Z

%at=2025-04-09T22:29:47.012Z