summaryrefslogtreecommitdiff
path: root/posts/2025-06-20-vr-plus-nixos-plus-nvidia.md
blob: 88fd45c6b2a34dcf3ed9effef364b1372704493f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
---
title: VR + NixOS + Nvidia
---

## ⚠️ Note

This post is quite outdated now.
The 'prerequisites' section is still quite accurate, as you still need the proprietary drivers, however setting WiVRn
up is significantly easier. I recommend looking at the [Linux VR Adventures Wiki](https://lvra.gitlab.io/docs/distros/nixos/)
for a much better guide.

## Introduction

For the longest time, getting VR working nicely with Linux (and especially NixOS) was a monumental task.
Nowadays however, it is easier than ever: only requiring a handful of lines of Nix!

## Prerequisites

In this blog post, I will be focusing on getting VR working with Steam games, using an Oculus Quest 2 headset.
Ensure you have the proprietary Nvidia drivers installed, as this will most likely not work without them.
You will also need Home Manager setup, as we will be utilising that to get Steam games working.

```nix
# Generic drivers, good to have
hardware.graphics = {
  enable = true;
  enable32Bit = true;
};

# Nvidia specific
hardware.nvidia = {
  modesetting.enable = true;
  open = true;
};

services.xserver.videoDrivers = ["nvidia"];
```

## Installing WiVRn

As I am using a Quest 2, I am going to use an application called WiVRn, which will allow me to stream both wired _or_ wirelessly.
If you are using a tethered headset such as a HTC Vive or Valve Index, I can recommend you look into [Monado](https://gitlab.freedesktop.org/monado/monado).
WiVRn is actually based on Monado, so gertting it up and running should be fairly similar.
All we need to get WiVRn installed is put the following in our configuration!

```nix
/* configuration.nix */
services.wivrn = {
  enable = true;
  openFirewall = true; # Required for wireless streaming
  defaultRuntime = true;
};
```

Although we don't _necessarily_ need anything else now, installing some quality-of-life tools will definitely benefit us.

```nix
/* configuration.nix */
environment.systemPackages = with pkgs; [
  wlx-overlay-s # In-VR overlay
  android-tools # Allows for wired WiVRn
];
```

## Getting Steam games working

If all we want to do is play OpenXR games, we're set!
Most, if not all, steam games use OpenVR though, so we will need a compatibility layer: OpenComposite.
We can tell Steam to use OpenComposite and WiVRn for games by writing a few configuration files.
Because these files live in our home directory, we need to use Home Manager.
In home.nix, or wherever you have your home configuration:

```nix
/* home.nix */
xdg.configFile."openxr/1/active_runtime.json".source =
  "${osConfig.services.wivrn.package}/share/openxr/1/openxr_wivrn.json";

xdg.configFile."openvr/openvrpaths.vrpath".text = ''
   {
    "config" :
    [
      "${config.xdg.dataHome}/Steam/config"
    ],
    "external_drivers" : null,
    "jsonid" : "vrpathreg",
    "log" :
    [
      "${config.xdg.dataHome}/Steam/logs"
    ],
    "runtime" :
    [
      "${pkgs.opencomposite}/lib/opencomposite"
    ],
    "version" : 1
  }
'';
```

We are using `osConfig` in this case, as to use the same package we use when enabling WiVRn, meaning that if we changed `services.wivrn.package` in the future, it will use that package instead of the generic one from nixpkgs.

Going back to our main configuration, we now need to tell the game to actually use these settings.

We can do this by setting our game launch options to...
```sh
PRESSURE_VESSEL_FILESYSTEMS_RW=$XDG_RUNTIME_DIR/wivrn/comp_ipc %command%
```
...however, that isn't very "Nix", is it?
To do this for _every_ game, we can override our steam package to include this environment variable.

```nix
/* configuration.nix */
programs.steam.package = lib.mkDefault (
  pkgs.steam.override (prev: {
    extraEnv =
    {
      PRESSURE_VESSEL_FILESYSTEMS_RW = "$XDG_RUNTIME_DIR/wivrn/comp_ipc";
    }
    // (prev.extraEnv or {});
  })
);
```

Don't worry about your flatscreen games: they should just ignore this setting!

## Done!

We should now just be able to open the "WiVRn server" GUI application, and start gaming!
You can read the [official WiVRn documentation](https://github.com/WiVRn/WiVRn?tab=readme-ov-file#running-1) for platform independent help on getting it up and running now, as the Nix specific stuff has now been sorted.