wivrn: 25.6.1 -> 25.8 (#432804)

This commit is contained in:
tomberek
2025-08-20 11:56:56 -04:00
committed by GitHub
2 changed files with 100 additions and 94 deletions
+83 -90
View File
@@ -10,12 +10,18 @@ let
mkEnableOption
mkPackageOption
mkOption
literalExpression
hasAttr
toList
length
head
tail
concatStringsSep
optionalString
optionalAttrs
isDerivation
recursiveUpdate
getExe
literalExpression
types
maintainers
;
@@ -28,38 +34,27 @@ let
# Since the json config attribute type "configFormat.type" doesn't allow specifying types for
# individual attributes, we have to type check manually.
# The application option must be either a package or a list with package as the first element.
# The application option should be a list with package as the first element, though a single package is also valid.
# Note that this module depends on the package containing the meta.mainProgram attribute.
# Checking if an application is provided
applicationAttrExists = builtins.hasAttr "application" cfg.config.json;
applicationListNotEmpty = (
if builtins.isList cfg.config.json.application then
(builtins.length cfg.config.json.application) != 0
else
true
);
# Check if an application is provided
applicationAttrExists = hasAttr "application" cfg.config.json;
applicationList = toList cfg.config.json.application;
applicationListNotEmpty = length applicationList != 0;
applicationCheck = applicationAttrExists && applicationListNotEmpty;
# Manage packages and their exe paths
applicationAttr = (
if builtins.isList cfg.config.json.application then
builtins.head cfg.config.json.application
else
cfg.config.json.application
);
applicationAttr = head applicationList;
applicationPackage = mkIf applicationCheck applicationAttr;
applicationPackageExe = getExe applicationAttr;
serverPackageExe = getExe cfg.package;
# Managing strings
applicationStrings = builtins.tail cfg.config.json.application;
applicationConcat = (
if builtins.isList cfg.config.json.application then
builtins.concatStringsSep " " ([ applicationPackageExe ] ++ applicationStrings)
else
applicationPackageExe
serverPackageExe = (
if cfg.highPriority then "${config.security.wrapperDir}/wivrn-server" else getExe cfg.package
);
# Manage strings
applicationStrings = tail applicationList;
applicationConcat = concatStringsSep " " ([ applicationPackageExe ] ++ applicationStrings);
# Manage config file
applicationUpdate = recursiveUpdate cfg.config.json (
optionalAttrs applicationCheck { application = applicationConcat; }
@@ -68,7 +63,7 @@ let
enabledConfig = optionalString cfg.config.enable "-f ${configFile}";
# Manage server executables and flags
serverExec = builtins.concatStringsSep " " (
serverExec = concatStringsSep " " (
[
serverPackageExe
"--systemd"
@@ -76,14 +71,6 @@ let
]
++ cfg.extraServerFlags
);
applicationExec = builtins.concatStringsSep " " (
[
serverPackageExe
"--application"
enabledConfig
]
++ cfg.extraApplicationFlags
);
in
{
options = {
@@ -95,7 +82,7 @@ in
openFirewall = mkEnableOption "the default ports in the firewall for the WiVRn server";
defaultRuntime = mkEnableOption ''
WiVRn Monado as the default OpenXR runtime on the system.
WiVRn as the default OpenXR runtime on the system.
The config can be found at `/etc/xdg/openxr/1/active_runtime.json`.
Note that applications can bypass this option by setting an active
@@ -104,34 +91,29 @@ in
autoStart = mkEnableOption "starting the service by default";
highPriority = mkEnableOption "high priority capability for asynchronous reprojection";
monadoEnvironment = mkOption {
type = types.attrs;
description = "Environment variables to be passed to the Monado environment.";
default = {
XRT_COMPOSITOR_LOG = "debug";
XRT_PRINT_OPTIONS = "on";
IPC_EXIT_ON_DISCONNECT = "off";
};
default = { };
};
extraServerFlags = mkOption {
type = types.listOf types.str;
description = "Flags to add to the wivrn service.";
default = [ ];
example = ''[ "--no-publish-service" ]'';
example = literalExpression ''[ "--no-publish-service" ]'';
};
extraApplicationFlags = mkOption {
type = types.listOf types.str;
description = "Flags to add to the wivrn-application service. This is NOT the WiVRn startup application.";
default = [ ];
};
steam = {
importOXRRuntimes = mkEnableOption ''
Sets `PRESSURE_VESSEL_IMPORT_OPENXR_1_RUNTIMES` system-wide to allow Steam to automatically discover the WiVRn server.
extraPackages = mkOption {
type = types.listOf types.package;
description = "Packages to add to the wivrn-application service $PATH.";
default = [ ];
example = literalExpression "[ pkgs.bash pkgs.procps ]";
Note that you may have to logout for this variable to be visible
'';
package = mkPackageOption pkgs "steam" { };
};
config = {
@@ -139,12 +121,12 @@ in
json = mkOption {
type = configFormat.type;
description = ''
Configuration for WiVRn. The attributes are serialized to JSON in config.json. If a config or certain attributes are not provided, the server will default to stock values.
Configuration for WiVRn. The attributes are serialized to JSON in config.json. The server will fallback to default values for any missing attributes.
Note that the application option must be either a package or a
list with package as the first element.
Like upstream, the application option is a list including the application and it's flags. In the case of the NixOS module however, the first element of the list must be a package. The module will assert otherwise.
The application can be set to a single package because it gets passed to lib.toList, though this will not allow for flags to be passed.
See <https://github.com/WiVRn/WiVRn/blob/master/docs/configuration.md>
See https://github.com/WiVRn/WiVRn/blob/master/docs/configuration.md
'';
default = { };
example = literalExpression ''
@@ -177,51 +159,59 @@ in
}
];
security.wrappers."wivrn-server" = mkIf cfg.highPriority {
setuid = false;
owner = "root";
group = "root";
capabilities = "cap_sys_nice+eip";
source = getExe cfg.package;
};
systemd.user = {
services = {
# The WiVRn server runs in a hardened service and starts the application in a different service
wivrn = {
description = "WiVRn XR runtime service";
environment = {
environment = recursiveUpdate {
# Default options
# https://gitlab.freedesktop.org/monado/monado/-/blob/598080453545c6bf313829e5780ffb7dde9b79dc/src/xrt/targets/service/monado.in.service#L12
XRT_COMPOSITOR_LOG = "debug";
XRT_PRINT_OPTIONS = "on";
IPC_EXIT_ON_DISCONNECT = "off";
}
// cfg.monadoEnvironment;
serviceConfig = {
ExecStart = serverExec;
# Hardening options
CapabilityBoundingSet = [ "CAP_SYS_NICE" ];
AmbientCapabilities = [ "CAP_SYS_NICE" ];
LockPersonality = true;
NoNewPrivileges = true;
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictNamespaces = true;
RestrictSUIDSGID = true;
};
PRESSURE_VESSEL_IMPORT_OPENXR_1_RUNTIMES = mkIf cfg.steam.importOXRRuntimes "1";
} cfg.monadoEnvironment;
serviceConfig = (
if cfg.highPriority then
{
ExecStart = serverExec;
}
# Hardening options break high-priority
else
{
ExecStart = serverExec;
# Hardening options
CapabilityBoundingSet = [ "CAP_SYS_NICE" ];
AmbientCapabilities = [ "CAP_SYS_NICE" ];
LockPersonality = true;
NoNewPrivileges = true;
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictNamespaces = true;
RestrictSUIDSGID = true;
}
);
path = [ cfg.steam.package ];
wantedBy = mkIf cfg.autoStart [ "default.target" ];
restartTriggers = [ cfg.package ];
};
wivrn-application = mkIf applicationCheck {
description = "WiVRn application service";
requires = [ "wivrn.service" ];
serviceConfig = {
ExecStart = applicationExec;
Restart = "on-failure";
RestartSec = 0;
PrivateTmp = true;
};
path = [ applicationPackage ] ++ cfg.extraPackages;
restartTriggers = [
cfg.package
cfg.steam.package
];
};
};
};
@@ -247,6 +237,9 @@ in
cfg.package
applicationPackage
];
sessionVariables = mkIf cfg.steam.importOXRRuntimes {
PRESSURE_VESSEL_IMPORT_OPENXR_1_RUNTIMES = "1";
};
pathsToLink = [ "/share/openxr" ];
etc."xdg/openxr/1/active_runtime.json" = mkIf cfg.defaultRuntime {
source = "${cfg.package}/share/openxr/1/openxr_wivrn.json";
+17 -4
View File
@@ -4,6 +4,7 @@
stdenv,
fetchFromGitHub,
fetchFromGitLab,
fetchpatch,
applyPatches,
autoAddDriverRunpath,
avahi,
@@ -21,6 +22,7 @@
glslang,
harfbuzz,
kdePackages,
libarchive,
libdrm,
libGL,
libnotify,
@@ -51,13 +53,13 @@
}:
stdenv.mkDerivation (finalAttrs: {
pname = "wivrn";
version = "25.6.1";
version = "25.8";
src = fetchFromGitHub {
owner = "wivrn";
repo = "wivrn";
rev = "v${finalAttrs.version}";
hash = "sha256-DqgayLXI+RPIb8tLzJoHi+Z12px4pdzU50C0UBSa2u4=";
hash = "sha256-x9nZyLk0A9eiZ9V700lc4To1cVJ875ZYR0GeqQ7qNpg=";
};
monado = applyPatches {
@@ -65,8 +67,8 @@ stdenv.mkDerivation (finalAttrs: {
domain = "gitlab.freedesktop.org";
owner = "monado";
repo = "monado";
rev = "bb9bcee2a3be75592de819d9e3fb2c8ed27bb7dc";
hash = "sha256-+PiWxnvMXaSFc+67r17GBRXo7kbjikSElawNMJCydrk=";
rev = "5c137fe28b232fe460f9b03defa7749adc32ee48";
hash = "sha256-4P/ejRAitrYn8hXZPaDOcx27utfm+aVLjtqL6JxZYAg=";
};
postPatch = ''
@@ -88,6 +90,15 @@ stdenv.mkDerivation (finalAttrs: {
fi
'';
patches = [
# Needed to allow WiVRn in-stream GUI to launch Steam games
(fetchpatch {
name = "wivrn-allow-launching-steam-games.patch";
url = "https://github.com/WiVRn/WiVRn/commit/30ceab5b3082cbc545acf8bc8ca4a24279e6f738.diff";
hash = "sha256-BD6MhCET7hdjog8rkl7G2l7/zGfVATpNAhNie0efOlA=";
})
];
nativeBuildInputs = [
cmake
git
@@ -117,10 +128,12 @@ stdenv.mkDerivation (finalAttrs: {
kdePackages.kirigami
kdePackages.qcoro
kdePackages.qqc2-desktop-style
libarchive
libdrm
libGL
libnotify
libpulseaudio
librsvg
libva
libX11
libXrandr