1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-12-02 15:11:03 +01:00
home-manager/docs/manual/usage/gpu-non-nixos.md

8 KiB

GPU on non-NixOS systems

To access the GPU, programs need access to OpenGL and Vulkan libraries. While this works transparently on NixOS, it does not on other Linux systems. There are two options:

  1. Recommended: modify the host system slightly so that the graphics libraries can be found where programs from Nixpkgs can find them.
  2. Wrap programs from Nixpkgs in an environment which tells them where to find graphics libraries.

The first option is very clean because the needed modifications to the host OS are small. However, it does require root/sudo access to the system, which may not be available. The second approach avoids that. However, it injects libraries from Nixpkgs into the environment of wrapped programs, which can make it impossible to launch programs of the host OS from wrapped programs.

When sudo is available: fixing the host OS

The {option}targets.genericLinux.gpu module is automatically enabled whenever the option {option}targets.genericLinux.enable is set (unless NixGL is used instead), which is recommended for non-NixOS Linux distributions in any case. The module can also be explicitly enabled by setting {option}targets.genericLinux.gpu.enable.

This module builds a directory containing GPU libraries. When activating the home configuration by home-manager switch, the host system is examined: for compatibility with NixOS, these libraries need to be placed in /run/opengl-driver. If this directory does not exist, or contains a different set of libraries, the activation script will print a warning such as

Activating checkExistingGpuDrivers
GPU drivers require an update, run
  sudo /nix/store/HASH-non-nixos-gpu/bin/non-nixos-gpu-setup

Because the /run directory is volatile and disappears on reboot, libraries cannot be simply copied or linked there. The non-nixos-gpu-setup script installs a Systemd service which ensures that the drivers are linked to /run/opengl-driver on boot. Home Manager will always check and warn you when this setup needs to be refreshed.

If you ever wish to uninstall these drivers, all you need to do is

sudo rm /run/opengl-driver
sudo systemctl disable --now non-nixos-gpu.service
sudo rm /etc/systemd/system/non-nixos-gpu.service

GPU offloading

You can use the {option}targets.genericLinux.nixGL.prime.installScript option. It installs the prime-offload script which is configured through options under {option}targets.genericLinux.nixGL.prime. This functionality is independent from the rest of NixGL and can be used when {option}targets.genericLinux.nixGL.packages is left null, which it should be when using drivers from /run/opengl-driver.

Nvidia drivers

If you need to include the proprietary Nvidia drivers, the process is a bit more involved. You need to:

  1. Determine the exact version used by the host system. Example: 550.163.01

  2. Fetch that version of the drivers from Nvidia and calculate their hash. Example:

    nix store prefetch-file \
      https://download.nvidia.com/XFree86/Linux-x86_64/550.163.01/NVIDIA-Linux-x86_64-550.163.01.run
    

    Attention: the version and architecture are present twice. If you are on an ARM system, replace x86_64 with aarch64.

  3. Put this information into your home configuration. Example:

    targets.genericLinux.gpu.nvidia = {
      enable = true;
      version = "550.163.01";
      sha256 = "sha256-74FJ9bNFlUYBRen7+C08ku5Gc1uFYGeqlIh7l1yrmi4=";
    };
    

::: {.warning} The Nvidia driver version must match the host system. This means that you must pay attention when upgrading the system and update the home configuration as well. :::

No root access: wrapping programs

The wrapping approach is facilitated by NixGL, which can be integrated into Home Manager.

::: {.warning}

This approach can cause issues when a wrapped program from Nixpkgs executes a program from the host. For example, Firefox from Nixpkgs must be wrapped by NixGL in order for graphical acceleration to work. If you then download a PDF file and open it in a PDF viewer that is not installed from Nixpkgs but is provided by the host distribution, there may be issues. Because Firefox's environment injects libraries from NixGL, they are inherited by the PDF viewer, and unless they are the same or compatible version as the libraries on the host, the viewer will not work. This problem manifests more often with Vulkan because it needs a larger set of injected libraries than OpenGL.

The problem typically manifests with errors similar to

/nix/store/HASH-gcc-12.3.0-lib/lib/libstdc++.so.6: version `GLIBCXX_3.4.31' not found

:::

To enable the integration, import NixGL into your home configuration, either as a channel, or as a flake input passed via extraSpecialArgs. Then, set the targets.genericLinux.nixGL.packages option to the package set provided by NixGL.

Once integration is enabled, it can be used in two ways: as Nix functions for wrapping programs installed via Home Manager, and as shell commands for running programs installed by other means (such as nix shell). In either case, there are several wrappers available. They can be broadly categorized

  • by vendor: as Mesa (for Free drivers of all vendors) and Nvidia (for Nvidia-specific proprietary drivers).
  • by GPU selection: as primary and secondary (offloading).

For example, the mesa wrapper provides support for running programs on the primary GPU for Intel, AMD and Nouveau drivers, while the mesaPrime wrapper does the same for the secondary GPU.

Note: when using Nvidia wrappers together with flakes, your home configuration will not be pure and needs to be built using home-manager switch --impure. Otherwise, the build will fail, complaining about missing attribute currentTime.

Wrapper functions are available under config.lib.nixGL.wrappers. However, it can be more convenient to use the config.lib.nixGL.wrap alias, which can be configured to use any of the wrappers. It is intended to provide a customization point when the same home configuration is used across several machines with different hardware. There is also the config.lib.nixGL.wrapOffload alias for two-GPU systems.

Another convenience is that all wrapper functions are always available. However, when targets.genericLinux.nixGL.packages option is unset, they are no-ops. This allows them to be used even when the home configuration is used on NixOS machines. The exception is the prime-offload script which ignores targets.genericLinux.nixGL.packages and is installed into the environment whenever targets.genericLinux.nixGL.prime.installScript is set. This script, which can be used to start a program on a secondary GPU, does not depend on NixGL and is useful on NixOS systems as well.

Below is an abbreviated example for an Optimus laptop that makes use of both Mesa and Nvidia wrappers, where the latter is used in dGPU offloading mode. It demonstrates how to wrap mpv to run on the integrated Intel GPU, wrap FreeCAD to run on the Nvidia dGPU, and how to install the wrapper scripts. It also wraps Xonotic to run on the dGPU, but uses the wrapper function directly for demonstration purposes.

{ config, lib, pkgs, nixgl, ... }:
{
  targets.genericLinux.nixGL = {
    packages = nixgl.packages;
    defaultWrapper = "mesa";
    offloadWrapper = "nvidiaPrime";
    installScripts = [ "mesa" "nvidiaPrime" ];
  };

  programs.mpv = {
    enable = true;
    package = config.lib.nixGL.wrap pkgs.mpv;
  };

  home.packages = [
    (config.lib.nixGL.wrapOffload pkgs.freecad)
    (config.lib.nixGL.wrappers.nvidiaPrime pkgs.xonotic)
  ];
}

The above example assumes a flake-based setup where nixgl was passed from the flake. When using channels, the example would instead begin with

{ config, lib, pkgs, ... }:
{
  targets.genericLinux.nixGL.packages = import <nixgl> { inherit pkgs; };
  # The rest is the same as above
  ...