Guide to setup openrgb on NixOS

Hey, folks, I was trying to set up openrgb on NixOS. My initial assumption was that all I have to do was add this to systemPackages and I will be done. That does not seem to be the case.

One of the devs of openrgb made a tutorial on how to configure this on Linux. Vide Link. What is the nix way to do this?

I have added openrgb and i2c-tools to the config. Next the person suggests to copy a file to udev rules, which I added to the /etcnixos/configuration.nix file like

  services.udev.extraRules = ''
    ${builtins.readFile ./60-openrgb.rules}
  '';

where I have this file in the same folder as my config files.

This creates a file by the name of 99-local.rules in /etc/udev/rules.d - Does naming matter for a udev file? Afterwards, he suggests to execute:

sudo udevadm control --reload-rules
sudo udevadm trigger

If I do nixos-rebuild will it automatically do these? Doing so outputs the following. Now what I don’t understand is that is this the same as the above operation?

stopping the following units: systemd-udevd-control.socket, systemd-udevd-kernel.socket, systemd-udevd.service
activating the configuration...
setting up /etc...
reloading user units for sherub...
setting up tmpfiles
starting the following units: systemd-udevd-control.socket, systemd-udevd-kernel.socket

They the video proceeds to setup i2c-dev

sudo modprobe i2c-dev
sudo modprobe i2c-piix4

When I execute these I get following errors

❯ sudo modprobe i2c-dev                                                                                       
modprobe: can't change directory to '/lib/modules': No such file or directory

❯ sudo modprobe i2c-piix4                                                                                     
modprobe: can't change directory to '/lib/modules': No such file or directory

❯ sudo i2cdetect -l                                                                                           
i2cdetect: can't open '/sys/class/i2c-dev': No such file or directory

First and foremost this feels non-nixy. What is the nix way of achieving this? Also, what do these errors mean and how to resolve these?

Should the nix derivation of this package take care of all this stuff?

[EDIT]: After a restart, openrgb was able to detect the motherboard. It was not able to find the AMD cooler (stock) and the RAM-sticks (Corsaier vengeance).
I believe which answers the question that the naming in udev rules file is inconsequential.

1 Like

it will determine the order, 99 is considered the last to be executed. But for this case, it probably doesn’t matter

nixos-rebuild switch should, but it will definitely take affect next boot

the modprobe commands should be replaced with boot.kernelModules:

  boot.kernelModules = [ "i2c-dev" "i2c-piix4" ];

And then all of this should get applied with sudo nixos-rebuild switch

Altogether, I would do something like (haven’t verified that this works):

{ config, pkgs, ... }:

let
  openrgb-rules = builtins.fetchurl {
    url = "https://gitlab.com/CalcProgrammer1/OpenRGB/-/raw/master/60-openrgb.rules";
  }
in {

  ...
  boot.kernelModules = [ "i2c-dev" "i2c-piix4" ];
  
  services.udev.extraRules =  builtins.readFile openrgb-rules;
  ...

then just do nixos-rebuild to apply the changes.

3 Likes

@jonringer Thanks for that elaborate answer. This takes care of of the problem I had with all this being unlike nix. Nifty tip there with the fetchUrl in let block.

I can’t get the RAM module and the AMD stock cooler lighting to work, but I believe that is outside the scope of this discussion. Probably a bug in the program. Will try to see what the devs of OpenRGB think.

in the video, he mentioned import a module specific to razor, I’m assuming you would have to do something similar for corsair and the cooler

I am in the a similar position as this author’s thread, trying to setup openrgb for a keyboard (Razer OrnataV3).

Using

{ config, pkgs, ... }:
let
  openrgb-rules = builtins.fetchurl {
  	url = "https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/raw/60-openrgb.rules?job=Linux+64+AppImage";
  };
in {
  boot.kernelModules = [ "i2c-dev" "i2c-piix4" ];
  services.udev.extraRules =  builtins.readFile openrgb-rules;
}

, adapted and updated from the snippet offered by @jonringer above, I am running into:

Adding rules for package /nix/store/dd7q5jadc2y7ydwc13pwawd4cci2zr7z-alsa-utils-1.2.10
Copying /nix/store/dd7q5jadc2y7ydwc13pwawd4cci2zr7z-alsa-utils-1.2.10/lib/udev/rules.d/90-alsa-restore.rules to /nix/store/95s04vca0w1m3fj8kp3vav47nniwy8pm-udev-rules/90-alsa-restore.rules
Checking that all programs called by relative paths in udev rules exist in /nix/store/iidxwcyp8pqhrq3iji17shs4m6gin0kv-systemd-254.6/lib/udev... OK
Checking that all programs called by absolute paths in udev rules exist... grep: warning: stray \ before /
FAIL
/bin/chmod is called in udev rules but is not executable or does not exist

Any hint?

You’ll need to do something like substituteInPlace to change the FHS paths to nix store paths

Understood, thanks a lot!

Did you (or anyone else) do this with flakes. I tried looking up the process to determine hashes and didn’t get very far (seems this should be easy info to find!).

Nope sorry, I ended up using a very lazy solution:

{ config, pkgs, ... }:
{
  boot.kernelModules = [ "i2c-dev" "i2c-piix4" ];
  services.udev.extraRules = ''
	# Just the rules I need for my hardware
    SUBSYSTEMS== ...  
  '';
}
1 Like

Thanks - not what I was looking for, but I forgot the “sidestep nix” style of doing this. I still need to learn how to sort this out, but your solution is a great step - I now have a backlit keyboard which is so much easier to use than the unlit version :slight_smile:

Glad to hear! The “side-step nix” approach works even better as a way of making tangible progress for the here and now, enjoy life a little while, and then get back to work and spiral your way up onto the full nix solution. :slight_smile:

Sorry for bringing a old thread from the dead, but I found a much better solution actually:

{pkgs,...}: {
  services.udev.extraRules = (builtins.readFile "${pkgs.openrgb}/lib/udev/rules.d/60-openrgb.rules");
}

Since this was posted, it was added as a module as services.hardware.openrg.enable

Even recorded myself making it, if you’re still curious.