12 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 'flat)
(url "https://github.com/flatwhatson/guix-channel.git"))
(channel
(name 'channel-q)
(url "https://github.com/SqrtMinusOne/channel-q.git"))
(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 whenever 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 xorg))
(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
xterm
vim)
%base-packages))
;; Services
(services
(append
(list (service openssh-service-type)
(set-xorg-configuration
(xorg-configuration
(keyboard-layout keyboard-layout))))
%desktop-services))
azure
azure is a Lenovo Ideapad 330 laptop.
<<system-common>>
(operating-system
<<system-base>>
(host-name "azure")
(bootloader
(bootloader-configuration
(bootloader grub-efi-bootloader)
(target "/boot/efi")
(keyboard-layout keyboard-layout)))
(swap-devices
(list (uuid "4b2dedb3-b111-4e69-8c05-6daa2b072c76")))
(file-systems
(cons* (file-system
(mount-point "/")
(device (file-system-label "my-root"))
(type "ext4"))
(file-system
(mount-point "/boot/efi")
(device "/dev/sda1")
(type "vfat"))
%base-file-systems)))
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)))
System installation
Preparation
In my cases the provided ISO doesn't work because of Libre kernel.
Fortunately, David Wilson has made a repository with a toolchain to make an ISO with the full kernel. In case it won't be an option, the nonguix repo also has instructions on how to do that.
When an ISO is there, we have to write it on a USB stick. Run sudo fdisk -l to get a list of disks.
The approach in the official instruction is to create a bootable USB with dd:
sudo dd of=/dev/sdxX if=<path-to-iso> status=progress && sync
However, I couldn't make it work for some strange reason. Fortunately, gnome-disk-utility was able to produce a bootable USB.
Installation
Going further, the official instructions for installation & SystemCrafters wiki entry are pretty good, so it's not necessary to repeat them here.
After installation
After the installation, the strategy is as follows.
Set a password for the main user (pavel). Login with openbox to get a tolerable interface, because i3 default config is horrible.
Clone the dotfiles repo:
mkdir Code cd Code git clone https://github.com/SqrtMinusOne/dotfiles.git
Copy the channels file and run guix pull:
cp ~/Code/dotfiles/.config/guix/channels.scm ~/.config/guix guix pull
The first pull usually takes a while. After that install yadm and pull dotfiles:
guix install yadm guix clone https://github.com/SqrtMinusOne/dotfiles.git
And activate the required profiles. Again, downloading & building Emacs, Starship and stuff will take a while.
Don't forget to install JetBrainsMono Nerd Font.
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
~/binfolder
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 &