System Crafters

Proprietary NVIDIA Drivers

GNU Guix makes installing and using the proprietary NVIDIA drivers more difficult than one may be used to coming from other distributions. However, it is possible and explained here.

Installation

Using the channel

If using the nonguix channel, the nvidia-driver package contains the proprietary drivers for GNU Guix. If you followed the nonguix installation guide, this should already be set up by default. From now on it will be assumed that the nonguix channel is available on your system.

The system configuration

Your system configuration is usually located at /etc/config.scm. We need to add several lines of code to make your system load the drivers properly. Open the file to edit it, and make sure you have write permissions.

Package definition

You need to add the nvidia package definition to your define-module function so Guix knows where to load it from:

(define-module (your-module)
  ;; ...
  ;; some stuff here
  ;; ...
  #:use-module (nongnu packages nvidia))

Renaming for grafting

In order to have libglx working, the nvidia-driver package needs to be grafted instead of mesa. It needs to be renamed to have the same number of characters as mesa. More information can be found here. Add the following function:

(define transform
  (options->transformation
   '((with-graft . "mesa=nvda"))))

OS configuration

From here on, everything mentioned should be placed in your operating-system block:

(define-public base-operating-system
  ;; ...
  (operating-system
   ;; here!
   ...))
  • Kernel modules

    You should blacklist the nouveau kernel module to avoid conflicts.

    (kernel-arguments (append 
                          '("modprobe.blacklist=nouveau")
                          %default-kernel-arguments))
    

    In addition, you should also add nvidia-driver to the loadable kernel modules:

    (kernel-loadable-modules (list nvidia-driver))
    
  • Services

    Now add two services. One for a custom udev rule and one to make sure the modules get loaded:

    (services (cons* (simple-service 
                         'custom-udev-rules udev-service-type 
                         (list nvidia-driver))
                        (service kernel-module-loader-service-type
                                 '("ipmi_devintf"
                                   "nvidia"
                                   "nvidia_modeset"
                                   "nvidia_uvm"))
                        ...))
    

Login manager

The system configuration is now complete. However, you probably want to setup a login manager. No matter what login manager you use, you need to list the nvidia-driver in the xorg-configuration block. Here is a minimal example using slim:

(service slim-service-type
         (slim-configuration
          (xorg-configuration (xorg-configuration
                               (modules (cons* nvidia-driver %default-xorg-modules))
                               (server (transform xorg-server))
                               (drivers '("nvidia"))))))

Please consult the manual for all possible xorg-configuration options.

Additional Xorg configuration

If you used to use special xorg configuration files (like /etc/X11/xorg.conf.d/10-nvidia.conf) you can also add them in Guix. Add the following to your xorg-configuration function: (extra-config (list %xorg-config)). You can rename %xorg-config to whatever you want. Just define the variable and add your configuration:

(define %xorg-config
  "Section \"Device\"
      Identifier     \"Device0\"
      Driver         \"nvidia\"
      VendorName     \"NVIDIA Corporation\"
      BoardName      \"GeForce GTX 1050 Ti\"
  EndSection")        

You can find examples for additional configurations in David's and minikN's config.

Reconfiguring the system

That's about it. The last thing you need to do is to reconfigure the system so your changes get applied. You need sudo in order to do that. You can use the following command:

sudo -E guix system --cores=$(nproc) -L /path/to/your/config.scm reconfigure

Screen tearing

After doing this, One may notice screen tearing when watching YouTube videos. To remedy this issue one has two options.

Force full composition pipeline

Forcing a full composition pipeline can help to avoid screen tearing. You can consult the Arch Wiki if you want to know about it. To put it simple, you need to add the MetaModes option to your screen Section block of your xorg configuration. Like this:

Section "Device"
        Identifier "Nvidia Card"
        Driver     "nvidia"
        VendorName "NVIDIA Corporation"
        BoardName  "GeForce GTX 1050 Ti"
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Device0"
    Monitor        "Monitor0"
    Option         "MetaModes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
    Option         "AllowIndirectGLXProtocol" "off"
    Option         "TripleBuffer" "on"
EndSection

However, the actual value of the option is dependent on your monitor setup. This was explained on the EXWM Wiki in greater detail.

Using a compositor

Generally, enabling the full composition pipeline works to get rid of screen tearing. However on GNU Guix it didn't for some reason. Maybe it'll work for you? In any case, another way is to use a compositor like picom (formely known as compton). There are multiple ways to set up a compositor.

Using EXWM

This example shows how to use picom with EXWM as a window manager. There is an emacs-exwm package. Unfortunately, one can not easily configure it to load picom as well. In addition, it still runs on Emacs 27.2, it could be benefitial to change to version 28 featuring native compilation. This package definition inheriting from emacs-exwm automatically starts picom and uses the native-compilation branch. Feel free to use it. It requires you to have set up flatwhatson's guix channel:

;; Override emacs-exwm package definition
;; To include emacs-native-comp and picom.
(define-public emacs-native-comp-exwm
  (package
   (inherit emacs-exwm)
   (name "emacs-native-comp-exwm")
   (synopsis "Emacs 28 with native compilation and picom as a compositor.")
   (inputs
    `(("picom" ,picom)
      ,@(package-inputs emacs-exwm)))
   (arguments
    `(,@(package-arguments emacs-exwm)
      #:emacs ,emacs-native-comp
      #:phases (modify-phases %standard-phases
                              (add-after 'build 'install-xsession
                                         (lambda* (#:key inputs outputs #:allow-other-keys)
                                                  (let* ((out (assoc-ref outputs "out"))
                                                         (xsessions (string-append out "/share/xsessions"))
                                                         (bin (string-append out "/bin"))
                                                         (exwm-executable (string-append bin "/exwm")))

                                                    ;; Add a .desktop file to xsessions
                                                    (mkdir-p xsessions)
                                                    (mkdir-p bin)
                                                    (make-desktop-entry-file
                                                     (string-append xsessions "/exwm.desktop")
                                                     #:name ,name
                                                     #:comment ,synopsis
                                                     #:exec exwm-executable
                                                     #:try-exec exwm-executable)

                                                    ;; Add a shell wrapper to bin
                                                    (with-output-to-file exwm-executable
                                                      (lambda _
                                                        (format #t "#!~a ~@
                                                                                       ~a +SI:localuser:$USER ~@
                                                                                       ~a &
                                                                                       exec ~a --exit-with-session ~a \"$@\" --eval '~s' ~%"
                                                                (string-append (assoc-ref inputs "bash") "/bin/sh")
                                                                (string-append (assoc-ref inputs "xhost") "/bin/xhost")
                                                                (string-append (assoc-ref inputs "picom") "/bin/picom")
                                                                (string-append (assoc-ref inputs "dbus") "/bin/dbus-launch")
                                                                (string-append (assoc-ref inputs "emacs") "/bin/emacs")
                                                                '(cond
                                                                  ((file-exists-p "~/.exwm")
                                                                   (load-file "~/.exwm"))
                                                                  ((not (featurep 'exwm))
                                                                   (require 'exwm)
                                                                   (require 'exwm-config)
                                                                   (exwm-config-default)
                                                                   (message (concat "exwm configuration not found. "
                                                                                    "Falling back to default configuration...")))))))
                                                    (chmod exwm-executable #o555)
                                                    #t))))))))