Installing Guix on a 10th gen Thinkpad X1

December 05, 2022
Tags:

The last time I bought a laptop, I got a used Thinkpad X220 from eBay. I loved that laptop, but time marches on and old hardware eventually becomes too slow for modern development needs. After a lot of indecision, I bought a 10th generation Thinkpad X1 with an Intel Core i7-1280P CPU, 32GB RAM, and 1TB NVMe SSD. While they don’t make Thinkpads like they used to, I’m still really happy with it and glad I chose it. Despite the keyboard changes, the TrackPoint™ is still there and I don’t think I could feel good using a laptop without it. Below I will explain all the steps I took to get the Guix distribution setup nicely on it. Maybe it can help you setup your own Thinkpad X1 or some other computer that requires more than what Guix provides for all of the hardware to work.

But first, a tangent about proprietary firmware

I'm going to talk about proprietary firmware now. If you don't care, which is totally understandable, skip to the next section.

I wanted to use Guix, which uses Linux-libre, on whatever laptop I got, but I knew the situation with regards to proprietary firmware blobs on laptops has only gotten worse in recent years. Unfortunately, despite there being more free/open drivers than ever (such as for AMD GPUs), those free drivers are often accompanied by proprietary firmware. After an exhaustive search of the laptops that can run without any proprietary software blobs (such as the Librem 14), I wasn't really feeling good about buying any of them. Newer generations of the Intel Core line of CPUs with new integrated Iris Xe graphics hardware now require proprietary firmware. Intel wireless cards have required proprietary firmware for a long time. Even Intel sound hardware requires proprietary firmware! Then, there's the longstanding CPU microcode update issue. Linux-libre removes microcode updates, which are all proprietary, so users of Linux-libre do not receive critical security fixes to CPU-level vulnerabilities. Of laptops that were Linux-libre compatible, the Librem 14 seemed the best. It uses older Intel 10th gen Core CPUs, the last generation that can be used with Linux-libre and still have hardware accelerated graphics.

While I would certainly like a world where all devices were run with free/open firmware, I've come to find this "no proprietary firmware" stance of the GNU Free Distribution Guidelines to be a hindrance to the spread and adoption of free software. The FSF's (really RMS's) stance on the firmware issue isn't exactly based on a solid foundation anyway. Firmware on nearly every device is proprietary, but most devices have the firmware “baked in” and do not need it loaded at system boot time. So, from the FSF's perspective, we can make an abstraction: A device may or may not have proprietary firmware on it, but if we never have to load that firmware then we can treat it as if it were hardware. It's only once the kernel gets involved that proprietary firmware becomes an issue, because the hardware maker now has the opportunity to provide malicious firmware updates. Okay, I get the abstraction and the potential risk, but it feels like a cop out. The lack of CPU microcode updates on fully free systems is the most damning evidence I've seen that this stance is a net-negative for users and for the free software movement. All of those users (myself included, on many past computers) are vulnerable to well-known issues that are patched in microcode updates! I'm a big free software guy, but we don't have our priorities straight here. Lack of firmware is the biggest blocker for people who want to use as much free software as possible. They often attempt to install a fully free distro only to find out that they can’t connect to the Internet because they have an Intel wireless card that requires a blob and our answer is “Sorry, buy new hardware.” I think we need to make a tactical retreat from the firmware battle and meet people where they are.

Anyway, I decided to abandon Linux-libre. While Guix itself does not provide vanilla Linux (with firmware blobs), Guix allows for adding unofficial package repositories called “channels.” One such repository is nonguix which does have Linux and a bunch of other stuff, like Firefox. It’s very nice and I recommend it! Thanks to the good folks who maintain it! Guix should drop the FSDG requirements! RMS will be mad but that’s okay!

Okay, off the soapbox and onto the installation process!

Download installer

I used the latest installer rather than the standard one because Guix goes a long time between releases and I wanted the freshest stuff.

wget https://ci.guix.gnu.org/search/latest/ISO-9660?query=spec:images+status:success+system:x86_64-linux+image.iso

Install to flash drive

I used good ol' disk destroyer to write the ISO image onto a flash drive:

sudo dd if=guix.iso of=/dev/sda bs=16M
sudo sync

Boot from the flash drive

Important note: I had the laptop connected to a dock with an Ethernet cable attached. This is critical because the official Guix installer uses Linux-libre, so the wireless card will not work. It is possible to build your own installation image using the instructions in the nonguix README, but using an Ethernet connection for the initial install is a lot easier.

This may be self-explanatory but for completeness, I did this:

Installer and initial system bootstrap

The Guix installer has become quite nice. It's an ncurses interface, not a fancy GTK one, but all the important stuff worked.

I did the following:

Once installation was complete, I removed the flash drive and ran reboot to reboot into the installed Guix system.

Note: When using full disk encryption, Guix is a little annoying in that you have to enter the decryption password twice. Once to get to the GRUB menu, and once more to get to the login screen.

Add nonguix channel

I wrote the following to ~/.config/guix/channels.scm:

(cons* (channel
        (name 'nonguix)
        (url "https://gitlab.com/nonguix/nonguix")
        (introduction
         (make-channel-introduction
          "897c1a470da759236cc11798f4e0a5f7d4d59fbc"
          (openpgp-fingerprint
           "2A39 3FFF 68F4 EF7A 3D29  12AF 6F51 20A0 22FB B2D5"))))
       %default-channels)

To activate the nonguix channel, I did this:

Having the channel activated is great, but to avoid compiling Linux from source I had to also enable Guix to download substitutes from the nonguix substitute server:

wget https://substitutes.nonguix.org/signing-key.pub
mv signing-key.pub nonguix-signing-key.pub
sudo guix archive --authorize < nonguix-signing-key.pub

Reconfigure system with Linux and GNOME

This is the OS configuration I ended up with:

(use-modules (gnu)
             (gnu services desktop)
             (nongnu packages linux)
             (nongnu system linux-initrd))

(operating-system
 ;; Use regular Linux with the big bad proprietary firmware blobs.
 (kernel linux)
 (initrd microcode-initrd)
 ;; sof-firmware is required for sound to work, linux-firmware takes
 ;; care of everything else.
 (firmware (list sof-firmware linux-firmware))
 (locale "en_US.utf8")
 (timezone "America/New_York")
 (keyboard-layout (keyboard-layout "us"))
 (host-name "ikaruga")
 (users (cons* (user-account
                (name "dave")
                (comment "David Thompson")
                (group "users")
                (home-directory "/home/dave")
                (supplementary-groups '("wheel" "netdev" "audio" "video")))
               %base-user-accounts))
 (packages (append (list (specification->package "nss-certs"))
                   %base-packages))
 (services (modify-services (cons (service gnome-desktop-service-type)
                                  %desktop-services)
             ;; Get nonguix substitutes.
             (guix-service-type config =>
                                (guix-configuration
                                 (inherit config)
                                 (substitute-urls
                                  (append (list "https://substitutes.nonguix.org")
                                          %default-substitute-urls))
                                 (authorized-keys
                                  (append (list (local-file "./nonguix-signing-key.pub"))
                                          %default-authorized-guix-keys))))))
 (bootloader (bootloader-configuration
              (bootloader grub-efi-bootloader)
              (targets (list "/boot/efi"))
              (keyboard-layout keyboard-layout)))
 (mapped-devices (list (mapped-device
                        (source (uuid "02b1ffb4-d868-4e5f-ab9b-8be3092e3a3c"))
                        (target "cryptroot")
                        (type luks-device-mapping))))
 (file-systems (cons* (file-system
                        (mount-point "/boot/efi")
                        (device (uuid "91D3-F76B" 'fat32))
                        (type "vfat"))
                      (file-system
                        (mount-point "/")
                        (device "/dev/mapper/cryptroot")
                        (type "ext4")
                        (dependencies mapped-devices))
                      %base-file-systems)))

To reconfigure the system using nonguix for the first time, the nonguix substitute server must be passed using a command line flag. Subsequent updates do not require this because the OS configuration above includes the relevant configuration for the Guix service to use nonguix substitutes automatically.

This is what I ran:

sudo -E guix system reconfigure config.scm --substitute-urls='https://ci.guix.gnu.org https://bordeaux.guix.gnu.org https://substitutes.nonguix.org'

When I rebooted, I was greeted by the GDM login screen. Success!

Hope this is helpful to someone out there, or at least my future self who has long since forgotten how to do a fresh install!