diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md index e9e09c81ce92..b0957c03a99a 100644 --- a/nixos/doc/manual/release-notes/rl-2405.section.md +++ b/nixos/doc/manual/release-notes/rl-2405.section.md @@ -87,6 +87,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - [go-camo](https://github.com/cactus/go-camo), a secure image proxy server. Available as [services.go-camo](#opt-services.go-camo.enable). +- [Monado](https://monado.freedesktop.org/), an open source XR runtime. Available as [services.monado](#opt-services.monado.enable). + - [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable). - [TuxClocker](https://github.com/Lurkki14/tuxclocker), a hardware control and monitoring program. Available as [programs.tuxclocker](#opt-programs.tuxclocker.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 1c0d256ea1b2..378921c99694 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -548,6 +548,7 @@ ./services/hardware/lcd.nix ./services/hardware/lirc.nix ./services/hardware/nvidia-container-toolkit-cdi-generator + ./services/hardware/monado.nix ./services/hardware/nvidia-optimus.nix ./services/hardware/openrgb.nix ./services/hardware/pcscd.nix diff --git a/nixos/modules/services/hardware/monado.nix b/nixos/modules/services/hardware/monado.nix new file mode 100644 index 000000000000..9f9c6c39a0b4 --- /dev/null +++ b/nixos/modules/services/hardware/monado.nix @@ -0,0 +1,102 @@ +{ config +, lib +, pkgs +, ... +}: +let + inherit (lib) mkDefault mkEnableOption mkIf mkOption mkPackageOption types; + + cfg = config.services.monado; + +in +{ + options.services.monado = { + enable = mkEnableOption "Monado user service"; + + package = mkPackageOption pkgs "monado" { }; + + defaultRuntime = mkOption { + type = types.bool; + description = '' + Whether to enable Monado as the default OpenXR runtime on the system. + + Note that applications can bypass this option by setting an active + runtime in a writable XDG_CONFIG_DIRS location like `~/.config`. + ''; + default = false; + example = true; + }; + + highPriority = mkEnableOption "high priority capability for monado-service" + // mkOption { default = true; }; + }; + + config = mkIf cfg.enable { + security.wrappers."monado-service" = mkIf cfg.highPriority { + setuid = false; + owner = "root"; + group = "root"; + # cap_sys_nice needed for asynchronous reprojection + capabilities = "cap_sys_nice+eip"; + source = lib.getExe' cfg.package "monado-service"; + }; + + services.udev.packages = with pkgs; [ xr-hardware ]; + + systemd.user = { + services.monado = { + description = "Monado XR runtime service module"; + requires = [ "monado.socket" ]; + conflicts = [ "monado-dev.service" ]; + + unitConfig.ConditionUser = "!root"; + + environment = { + # Default options + # https://gitlab.freedesktop.org/monado/monado/-/blob/4548e1738591d0904f8db4df8ede652ece889a76/src/xrt/targets/service/monado.in.service#L12 + XRT_COMPOSITOR_LOG = mkDefault "debug"; + XRT_PRINT_OPTIONS = mkDefault "on"; + IPC_EXIT_ON_DISCONNECT = mkDefault "off"; + }; + + serviceConfig = { + ExecStart = + if cfg.highPriority + then "${config.security.wrapperDir}/monado-service" + else lib.getExe' cfg.package "monado-service"; + Restart = "no"; + }; + + restartTriggers = [ cfg.package ]; + }; + + sockets.monado = { + description = "Monado XR service module connection socket"; + conflicts = [ "monado-dev.service" ]; + + unitConfig.ConditionUser = "!root"; + + socketConfig = { + ListenStream = "%t/monado_comp_ipc"; + RemoveOnStop = true; + + # If Monado crashes while starting up, we want to close incoming OpenXR connections + FlushPending = true; + }; + + restartTriggers = [ cfg.package ]; + + wantedBy = [ "sockets.target" ]; + }; + }; + + environment.systemPackages = [ cfg.package ]; + environment.pathsToLink = [ "/share/openxr" ]; + + environment.etc."xdg/openxr/1/active_runtime.json" = mkIf cfg.defaultRuntime { + source = "${cfg.package}/share/openxr/1/openxr_monado.json"; + }; + }; + + meta.maintainers = with lib.maintainers; [ Scrumplex ]; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index a70326a436ef..a5991abbfc88 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -537,6 +537,7 @@ in { mobilizon = handleTest ./mobilizon.nix {}; mod_perl = handleTest ./mod_perl.nix {}; molly-brown = handleTest ./molly-brown.nix {}; + monado = handleTest ./monado.nix {}; monica = handleTest ./web-apps/monica.nix {}; mongodb = handleTest ./mongodb.nix {}; moodle = handleTest ./moodle.nix {}; diff --git a/nixos/tests/monado.nix b/nixos/tests/monado.nix new file mode 100644 index 000000000000..8368950951e7 --- /dev/null +++ b/nixos/tests/monado.nix @@ -0,0 +1,39 @@ +import ./make-test-python.nix ({ pkgs, ... }: { + name = "monado"; + + nodes.machine = + { pkgs, ... }: + + { + hardware.opengl.enable = true; + users.users.alice = { + isNormalUser = true; + uid = 1000; + }; + + services.monado = { + enable = true; + defaultRuntime = true; + }; + # Stop Monado from probing for any hardware + systemd.user.services.monado.environment.SIMULATED_ENABLE = "1"; + + environment.systemPackages = with pkgs; [ openxr-loader ]; + }; + + testScript = { nodes, ... }: + let + userId = toString nodes.machine.users.users.alice.uid; + runtimePath = "/run/user/${userId}"; + in + '' + machine.succeed("loginctl enable-linger alice") + machine.wait_for_unit("user@${userId}.service") + + machine.wait_for_unit("monado.socket", "alice") + machine.systemctl("start monado.service", "alice") + machine.wait_for_unit("monado.service", "alice") + + machine.succeed("su -- alice -c env XDG_RUNTIME_DIR=${runtimePath} openxr_runtime_list") + ''; +}) diff --git a/pkgs/applications/graphics/monado/default.nix b/pkgs/applications/graphics/monado/default.nix index 40e5f916f3f3..7442f192fe24 100644 --- a/pkgs/applications/graphics/monado/default.nix +++ b/pkgs/applications/graphics/monado/default.nix @@ -41,6 +41,7 @@ , wayland-scanner , libdrm , zlib +, nixosTests # Set as 'false' to build monado without service support, i.e. allow VR # applications linking against libopenxr_monado.so to use OpenXR standalone # instead of via the monado-service program. For more information see: @@ -137,6 +138,10 @@ stdenv.mkDerivation { ./force-enable-steamvr_lh.patch ]; + passthru.tests = { + basic-service = nixosTests.monado; + }; + meta = with lib; { description = "Open source XR runtime"; homepage = "https://monado.freedesktop.org/"; diff --git a/pkgs/by-name/xr/xr-hardware/package.nix b/pkgs/by-name/xr/xr-hardware/package.nix new file mode 100644 index 000000000000..b2359c2673df --- /dev/null +++ b/pkgs/by-name/xr/xr-hardware/package.nix @@ -0,0 +1,27 @@ +{ + lib, + stdenvNoCC, + fetchFromGitLab +}: stdenvNoCC.mkDerivation { + pname = "xr-hardware"; + version = "unstable-2023-11-08"; + + src = fetchFromGitLab { + domain = "gitlab.freedesktop.org"; + owner = "monado/utilities"; + repo = "xr-hardware"; + rev = "9204de323210d2a5ab8635c2ee52127100de67b1"; + hash = "sha256-ZS15WODms/WKsPu+WbfILO2BOwnxrhCY/SoF8jzOX5Q="; + }; + + installTargets = "install_package"; + installFlagsArray = "DESTDIR=${placeholder "out"}"; + + meta = with lib; { + description = "Hardware description for XR devices"; + homepage = "https://gitlab.freedesktop.org/monado/utilities/xr-hardware"; + license = licenses.boost; + maintainers = with maintainers; [ Scrumplex ]; + platforms = platforms.linux; + }; +}