Gaming on nixos

A post about the tools and modules you should use to improve your gaming experience on NixOS both from hardware and software perspective.

Vimjoyer avatar

Vimjoyer


This post is available in video form


NixOS is a general purpose Linux distribution capable of doing anything from serving your simple web app to being a fully-fledged desktop OS, which is why it always seems strange to me when people ask about wether or not you should or even can game on NixOS at all. And so, answering the question from the clickbaity thumbnail, NixOS is not the best gaming distro - because there probably isn’t one.

However, if you, like me, want it to be a great gaming distro, then this post is definetely for you, because today I will showcase several different programs and options you can set for comfortable gaming experience on NixOS.

OpenGL

And the first thing we want to do is to enable OpenGL and the corrent GPU drivers. Enabling OpenGL is simply a matter of adding these several lines to your configuration.

# configuration.nix
 
{ pkgs, }:
 
{
 
  hardware.opengl = {
    enable = true;
    driSupport = true;
    driSupport32Bit = true;
  };
 
  services.xserver.videoDrivers = [nvidia];
  # services.xserver.videoDrivers = [“amdgpu”];
 
  hardware.nvidia.modesetting.enable = true;
 
}

This step can be omitted entirely if you’re going to enable steam, but having it in your configuration won’t hurt anyway.

GPU

Now, loading GPU drivers on NixOS is done by adding them to the services.xserver.videoDrivers list, which, contrary to the option name, will enable them for both X and Wayland.

If you are using Nvidia you might also want to enable modesetting for some wayland compositors and desktop environments to work properly, but if you are not experiencing any issues, this step can be skipped too.

These are pretty much all the options you need to set on a regular desktop PC, however, if you are using a hybrid graphics laptop with an Nvidia GPU, which, I know, many of you do, you might want to configure Nvidia Optimus Prime. This step is kinda lenghty, so if it’s not about you, feel free to skip to the next section

Prime has two different modes called offload and sync. In the offload mode the dedicated GPU is only enabled when needed, optimizing power consumption, and the sync mode, on the other hand, keeps your dedicated GPU running at all times, improving game performance at the expense of battery life.

For both of these to work you will need to determine the bus IDs of your GPUs, and there are several ways to do it. I personally prefer to use the lspci utility from the pciutils package, which you can run on any nix machine with this command:

nix shell nixpkgs#pciutils -c lspci | grep VGA

It will output both values we need, and, judging by their names, we can determine that in this example I have an Nvidia dedicated GPU with an ID 01:00.0 and an AMD builtin with an ID 06:00.0.

01:00.0 VGA compatible controller: NVIDIA Corporation GA106M [GeForce…
06:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/…

We can now go back to our NixOS configuration and add these values here. Make sure to select the correct option for your iGPU vendor, whether it is AMD or Intel.

Sync mode
# configuration.nix
 
{ pkgs, }:
 
{
 
  hardware.nvidia.prime = {
    sync.enable = true;
 
    # integrated
    amdgpuBusId =PCI:6:0:0
    # intelBusId = “PCI:0:0:0”;
 
    # dedicated
    nvidiaBusId =PCI:1:0:0;
  };
 
}

If you chose to enable the offload mode the enableOffloadCmd option will provide us with a convenient wrapper shell script that will tell your Nvidia gpu to take over any command given to it, meaning all you have to do is to prefix your game executables with this command for them to run on dGPU.

Offload mode
# configuration.nix
 
{ pkgs, }:
 
{
 
  hardware.nvidia.prime = {
    offload = {
        enable = true;
        enableOffloadCmd = true;
    };
 
    # integrated
    amdgpuBusId =PCI:6:0:0
    # intelBusId = “PCI:0:0:0”;
 
    # dedicated
    nvidiaBusId =PCI:1:0:0;
  };
 
}

The general rule of thumb here is to choose offload if you are traveling a lot with your laptop and sync if you always have access to the power grid.

However, if you still want to have both, NixOS specializations allow us to define system variations that will only slightly differ from the original configuration, meaning we can go ahead to choose the offload mode and then define a specialization, call it gaming-time, for example, that will force off your offload mode and enable sync instead. Now you will get two boot entries on every rebuild instead of one, allowing you to choose your desired mode every time you start your computer.

Specializations
# configuration.nix
 
{ pkgs, }:
 
{
 
  hardware.nvidia.prime = {
    offload = {
      enable = true;
      enableOffloadCmd = true;
    };
 
    # integrated
    # intelBusId = “PCI:0:0:0”;
    amdgpuBusId =PCI:6:0:0
 
    # dedicated
    nvidiaBusId =PCI:1:0:0;
  };
 
  specialisation = {
    gaming-time.configuration = {
 
      hardware.nvidia = {
        prime.sync.enable = lib.mkForce true;
        prime.offload = {
          enable = lib.mkForce false;
          enableOffloadCmd = lib.mkForce false;
        };
      };
 
    };
  };
 
}

Nixos-hardware

And now, while we are still on the topic of hardware, I want to mention the official nixos-hardware github repo, which already includes ready to use hardware modules for many pre-built machines. These modules include optimized settings taking care of your kernel modulse, firmware, cooling, battery, CPU, and even the upper mention GPU bus IDs. It even has it’s own flake, so if you wish to import a module from it, you can simply add it to your inputs and grab any module from it.

Using nixos-hardware
{
  description =NixOS configuration with flakes;
  inputs.nixos-hardware.url =github:NixOS/nixos-hardware/master;
 
  outputs = { self, nixpkgs, nixos-hardware }: {
    # replace <your-hostname> with your actual hostname
    nixosConfigurations.<your-hostname> = nixpkgs.lib.nixosSystem {
      # …
      modules = [
        # …
        # add your model from this list: https://github.com/NixOS/nixos-hardware/blob/master/flake.nix
        nixos-hardware.nixosModules.dell-xps-13-9380
      ];
    };
  };
}

There is also an example for importing these modules with fetchGit, which you can use if you haven’t yet switched to flakes.

imports = [
${builtins.fetchGit { url =https://github.com/NixOS/nixos-hardware.git; }}/lenovo/thinkpad/x220
];

Steam

Enough talking about hardware, let’s finally talk software. And to kick it off, probably the most important piece of software for any gamer is steam. Now, I know that nowadays it’s not the only way to run games on Linux, and we will run about some alternatives later, but it’s massive influence on Linux gaming as a whole cannot be understated. And so to enable it on NixOS we can just add this one line to our config. It will install steam and set some other options you may need to run the games.

# configuration.nix
 
{ pkgs, }:
 
{
 
  programs.steam.enable = true;
 
}

While we are here, let’s also enable a bunch of wrapper commands that will make our gaming experience smoother.

  • Gamescope allows us to start a game in an optimized micro compositor that may help you if the game you are running has problems with upscaling or resolutions on your specific desktop environment or your window manager.

  • Mangohud is a simple overlay program for monitoring FPS, temperature, CPU and GPU load, and more.

  • And, finally, last but not least, Gamemode, that will greatly improve your game’s performance by requesting a set of optimizations to be temporarily applied to the OS and the game process.

To access those capabilities, gamemode and gamescope require specific system permissions, so adding them to the systemPackages alone will not suffice, hence the enable options.

Wrappers usage
# configuration.nix
 
{ pkgs, }:
 
{
 
  programs.steam.enable = true;
  programs.steam.gamescopeSession.enable = true;
 
  environment.systemPackages = with pkgs; [
    mangohud
  ];
 
  programs.gamemode.enable = true;
 
}

Now you can simply prepend any of these programs to the executables in any game’s General options.

Usage with steam's General options

Usage with steam's General options

Proton-ge

Next up, let’s talk about installing GloriousEggroll’s proton fork, ProtonGE. It offers some additional patches not included in regular proton and may greatly improve performance in some games. We will actually use an imperative way today, but that’s because steam will update some of it’s components every time you start it anyway.

To install ProtonGE, we can use the convenient protonup command, does require us to specify the installation path. There are many ways to do it, so here are some of them.

  • We can add an environment variable to our NixOS configuration and run the protonup command:
With environment
# configuration.nix
 
{ pkgs, }:
 
{
 
  environment.systemPackages = with pkgs; [
    protonup
  ];
 
  environment.sessionVariables = {
    STEAM_EXTRA_COMPAT_TOOLS_PATHS =
      ”\${HOME}/.steam/root/compatibilitytools.d;
  };
 
}
  • We can include it in our home-manager configuration and run the protonup command:
With home-manager
# home.nix
 
{ pkgs, }:
 
{
 
  home.packages = with pkgs; [
    protonup
  ];
 
  home.sessionVariables = {
    STEAM_EXTRA_COMPAT_TOOLS_PATHS =
      ”\\\${HOME}/.steam/root/compatibilitytools.d;
  };
 
}
  • Or even simply pass the correct path with a -d flag.
protonup -d ”~/.steam/root/compatibilitytools.d/”

Afterwards, you can simply select the newly installed proton version in the compatibiliy menu of any steam game.

Selecting correct proton version

Selecting correct proton version

Game launchers

And now, let’s also talk about alternative ways to run games on NixOS. And, first up, we have the popular lutris launcher. It allows you to run games from all sorts of sources, can help with managing wine and proton versions and generally serves as a all-in-one Linux game launcher. It does not require any extra permissions, so installing it on NixOS is simply a matter of adding them to your systemPackages

# configuration.nix
 
{ pkgs, }:
 
{
    environment.systemPackages = with pkgs; [
        lutris
    ];
}
 

Another useful game launcher you can try on NixOS is called heroic. It allows you to seamlessly run all of your epic and gog games and features a wide range of easy-to-use wine and proton settings.

# configuration.nix
 
{ pkgs, }:
 
{
    environment.systemPackages = with pkgs; [
        heroic
    ];
}
 

And, finally, if the games that you want to run cannot be installed with the previous solutions, your best bet will probably be bottles.

Bottles is an incredible wine prefix manager that comes with some sensible presets and the most intuitive interface I’ve ever seen in an application like this.

# configuration.nix
 
{ pkgs, }:
 
{
    environment.systemPackages = with pkgs; [
        bottles
    ];
}
 

You can use it to run regular Windows .exe files, making it a perfect solution for games not published on major platforms.

ProtonDB

And, before I finish this post, I also wanted to mention ProtonDB, which is an official steam Linux compatibility database that you can use before buying any games to know whether or not they will actually work on Linux, because, like I’ve said in the beginning, NixOS is just another linux distro when it comes to gaming, so any issues and fixes you see there will most probably also work for you.