Guix uses channels which are basically git repositories containing Guile files defining Guix packages that can be installed on your system.
As my current laptop uses a WiFi chip which doesn’t have a supported libre driver and Guix is a free system so we have to add the nonguix channel to use the non-free Linux kernel.
(define nonguix
(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")))))
Also add the signing key to sign the Nonguix substitute server.
(public-key
(ecc
(curve Ed25519)
(q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#)))
rde is an extension on top of Guix home which adds additional services for configuring the home environment and operating system.
(define rde
(channel
(name 'rde)
(url "https://git.sr.ht/~abcdw/rde")
(introduction
(make-channel-introduction
"257cebd587b66e4d865b3537a9a88cccd7107c95"
(openpgp-fingerprint
"2841 9AC6 5038 7440 C7E9 2FFA 2208 D209 58C1 DEB0")))))
Return all the channels including the base channels which has the main Guix channel.
(cons* nonguix
rde
%default-channels)
This configuration is (will be) shared between different computers and as such they share the same base services, packages, and system.
(define-module (jayu build system base)
#:use-module (gnu)
#:use-module (gnu packages)
#:use-module (gnu system)
#:use-module (gnu packages bash)
#:use-module (gnu packages shells))
Define some basic system agnostic packages to include in all machines.
(define-public jayu-base-packages
(append
(map (compose list specification->package+output)
'("curl" "dbus" "emacs" "gash" "git" "gnupg"
"guile-readline" "make" "ncurses" "nss-certs" "openssh"
"wget" "vim" "xdg-user-dirs" "xdg-utils"
"docker" "docker-cli" "docker-compose" "containerd"))
%base-packages))
Define a service which adds coreutils to /usr/bin/env
,
Bash to /bin/bash
, and Dash to /bin/sh
.
(define-public jayu-file-services
(list
(extra-special-file "/usr/bin/env"
(file-append coreutils "/bin/env"))
(extra-special-file "/bin/zsh"
(file-append zsh "/bin/zsh"))
(extra-special-file "/bin/bash"
(file-append bash "/bin/bash"))
(extra-special-file "/bin/sh"
(file-append dash "/bin/dash"))))
Allow inbound connection on port 9090.
(use-modules (gnu services networking))
(define-public jayu-port-services
(list
(service iptables-service-type
(iptables-configuration
(ipv4-rules (plain-file "iptables.rules" "*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
-A INPUT -p tcp --dport 9090 -j ACCEPT
COMMIT
"))))))
Combine services into base services.
(define-public jayu-base-services
(append
jayu-port-services
jayu-file-services))
Define a list of users which will be on all machines.
(define jayu-users
(list
(user-account
(name "nouun")
(comment "nouun")
(home-directory "/home/nouun")
(group "users")
(supplementary-groups
'("wheel" "netdev" "audio" "video"))
(shell (file-append bash "/bin/bash")))))
(define-public jayu-base-users
(append
jayu-users
%base-user-accounts))
Define a base system which is inherited and updated in each specific machine configuration.
(define-public jayu-base-system
(operating-system
(locale "en_NZ.utf8")
(timezone "Pacific/Auckland")
(host-name "guix")
(users jayu-base-users)
(packages jayu-base-packages)
(services jayu-base-services)
(bootloader
(bootloader-configuration
(bootloader grub-efi-bootloader)
(targets (list "/boot/efi"))))
;; Guix requires file-system to be defined to create an operating-system
;; so pass through a dummy file system which will be overriden in each
;; machine configuration.
(file-systems
(cons* (file-system
(mount-point "/")
(device "none")
(type "ext4")
(check? #f))
%base-file-systems))))
Verrb is the configuration that is used on my Macbook Pro. Being an Apple Macbook, it uses a nonfree WiFi chip and as such, the non-free Linux kernel and b43 firmware are required to get WiFi working.
(define-module (jayu build system systems verrb)
#:use-module (gnu)
#:use-module (gnu packages bash)
#:use-module (gnu packages firmware)
#:use-module (gnu packages messaging)
#:use-module (gnu system)
#:use-module (gnu services desktop)
#:use-module (gnu services dns)
#:use-module (gnu services networking)
#:use-module (gnu services messaging)
#:use-module (gnu services sddm)
#:use-module (gnu services ssh)
#:use-module (gnu services web)
#:use-module (gnu services xorg)
#:use-module (guix download)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix store)
#:use-module (srfi srfi-1)
; Nonfree packages: linux, b43-firmware
#:use-module (nongnu packages linux)
#:use-module (jayu packages nonfree)
#:use-module (jayu build system base)
#:use-module (jayu packages display-managers)
#:use-module (jayu packages extras)
#:use-module (jayu packages rust-apps))
Define packages specific to Verrb. alsa-utils
and
pulseaudio
are used for audio. My AwesomeWM configuration
requires an upstream version, therefore awesome-git
is used
instead of the packaged version included in the Guix repos.
verrb-sddm-theme
is the SDDM theme that I made and use.
(define verrb-packages
(append
(list awesome-git
adverrb-sddm-theme)
(map (compose list specification->package+output)
'("alsa-utils" "pulseaudio"))
jayu-base-packages))
This will install SDDM as the display manager and use the verrb theme.
(define verrb-sddm-service
(service sddm-service-type
(sddm-configuration
(theme "adverrb"))))
Setup the udev rules needed for flashing keyboards through QMK without needing to run as root every time.
(define verrb-qmk-udev-service
(udev-rules-service 'qmk
(file->udev-rule
"50-qmk.rules"
(let ((version "2d71ac7541e81ae4313cecc7e7597d45f9a96809"))
(origin
(method url-fetch)
(uri (string-append "https://raw.githubusercontent.com/qmk/"
"qmk_firmware/" version "/util/udev/50-qmk.rules"))
(sha256
(base32 "0ks0z4pyg9aq971n5zbbrk4psj21r6pfs1gxqjq2izmb3zrz94j6")))))))
Enable Bitlbee and install the Discord plugin so we can interact with Discord without having to use the bloated electron client.
(define verrb-bitlbee-service
(service bitlbee-service-type
(bitlbee-configuration
(plugins
(list bitlbee-discord)))))
Enable Nix support for those few packages I cannot be bothered packaging.
(use-service-modules nix)
(define verrb-nix-service
(service nix-service-type))
Modify the default desktop services to do the following:
- Remove GDM as SDDM is used instead.
- Allow changing backlight without root.
- Set Guix to always use 4 cores.
- Set power button suspend instead of shutdown.
- Stop network-manager from modifying /etc/resolve.conf
To use the Nonguix substitute server, we need to modify the guix service and add the substitute server as well as the signing key.
(define verrb-desktop-services
(cons*
(udev-rules-service 'backlight
(udev-rule
"backlight.rules"
(string-append
"ACTION==\"add\", "
"SUBSYSTEM==\"backlight\", "
"KERNEL==\"intel_backlight\", "
"RUN+=\"/run/current-system/profile/bin/chgrp video /sys/class/backlight/%k/brightness\""
"\n"
"ACTION==\"add\", "
"SUBSYSTEM==\"backlight\", "
"KERNEL==\"intel_backlight\", "
"RUN+=\"/run/current-system/profile/bin/chmod g+w /sys/class/backlight/%k/brightness\""
"\n")))
(modify-services
(remove (lambda (service)
(eq? (service-kind service) gdm-service-type))
%desktop-services)
(guix-service-type
config => (guix-configuration
(inherit config)
(extra-options '("--max-job=4"))
(substitute-urls
(append %default-substitute-urls
(list "https://substitutes.nonguix.org")))
(authorized-keys
(append %default-authorized-guix-keys
(list (local-file "../../nonguix-key.pub"))))))
(elogind-service-type
config => (elogind-configuration
(inherit config)
(handle-power-key 'suspend)))
(network-manager-service-type
config => (network-manager-configuration
(inherit config)
(dns "none"))))))
Append all services into a single list.
(define verrb-services
(append
(list verrb-sddm-service
verrb-qmk-udev-service
verrb-bitlbee-service
verrb-nix-service)
verrb-desktop-services
jayu-file-services))
Mount root and boot partitions.
(define verrb-file-system
(cons* (file-system
(mount-point "/")
(device
(uuid "e66d5096-1a1a-420d-92f0-b01cf7d103ea"
'ext4))
(type "ext4"))
(file-system
(mount-point "/boot/efi")
(device (uuid "A23F-3C5F" 'fat32))
(type "vfat"))
%base-file-systems))
Return a new operating system which inherits the
jayu-base-system
created in the base configuration and
passes through the variables we’ve already defined. As
mentioned at the start, this machine requires the
non-free Linux kernel and b43-firmware so we also set
those.
(operating-system
(inherit jayu-base-system)
(host-name "verrb")
(users jayu-base-users)
(file-systems verrb-file-system)
(packages verrb-packages)
(services verrb-services)
(kernel linux)
(firmware (list b43-firmware)))
Pronouun is the configuration that is used on the server which hosts my website and git frontend.
(define-module (jayu build system systems pronouun)
#:use-module (gnu)
#:use-module (gnu packages bash)
#:use-module (gnu packages firmware)
#:use-module (gnu packages messaging)
#:use-module (gnu system)
#:use-module (gnu services dns)
#:use-module (gnu services networking)
#:use-module (gnu services messaging)
#:use-module (gnu services ssh)
#:use-module (gnu services web)
#:use-module (guix store)
#:use-module (srfi srfi-1)
#:use-module (jayu build system base))
Define packages specific to Pronouun.
(use-package-modules certs tls)
(define pronouun-packages
(append
(list nss-certs
certbot)
jayu-base-packages))
Mainly just git and website services
Git Daemon
(use-service-modules version-control)
(define pronouun-git-daemon-service
(service git-daemon-service-type))
; (git-daemon-configuration)))
; (base-path "/home/git/repositories/"))))
Fast CGI
(define pronouun-fcgi-service
(service fcgiwrap-service-type))
Git frontend
(use-service-modules cgit)
(use-package-modules version-control)
(define (cert-path host file)
(format #f "/etc/letsencrypt/live/~a/~a.pem"
host (symbol->string file)))
(define pronouun-cgit-nginx-configuration
(nginx-server-configuration
(root cgit)
(server-name '("git.nouun.dev"
"www.git.nouun.dev"))
(listen '("80"))
(locations
(list
(nginx-location-configuration
(uri "@cgit")
(body '("fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;"
"fastcgi_param PATH_INFO $uri;"
"fastcgi_param QUERY_STRING $args;"
"fastcgi_param HTTP_HOST $server_name;"
"fastcgi_pass 127.0.0.1:9000;")))))
(try-files (list "$uri" "@cgit"))
(ssl-certificate (cert-path "git.nouun.dev"
'fullchain))
(ssl-certificate-key (cert-path "git.karl.hallsby.com"
'privkey))))
(define pronouun-cgit-service
(service cgit-service-type
(cgit-configuration
(enable-commit-graph? #t)
(enable-html-serving? #t)
(repository-directory "/home/cgit/repositories")
(nocache? #t)
(nginx
(list
pronouun-cgit-nginx-configuration)))))
nginx
(use-service-modules web)
(define pronouun-website-nginx-configuration
(nginx-server-configuration
(server-name '("nouun.dev"
"www.nouun.dev"))
(listen '("80"))))
;(ssl-certificate (cert-path "git.nouun.dev"
; 'fullchain))
;(ssl-certificate-key (cert-path "git.karl.hallsby.com"
; 'privkey))))
(define pronouun-nginx-service
(service nginx-service-type
(nginx-configuration
(server-blocks
(list pronouun-website-nginx-configuration)))))
certbot
(use-service-modules certbot)
(define pronouun-certbot-nginx-deploy-hook
(program-file
"nginx-deploy-hook"
#~(let ((pid (call-with-input-file "/var/run/nginx/pid" read)))
(kill pid SIGHUP))))
(define pronouun-certbot-service
(service certbot-service-type
(certbot-configuration
(email "[email protected]")
(certificates
(list
(certificate-configuration
(name "Website")
(domains '("nouun.dev"
"www.nouun.dev"))
(deploy-hook
pronouun-certbot-nginx-deploy-hook))
(certificate-configuration
(name "Website")
(domains '("git.nouun.dev"
"www.git.nouun.dev"))
(deploy-hook
pronouun-certbot-nginx-deploy-hook)))))))
dhcp
(use-service-modules networking)
(define pronouun-dhcp-service
(service dhcp-client-service-type))
I use openssh-sans-x
as there is no X11 server setup and
as such, OpenSSH doesn’t need X11 support.
(use-service-modules ssh)
(use-package-modules ssh)
(define pronouun-ssh-service
(service openssh-service-type
(openssh-configuration
(openssh openssh-sans-x)
(password-authentication? #t)
(permit-root-login #f))))
Modify the default base services to do the following:
- Nothing for now
(define pronouun-base-services
(append
jayu-file-services
%base-services))
Append all services into a single list.
(define pronouun-services
(append (list pronouun-git-daemon-service
pronouun-fcgi-service
pronouun-cgit-service
pronouun-nginx-service
pronouun-certbot-service
pronouun-dhcp-service
pronouun-ssh-service)
pronouun-base-services
jayu-file-services))
Users
(define pronouun-users
(list
(user-account
(name "git")
(comment "git")
(home-directory "/home/git")
(group "users")
(supplementary-groups
'("wheel" "netdev" "audio" "video"))
(shell (file-append bash "/bin/bash")))))
Mount root and boot partitions.
(define pronouun-swap
(list (uuid "61c2aeba-85ed-4e02-a227-027ecbd115f0")))
(define pronouun-file-system
(cons* (file-system
(mount-point "/")
(device
(uuid "b2b07395-cfd5-4133-86e2-5538eb0c0406"
'ext4))
(type "ext4"))
%base-file-systems))
Test
(operating-system
(inherit jayu-base-system)
(host-name "pronouun")
(users pronouun-users)
(file-systems pronouun-file-system)
(packages pronouun-packages)
(services pronouun-services)
(bootloader
(bootloader-configuration
(bootloader grub-bootloader)
(targets (list "/dev/vda")))))