Installing NVIDIA Drivers on a Laptop in NixOS

Warning for readers: my main language is Russian, the translation may be incorrect in some places. Have fun reading.

This guide walks through the process of configuring NVIDIA proprietary drivers on a NixOS laptop with a hybrid graphics setup (a dedicated NVIDIA GPU and an integrated Intel GPU). Our specific hardware was a laptop with an NVIDIA GeForce GTX 1650 Ti and an Intel Core i5-10300H.

The journey involved several common errors and a final switch to a more stable configuration mode.

Step 1: Find Your GPU Bus IDs
For laptops with hybrid graphics, you must tell NixOS the PCI Bus IDs of both your integrated and dedicated GPUs.

  1. Open a terminal.

  2. The lspci command is not installed by default. Run it within a temporary shell:

    nix-shell -p pciutils
    
  3. Once inside the nix-shell, run the command to find your graphics devices:

    lspci | grep -E 'VGA|3D'
    
  4. You will get an output similar to this. Note the values at the beginning of each line (e.g., 00:02.0 and 01:00.0).

    00:02.0 VGA compatible controller: Intel Corporation CometLake-H GT2 [UHD Graphics]
    01:00.0 VGA compatible controller: NVIDIA Corporation TU117M [GeForce GTX 1650 Ti Mobile]
    
  5. Convert these IDs to the format PCI:BUS:SLOT:FUNCTION. For our example, this becomes:

    • Intel: PCI:0:2:0
    • NVIDIA: PCI:1:0:0
  6. Type exit to leave the nix-shell.

Step 2: Initial Configuration Attempt (PRIME Offload)

Our first goal was to use PRIME Offload, a mode that saves battery by keeping the NVIDIA GPU powered down until it’s explicitly needed.

Here is the initial configuration block we added to configuration.nix:

# Enable OpenGL
hardware.graphics = {
  enable = true;
  enable32Bit = true;
};

# Configure the NVIDIA driver
hardware.nvidia = {
  modesetting.enable = true;
  open = true; # Use the open-source kernel module
  nvidiaSettings = true;
  package = config.boot.kernelPackages.nvidiaPackages.stable;
  
  prime = {
    offload = {
      enable = true;
      enableOffloadCmd = true;
    };
    # Use the Bus IDs you found earlier
    intelBusId = "PCI:0:2:0";
    nvidiaBusId = "PCI:1:0:0";
  };
};

# Load the nvidia driver for Xorg and Wayland
services.xserver.videoDrivers = [ "modesetting" "nvidia" ];

Troubleshooting: The Errors We Encountered

Applying the initial configuration was not smooth. Here are the errors we faced and how we fixed them.

Error 1: `hardware.opengl.videoDrivers’ does not exist

  • Problem: This option has been renamed.
  • Solution: We changed hardware.opengl.videoDrivers to services.xserver.videoDrivers.

Error 2: `hardware.opengl.driSupport’ no longer has any effect

  • Problem: This option is now enabled automatically when hardware.opengl.enable is set to true.
  • Solution: We simply removed the driSupport = true; line from our configuration.

Error 3: Syntax Error, unexpected =

  • Problem: A simple typo where we wrote package = package = ....
  • Solution: We corrected the line to package = config.boot.kernelPackages.nvidiaPackages.stable;.

Error 4: attribute ‘production_open’ missing

  • Problem: We tried to use a package name (production_open) that doesn’t exist in this NixOS version.
  • Solution: We used the standard stable package and relied on the open = true; flag to select the correct variant.

Problem 5: The X11 Login Loop

  • Problem: After rebuilding, we could log in to the Wayland session, but trying to log into the “Plasma (X11)” session would show a black screen and return us to the login prompt. This is a classic “login loop”.
  • Root Cause: PRIME Offload can be complex to configure and sometimes conflicts with the X server startup.

Step 3: The Final Solution - Switching to PRIME Sync

To solve the login loop, we switched from Offload mode to PRIME Sync. This mode is less power-efficient but significantly more stable and easier to configure. It uses the NVIDIA GPU for all rendering and simply displays the final image on the screen.

  1. We modified the hardware.nvidia.prime block in our configuration.nix:

    # Replace the entire 'prime' block with this:
    prime = {
      sync.enable = true;
      intelBusId = "PCI:0:2:0";
      nvidiaBusId = "PCI:1:0:0";
    };
    
  2. We also removed "modesetting" from the videoDrivers list for maximum compatibility with X11:

    services.xserver.videoDrivers = [ "nvidia" ];
    
  3. We ran sudo nixos-rebuild switch and rebooted.

The Final Working Configuration

This is the final, working hardware.nvidia block that successfully configured our system:

# === NVIDIA CONFIGURATION FOR LAPTOP ===
hardware.graphics = {
  enable = true;
  enable32Bit = true;
};

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

hardware.nvidia = {
  modesetting.enable = true;
  open = true;
  nvidiaSettings = true;
  package = config.boot.kernelPackages.nvidiaPackages.stable;

  prime = {
    sync.enable = true; # The stable solution
    intelBusId = "PCI:0:2:0";
    nvidiaBusId = "PCI:1:0:0";
  };
};
# === END OF NVIDIA CONFIGURATION ===

Verification

After rebooting and logging into the “Plasma (X11)” session, we verified the installation by opening a terminal and running:

nvidia-smi

This command displayed a detailed table with our GTX 1650 Ti’s information, confirming that the driver was active and correctly configured. Games and applications now use the NVIDIA GPU by default.

3 Likes

Good attempt. This is approaching a correct setup, however:

These are default settings, omit them.

This is almost certainly not how you fixed the X11 “boot loop”. It was doing:

This has nothing to do with X11 compat; Adding the modesetting driver simply breaks your setup (since X11 will be configured to use nvidia but your iGPU will be driving the actual display). You can likely just disable sync.enable at this point and it’ll work.

When using prime offload, you need to use the nvidia-offload command to start any applications you want to run on the nvidia GPU. You can override your .desktop files to make this automatic for specific applications, by setting the environment variables it configures as part of the .desktop file.

Also note that none of this works on wayland (hence the “X11 compat” comment makes no sense ;p); for that you need compositor-specific configuration. I have a module (also needs this udev rule) that sets that up for the compositors I know about. This doesn’t include Hyprland.

2 Likes

Good catch on the modesetting conflict. You’re right, that’s the real fix.

As I just installed NixOS today, I’ll leave the original guide as-is to document the beginner’s journey. Your comment serves as the perfect technical clarification and correction for anyone who finds this thread.

Appreciate you taking the time to write this out.

1 Like