dotfiles/Guix.org

9.3 KiB

Guix

GNU Guix is (1) a transactional package manager and (2) a GNU/Linux distribution.

My personal selling points are declarative package configuration and transactional upgrades.

References:

Profiles

A profile is way to group Guix packages. Amongst many advantages, profiles can be defined by manifests, which in turn can be stored in VCS.

References:

Activate profiles

A script to activate guix profiles. Usage:

activate-profiles [profile1] [profile2] ...

Source: David Wilson's config

GREEN='\033[1;32m'
RED='\033[1;30m'
NC='\033[0m'
GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles

profiles=$*
if [[ $# -eq 0 ]]; then
    profiles="$HOME/.config/guix/manifests/*.scm";
fi

for profile in $profiles; do
  # Remove the path and file extension, if any
  profileName=$(basename $profile)
  profileName="${profileName%.*}"
  profilePath="$GUIX_EXTRA_PROFILES/$profileName"
  manifestPath=$HOME/.config/guix/manifests/$profileName.scm

  if [ -f $manifestPath ]; then
    echo
    echo -e "${GREEN}Activating profile:" $manifestPath "${NC}"
    echo

    mkdir -p $profilePath
    guix package --manifest=$manifestPath --profile="$profilePath/$profileName"

    # Source the new profile
    GUIX_PROFILE="$profilePath/$profileName"
    if [ -f $GUIX_PROFILE/etc/profile ]; then
        . "$GUIX_PROFILE"/etc/profile
    else
        echo -e "${RED}Couldn't find profile:" $GUIX_PROFILE/etc/profile "${NC}"
    fi
  else
    echo "No profile found at path" $profilePath
  fi
done

Update profiles

A script to update Guix profiles. Usage:

update-profiles [profile1] [profile2] ...

Source: once again, David Wilson's config.

GREEN='\033[1;32m'
NC='\033[0m'
GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles

profiles=$*
if [[ $# -eq 0 ]]; then
    profiles="$GUIX_EXTRA_PROFILES/*";
fi

for profile in $profiles; do
  profileName=$(basename $profile)
  profilePath=$GUIX_EXTRA_PROFILES/$profileName

  echo
  echo -e "${GREEN}Updating profile:" $profilePath "${NC}"
  echo

  guix package --profile="$profilePath/$profileName" --manifest="$HOME/.config/guix/manifests/$profileName.scm"
done

Channels

Specifying additional channels.

References:

(cons*
 (channel
  (name 'channel-q)
  (url "file:///home/pavel/Code/channel-q"))
 (channel
  (name 'nonguix)
  (url "https://gitlab.com/nonguix/nonguix"))
 %default-channels)

Systems

Configuring systems with Guix.

Base configuration

The base configuration is shared between all the machines.

While it's possible to make a single .scm file with base confguration and load it, I noticed that it produces more cryptic error messages wherever there is an error in the base file, so I opt in for noweb.

guix system invocation is as follows:

sudo -E guix system reconfigure ~/.config/guix/systems/[system].scm

Common modules:

(use-modules (gnu))
(use-modules (gnu system nss))
(use-modules (gnu packages certs))
(use-modules (gnu packages version-control))
(use-modules (gnu packages vim))
(use-modules (gnu packages wm))
(use-modules (gnu packages openbox))
(use-modules (nongnu packages linux))
(use-modules (nongnu system linux-initrd))

(use-service-modules desktop networking ssh xorg)
(use-package-modules ssh)

In principle, we could define a variable called base-operating-system and extend it in ancestors. However, then we would have to define mandatory fields like host-name, bootloader with dummy values. Since I'm already using noweb, there is little point.

The following code will be inserted in the top of the operating-system definition.

;; Use the full Linux kernel
(kernel linux)
(initrd microcode-initrd)
(firmware (list linux-firmware))
(locale "en_US.utf8")
(timezone "Europe/Moscow")

;; US/RU keyboard layout
(keyboard-layout (keyboard-layout "us,ru" #:options '("grp:alt_shift_toggle")))

;; User accounts
(users (cons* (user-account
               (name "pavel")
               (comment "Pavel")
               (group "users")
               (home-directory "/home/pavel")
               (supplementary-groups
                '("wheel"  ;; sudo
                  "netdev" ;; network devices
                  "audio"
                  "video"
                  "input"
                  "tty"
                  ;; "docker"
                  "lp")))
              %base-user-accounts))

;; Base packages
(packages
 (append
  (list nss-certs
	    git
        i3-gaps
        openbox
	    vim)
  %base-packages))

;; Services
(services
 (append
  (list (service openssh-service-type)
        (set-xorg-configuration
         (xorg-configuration
          (keyboard-layout keyboard-layout))))
  %desktop-services))

blue

A VM on which I test Guix. Will probably be deleted sooner or later.

<<system-common>>

(operating-system
  <<system-base>>
 (host-name "blue")

 (bootloader
  (bootloader-configuration
   (bootloader grub-bootloader)
   (target "/dev/sda")
   (keyboard-layout keyboard-layout)))

 (swap-devices
  (list (uuid "d9ca4f8b-4bb1-420e-9371-3558731bada1")))

 (file-systems
  (cons* (file-system
          (mount-point "/")
          (device
           (uuid "179fbd75-3c7f-4de2-8c4f-4c30939b8a3f"
                 'ext4))
          (type "ext4"))
         %base-file-systems)))

Notes on installing software

Category Guix dependency Description
dev patchelf A program to modify existsing ELF executables
dev glibc A lot of stuff, including ELF interpeter and ldd

wakatime-cli

Note Description
TODO Package this for Guix

Before I figure out how to package this for Guix:

  • Clone the repo
  • Run go build
  • Copy the binary to the ~/bin folder

ActivityWatch

Note Description
TODO Package this for Guix

The official binaries work just fine after some patching, except for the aw-qt binary.

Properly building from source is more awkward (PyInstaller? Are you serious? xD), as there are multiple packages with lots of dependencies.

The patching is as follows:

  • Get ELF interpeter patch from guix build glibc, after which patch ELF interpeter path for the required binaries, e.g.:
patchelf --set-interpreter /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 aw-qt
patchelf --set-interpreter /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 aw-server/aw-server
patchelf --set-interpreter /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 aw-server-rust/aw-server-rust
patchelf --set-interpreter /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 aw-watcher-afk/aw-watcher-afk
patchelf --set-interpreter /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 aw-watcher-window/aw-watcher-window

Add libz to RPATH

Category Guix dependency
misc zlib
patchelf --set-rpath /gnu/store/rykm237xkmq7rl1p0nwass01p090p88x-zlib-1.2.11/lib/ aw-qt
patchelf --set-rpath /gnu/store/rykm237xkmq7rl1p0nwass01p090p88x-zlib-1.2.11/lib/ aw-server/aw-server
patchelf --set-rpath /gnu/store/rykm237xkmq7rl1p0nwass01p090p88x-zlib-1.2.11/lib/ aw-server-rust/aw-server-rust
patchelf --set-rpath /gnu/store/rykm237xkmq7rl1p0nwass01p090p88x-zlib-1.2.11/lib/ aw-watcher-afk/aw-watcher-afk
patchelf --set-rpath /gnu/store/rykm237xkmq7rl1p0nwass01p090p88x-zlib-1.2.11/lib/ aw-watcher-window/aw-watcher-window

As aw-qt doesn't work properly, and the only thing it does is makes a tray icon anyhow, here is a script to launch the required components:

~/Programs/activitywatch/aw-server/aw-server &
~/Programs/activitywatch/aw-watcher-afk/aw-watcher-afk &
~/Programs/activitywatch/aw-watcher-window/aw-watcher-window &