From Guix to NixOS

Posted:

I love GNU and all of the work they do, but If i have to work a full time job to use your software the way I want, its not feasible for me to use...

Why GNU/Guix?

Throughout my time using Linux, I have hopped around many distributions. I started with Ubuntu, a commenly used Linux system. It is a preprepared Linux system, installing a windowing environment for you, a miltutude of system packages, and uses the apt package manager. I eventually switched to Manjaro as I found the apt package manager cumersome, and I wanted a leaner prebuilt system. Based on Arch, Manjaro uses the pacman package manager which I found to be alot faster and nicer to use. Manjaro still had a lot of packages preinstalled but I continued to use it for a few years, mainly throughout high school. When I got to college I wanted a system that I could build myself so I eventually switched to Arch Linux. As the base of Manjaro it shared many similarities but it allowed me to have more fine grain controll of what was on my computers.

Unsustainable state

What Ubuntu, Manjaro, and Arch Linux all have in common is that they are statefull systems. Each of them have a predefined base system which can build ontop of manually. The problem that I faced was forgetting what changes have been made, what programs were installed (and why I installed them), and what configurations were applied. At times I like to cut down or trim my system, but I would find that I dont know what is installed, where its installed, and why I installed it.

When trying to mirror my custom system on another device, things would never be exactly the same, and It was a hassle to try to mirror changes from one device to the other. I tried to use a git repository that stored some configurations and a list installed packages, but it never solved every edge case, and didn't allow me to have any differences between systems.

An example was that my laptop had a intel cpu and my desktop AMD, and my list of packages didnt allow me to have only amd microcode on my desktop and only intel microcode on my laptop. It was annoying to manage, and I wanted something else.

Another example for paru, an AUR package manager, I could not partially modify its config file. When I still was using Arch I wanted paru to use doas instead of sudo, which is a single line change in the config. Since paru stores all its configs in /etc, I would have to save the entire config file (and all its default settings) to save my one change. Unlike other programs I cannot just have custom per user overrides in my ~/.config.

Being declarative

I found my solution in GNU/Guix, a declarative system developed by the GNU project. For those who don't know what a declarative system is, it's an environment where a declarative package manager, provided with a configuration, installs programs with their settings, installs and runs background services, provisions user accounts, and anything else needed by the system. If two machines are provided the same configuration, they will be exactly the same down to the programs installed, services, users, bootloader, etc. Another upside is that the configuration languages are commonly functional programming langauges, allowing the user to specify differences between systems but still share a common base.

Guix is developed by the GNU project and the Free Software Foundation. It uses Guile as its configuration language, Shepherd as its init system, and is fully libre. There is alot to love about Guix. Besides being declarative, Guile is a lisp dialect which I enjoy (functional programming for the win). Its init system is also configured in guile allowing the entire system (packages, users, configuration) along with the code to run services to all be in one place. Being libre has its downside that no binary blobs will be packaged (meaning no drivers), but there is a third-party repo called nonguix that solves this problem.

With Guix I was able to declare everything in two guile scheme modules, one for my system, and one for my home environment. In both I could specify system and user services, packages, and configuration. When applying my custom configuration, Guix will automatically install my desktop environment, wallpapers, my teminal, my neovim configuration, auto run script files, custom CA certificates, and everything else. With a single command I can easially clone my entire system!

As an example, the following scheme defined the users that were on my systems.

(define freya-user-accounts
  (lambda (groups)
    (cons* (user-account
             (name "freya")
             (comment "Freya Murphy")
             (uid 1000)
             (group "users")
             (shell (file-append zsh "/bin/zsh"))
             (home-directory "/home/freya")
             (create-home-directory? #t)
             (supplementary-groups groups))
           %base-user-accounts)))

Packages can be defined...

(define-public %freya-packages
  (append
    (specifications->packages (list ; video audio
                                    "mesa"
                                    "mesa-utils"
                                    ; terminal
                                    "alsa-utils"
                                    "vim"
                                    "neovim"
                                    ; .... and so on
                                    ))))

Services can be defined...

(define-public %freya-services
  (append
    ;; append needed base services
    (list ; mtp
          (simple-service 'mtp udev-service-type (list libmtp))
          ; polkit
          polkit-wheel-service
          ; font config
          fontconfig-file-system-service
          ; networking
          (service ntp-service-type)
          (service network-manager-service-type)
          (service wpa-supplicant-service-type)
          (service modem-manager-service-type)
          (service usb-modeswitch-service-type)
          ; dbus
          (service upower-service-type)
          (service polkit-service-type)
          (service pam-limits-service-type)
          (service elogind-service-type)
          (service dbus-root-service-type)
          ; openssh
          (service openssh-service-type
                   (openssh-configuration
                     (authorized-keys
                       `(("freya" ,(local-file "../../files/keys/freya-ssh.pub"))
                         ("root" ,(local-file "../../files/keys/freya-ssh.pub"))))
                     (permit-root-login #t)
                     (allow-empty-passwords? #t)
                     (password-authentication? #f)
                     (public-key-authentication? #t)
                     (x11-forwarding? #t)
                     (allow-tcp-forwarding? #t))))
    ;; append guix base services
    (modify-services %base-services
      (guix-service-type config =>
        (guix-configuration
          (inherit config)
          (substitute-urls
            (append (list "https://substitutes.nonguix.org"
                          "https://substitutes.freya.cat")
                    %default-substitute-urls))
          (authorized-keys
            (append (list (local-file "../../files/keys/nonguix.pub")
                          (local-file "../../files/keys/sakura.pub"))
                    %default-authorized-guix-keys)))))))

Not all grass was greener

So there was a lot great about Guix. I could have my entire system configured and deployed in one place. Guix is also libre supporting real free and open source projects. But I ran into a few issues, some that were quite major.

  1. The Guix package manager is really slow

    The guix package manager is used to redeploy the system, pull updates for the channels (guix's name for repositories), load the environment. It does everything and is core to the system. So what sucks about guix is how slow its package manager is. Just to pull down new changes from my guix channels, it could take at least a few minutes. Updating my system could sometimes take 30min to an hour. Anything guix tried to do was slow, and it constantly redoes redundant work when completing multiple tasks in succession. This sucked because anytime I wanted to update my system I was filled with dread.

  2. Very few packages

    The main issue with using software that is used by a very small community is you will run into things just not being supported. With guix, this is packages. Since guix does not expose binaries and shared libraries globally (this is just how declarative systems work) you cannot just download software and built it. With guix and other declarative systems, you have to package the software to get it to run at all.

    Due to this, I had to spend hours packaging software I wanted to use including, but not limited to, UEFI firmware for QEMU, Hyprland, my lock screen, clipboard, gtk themes, and modern versions of pipewire.

    Since I was packaging all this software myself, there were no official binary substitutes avaliable such that I didnt have to build all the software all the time. Instead I had to manage my own build server.

  3. No non-free software

    Do you need to use Discord because all your friends use it? Do you want drivers to run a functional computer? Well if you asked those to questions GNU, GNU would tell you to get better friends and get a better computer. I'm sorry but im just not going to do that. Unlike other distrobutions that hide non-free software behind a flag, GNU just doesnt support it. At all. Nada.

    I did mention earlier abou nonguix, a third-party repository, which packageseverything everything I just mentioned. Its really good, but I wasnt super comfortable relying on a super small team for a set of packages that I relied on daily.

  4. Documentation and Support

    The biggest issue I had with guix was their documentation and support, or the lack there of. In the standard GNU fassion, the support they offer is "read the fucking documentation" (RTFM). This is fine if the documentation is good. With guix its not.

    You would be lucky to find something in guix documented. You would be even luckier if the documentation was any good. With guix, the best place to figure how to use the system is IRC chat logs, mailing list archives, reading other peoples dotfiles, and reading the guix source code.

NixOS

NixOS is another declarative system that is much older, more widly used, and better supported then GNU/Guix. In fact, guix is a hard-fork of Nix. The major two differences between nix and guix is how they are configured (the language used), and the init system. Unlike how guix uses guile and shepherd, nix uses nix (the language), and systemd.

For a while when using guix, I also used nix on the side for a few packages. Guix didn't have some packages I wanted such as firefox (non GNUd version), starship prompt, discord and element (they were broken using the guix packages), and rust (rust-analyzer was broken using the guix package). Guix and nix both support installing a home environment ontop of any distrobution, not just their own system environments. So for a while when using guix, I was already relying in nix for part of my setup. When using nix there were a few things I noticed. The package manager was way faster, an order of magnitude faster then guix's. Also there were alot more software that was packaged, and packaged properly. On guix I ran into software that sometimes was just broken, and thats probably just to the much smaller community and team working on and maintaining guix.

So a thought appeared that I could not get out of my head for a while. If not is faster (solves problem #1), software is packaged and works (#2 & #3) why not switch? I pondered this for a while, but what really hit the nail in the coffin was nix's superior documentation. Nix has a much bigger community meaning that if I ran into an issue it would be alot easier to solve. I wasnt and am still not a super huge fan of systemd and the nix programming language (not the nix package manager), I pulled the lever and switched to NixOS.

For about two months now I have been in nix. Its alot faster and quicker to use. Updates and pulling down changes are alot faster and efficient. It is quite rare for software to not be packaged. And nix also supports proprietary if you choose to use that. There is alot about guix that I love, but I ran into too many problems. I am able to have my declarative system with nix without the hassle of guix.

You can see my guix configuration here and my nix configuration here. If you are trying to learn or switch to either system, you can use them as a good resource. You can also view the guix repository I created called sakura when I had to package things. If you need a recommendation to use either GUIX or NixOS, from someone who used Guix for two years, use Nix.

Comments

No comments

New comment: