Issue getting Nvidia settings to load on startup

Hi! I’m having an issue getting the settings from .nvidia-settings-rc to load on startup.

I had a issue with my monitor flickering and stuttering when GSync was enabled. I don’t care about it so instead of going through the agony of trying to fix nvidia stuff, I just disabled it which fixed issue.
But now when I reboot, the stuttering and flickering returns untill I open the nvidia settings panel or run nvidia-settings --load-config-only.

I tried to create a systemd service to run nvidia-settings --load-config-only on boot, but failed (mostly because I don’t know what I am doing, I have never created a systemd service before, and I am still new to NixOS). Untill I found this post of someone also having a nvidia issue and needing to run nvidia-settings on each boot.

systemd.services.nvidia-load-settings = {
  description = "Loads the .nvidia-settings-rc file on boot";
  serviceConfig = {
    #Type = "simple";
    Type = "oneshot";
    ExecStart = "${config.hardware.nvidia.package.settings}/bin/nvidia-settings --load-config-only";
  };
  wantedBy = [ "multi-user.target" ];
};

This actually creates the service but has an error running it.

➜  ~ systemctl status nvidia-load-settings.service  
× nvidia-load-settings.service - Loads the .nvidia-settings-rc file on boot
     Loaded: loaded (/etc/systemd/system/nvidia-load-settings.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Wed 2024-04-24 22:11:29 CEST; 29s ago
    Process: 13295 ExecStart=/nix/store/ry9g089jgzj1agpdb8yy5r5rb3byvgwc-nvidia-settings-545.29.02/bin/nvidia-settings --load-config-only (code=exited, status=1/FAILURE)
   Main PID: 13295 (code=exited, status=1/FAILURE)
         IP: 0B in, 0B out
        CPU: 13ms

apr 24 22:11:29 titanium systemd[1]: Starting Loads the .nvidia-settings-rc file on boot...
apr 24 22:11:29 titanium nvidia-settings[13295]: ERROR: The control display is undefined; please run `/nix/store/ry9g089jgzj1agpdb8yy5r5rb3byvgwc-nvidia-settings-545.29.02/bin/nvidia-settings --help` for usage information.
apr 24 22:11:29 titanium systemd[1]: nvidia-load-settings.service: Main process exited, code=exited, status=1/FAILURE
apr 24 22:11:29 titanium systemd[1]: nvidia-load-settings.service: Failed with result 'exit-code'.
apr 24 22:11:29 titanium systemd[1]: Failed to start Loads the .nvidia-settings-rc file on boot.

Manually restarting the service gives the same result.
Looking up the “The control display is undefined” error didn’t result in any insights for me.
When I run the command myself it runs fine. It does appear to output some kind of error but it has exit code 0 so I assume that is not what the service is complaining about.

➜  ~ nvidia-settings --load-config-only                
ERROR: libGL setup error : libGL.so.1: cannot open shared object file: No such file or directory
ERROR: libEGL setup error : libEGL.so.1: cannot open shared object file: No such file or directory
ERROR: libEGL setup error : libEGL.so.1: cannot open shared object file: No such file or directory
➜  ~ echo $?
0

Any help would be appreciated!

1 Like

Hi! Here is what I eventually came up with after that post:

systemd.user.services.nvidia-apply-settings = {
    wantedBy = [ "default.target" ];
    description = "Apply the nvidia-settings.";
    serviceConfig = {
      Type = "simple";
      Restart = "on-failure";
      ExecStart = ''${config.hardware.nvidia.package.settings}/bin/nvidia-settings --load-config-only'';
    };
  };

This launches nvidia-settings after you log in (notice that this is a user service), so any problems you have before loading nvidia-settings will be present on the login screen.

The main things here about this service is that it simply won’t work without wantedBy = [ "default.target" ];, and if I remember correctly there is a chance it does not work on the first try (too early into login process, and it simply won’t work at all if you select any other target), so I made the thing a simple service with Restart = "on-failure"; so it will try until it succeeds. You can try to increase the amount of times systemd tries to restart the service by setting the StartLimitBurst setting to how many times it should try (3 is the default afaik)

2 Likes

To explain why the original fails, nvidia-settings needs to run under an Xorg (or wayland, with severely limited functionality) context to do anything. The systemd non-user service will launch without such a context, so there’s no display for nvidia-settings to manage, and it fails.

Launching it as a user service will be more successful, but I’d recommend changing the wantedBy to:

systemd.user.services.nvidia-apply-settings = {
    wantedBy = [ "graphical-session.target" ];
    description = "Apply the nvidia-settings.";
    serviceConfig = {
      Type = "simple";
      Restart = "on-failure";
      ExecStart = ''${config.hardware.nvidia.package.settings}/bin/nvidia-settings --load-config-only'';
    };
  };

That way it’s guaranteed to actually run after your graphical session has started (assuming your WM/DM is set up to launch that target, which I think all NixOS ones are, but if it doesn’t work that’s the culprit), not when you log into a tty or such.

3 Likes

Also, depending on the implementation of WM/DE’s systemd integration, you may also need to ensure that certain environment variables (like DISPLAY for xorg and WAYLAND_DISPLAY for wayland) are set when the service runs. Systemd allows propagating and ensuring env vars through systemctl set-environment and through *Environment directives.

2 Likes

Thanks to all of you for the help and useful info! Works perfectly now :slight_smile: