;; This is an operating system configuration file for a fairly minimal ;; "desktop" setup with i3 where the /home partition partition is ;; encrypted with LUKS. ;; ;; https://guix.gnu.org/manual/en/html_node/operating_002dsystem-Reference.html (define-module (tw system frm) #:use-module (gnu) #:use-module (gnu bootloader grub) #:use-module (gnu system locale) #:use-module (gnu system nss) #:use-module (guix gexp) #:use-module (guix packages) #:use-module ((nongnu packages linux) #:prefix nongnu:) ; don't interfere with (gnu packages linux) #:use-module ((nongnu system linux-initrd) #:prefix nongnu:) #:use-module (tw channels) #:use-module (tw packages scanner) #:use-module (tw services secrets) #:use-module (tw services wireguard) #:use-module (tw system)) (use-package-modules android certs cups disk docker file-systems gnome guile kerberos linux mtools pulseaudio search shells tls wm xorg) (use-service-modules admin authentication avahi base cups dbus desktop docker kerberos linux mcron networking pm shepherd syncthing vpn xorg) (define efi-system-partition ; /dev/nvme0n1p1 (uuid "D8C7-2624" 'fat)) (define root-partition ; /dev/nvme0n1p2 (uuid "62fb4710-33d1-4eaf-aaaa-43d16ab26a58" 'btrfs)) (define touchpad-xorg-config (@@ (tw system lap) touchpad-xorg-config)) (define set-timezone-script (@@ (tw system lap) set-timezone-script)) (define custom-xorg-config (xorg-configuration (keyboard-layout %british-keyboard) (extra-config (list touchpad-xorg-config)))) (define-public %frm-system (operating-system (host-name "frm.twilken.net") (timezone "Europe/Paris") (locale "en_GB.utf8") (locale-definitions (list (locale-definition (name "en_GB.utf8") (source "en_GB")) (locale-definition (name "en_US.utf8") (source "en_US")) (locale-definition (name "fr_FR.utf8") (source "fr_FR")))) ;; Allow resolution of '.local' host names with mDNS. (name-service-switch %mdns-host-lookup-nss) ;; Choose UK English X11 keyboard layout. (keyboard-layout %british-keyboard) ;; Use the UEFI variant of GRUB with the EFI System ;; Partition mounted on /boot/efi. (bootloader (bootloader-configuration (bootloader grub-efi-bootloader) (targets '("/boot/efi")) ;; Note: keyboard-layout is ignored by non-grub bootloaders. (keyboard-layout keyboard-layout))) ;; Use non-free kernel to load non-free firmware (e.g. for wifi). (kernel nongnu:linux) (initrd nongnu:microcode-initrd) (firmware (cons* nongnu:amdgpu-firmware ; TODO: wifi firmware? %base-firmware)) (file-systems (cons* (file-system (device root-partition) (mount-point "/") (flags '(no-atime)) (options (alist->file-system-options '("ssd" ("compress" . "zstd")))) (type "btrfs")) (file-system (device efi-system-partition) (mount-point "/boot/efi") (flags '(no-atime)) (type "vfat")) ;; Put /home in a subvolume for better accounting/snapshotting potential. (file-system (device root-partition) (mount-point "/home") (flags '(no-atime)) (options (alist->file-system-options '("ssd" ("compress" . "zstd") ("subvol" . "home")))) (type "btrfs")) %base-file-systems)) ;; Members of the wheel group are allowed to use sudo. (users (cons* (user-account (name "timo") (comment "Timo Wilken") (group "users") (supplementary-groups '("wheel" "audio" "video" "docker" "adbusers")) (shell (file-append zsh "/bin/zsh"))) %base-user-accounts)) (sudoers-file (plain-file "sudoers" (string-append ;; We need to preserve $TERMINFO so that programs under sudo can ;; find kitty's terminfo files. This is possibly unsafe; sudo ;; explicitly deletes this variable by default. "Defaults env_keep += \"TERMINFO\"\n" (plain-file-content %sudoers-specification) ;; In addition to the default rules, allow admins to power off ;; the computer. They'll have to use the system binaries, not ;; those from their user profile, as /etc/sudoers requires ;; absolute paths to commands. "%wheel ALL=(ALL) NOPASSWD: " "/run/current-system/profile/sbin/halt, " "/run/current-system/profile/sbin/reboot, " "/run/current-system/profile/sbin/shutdown\n"))) ;; This is where we specify system-wide packages. (packages (cons* ;; System stuff cups docker mit-krb5 ;; File systems dosfstools mtools ntfs-3g ;; Desktop and drivers ;; FIXME: lightdm depends on python-2, but the build throws an ;; error that python2 is not supported. ;; TODO: Does lightdm have a service I need to enable? ;;lightdm lightdm-gtk-greeter pulseaudio xf86-video-amdgpu ;; Adds /sys/class/backlight entries for external monitors. ;; Not needed for laptop display. ;; ddcci-driver-linux i3-gaps ; install i3 here so gdm can see its xsession file i3lock ; we need a system service to make i3lock setuid root ;; We need to install gnome-keyring here so its PAM module is ;; enabled properly (by its service; see below). ;; nheko needs gnome-keyring to store secrets (kwallet doesn't do dbus). gnome-keyring ;; It's probably easiest to install geoclue system-wide, so it ;; gets added to `%desktop-services' and redshift can access the ;; location. geoclue ;; Base packages %base-system-packages)) ;; Use the "desktop" services, which include the X11 ;; log-in service, networking with NetworkManager, and more. ;; See info '(guix)Services' for useful services. (services (cons* (service syncthing-service-type (syncthing-configuration (user "timo"))) (service cups-service-type (cups-configuration (web-interface? #t) (default-shared? #f) ;; See info '(guix)Printing Services' for more extensions. (extensions (list cups-filters foomatic-filters brlaser)))) (service bluetooth-service-type) (service tw-wireguard-service-type (tw-wireguard-configuration (this-host host-name))) (service docker-service-type (docker-configuration)) (service krb5-service-type (krb5-configuration (default-realm "CERN.CH") (rdns? #f) (realms (list (krb5-realm (name "CERN.CH") (default-domain "cern.ch") (kdc "cerndc.cern.ch")))))) (service tlp-service-type (tlp-configuration)) ; TODO: configure properly (service thermald-service-type (thermald-configuration (adaptive? #t))) (service earlyoom-service-type (earlyoom-configuration)) ; TODO: configure at least `avoid-regexp' (service fprintd-service-type) ;; Install i3lock as a setuid binary, so it can talk to PAM. (service screen-locker-service-type (screen-locker-configuration (name "i3lock") (program (file-append i3lock "/bin/i3lock")))) ;; gnome-keyring is not in `%desktop-services' by default, ;; but needs to be there to add itself to /etc/pam.d/. ;; If using a DM other than GDM, add it to `pam-services' in ;; `gnome-keyring-configuration' (see its docs). (service gnome-keyring-service-type (gnome-keyring-configuration)) (udev-rules-service 'android android-udev-rules #:groups '("adbusers")) (set-xorg-configuration custom-xorg-config) (service unattended-upgrade-service-type (unattended-upgrade-configuration (schedule "0 21 * * *") ; every night at 21:00, when the laptop is turned on (maximum-duration (* 40 60)) ; 40 minutes to allow for slow downloads (channels %system-channels) (operating-system-expression #~(@ (tw system frm) %frm-system)) (services-to-restart ;; Anything that won't cause disruption when restarting. '(syncthing-timo earlyoom thermald tlp wireguard-wg0 mcron)))) (simple-service 'disk-maintenance mcron-service-type ;; I don't think jobs run on boot if they would have run when the ;; computer was turned off, so choose a time when the computer is ;; probably turned on. (list #~(job "45 21 * * *" "guix gc -d 2w -F 25G") ; after unattended-upgrade #~(job "0 22 * * *" ; after guix gc (string-append #$(file-append util-linux "/sbin/fstrim") " --fstab --verbose")))) (extra-special-file "/etc/NetworkManager/dispatcher.d/09-set-timezone" (program-file "set-timezone" set-timezone-script)) (simple-service 'scanning-services shepherd-root-service-type (list (shepherd-service (documentation "Expose USB scanners over IPP.") (provision '(ipp-usb)) (requirement '(networking)) ; only on localhost, though (start #~(make-forkexec-constructor (list #$(file-append ipp-usb "/bin/ipp-usb") "standalone"))) (stop #~(make-kill-destructor))))) ;; Since Guix 953c65ffdd4, build-machines can be directly specified in ;; `guix-configuration'. However, this doesn't allow the dynamic ;; selection of build machines as is done here. (extra-special-file "/etc/guix/machines.scm" (scheme-file "machines.scm" #~(let ((lud (build-machine (name "lud.twilken.net") (systems '("x86_64-linux")) (port '#$(assoc-ref %ssh-ports "lud.twilken.net")) (host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGqXbxv3a2bZyGjnEirVCMtRBeLKW/ha8ULSR9Xye4Z1") (user "timo") (private-key "/home/timo/.local/share/ssh-keys/id_rsa") (speed 1/3))) ; 4 cores, 16 GB RAM (vin (build-machine (name "vin.twilken.net") (systems '("x86_64-linux")) (port '#$(assoc-ref %ssh-ports "vin.twilken.net")) (host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEEpdfKxzoCwg53TKPF5YxgUwhGF+bELAyBGdxagQroJ") (user "timo") (private-key "/home/timo/.local/share/ssh-keys/id_rsa") (speed 2/3)))) ; 8 cores, 16 GB RAM (use-modules (ice-9 popen) (ice-9 textual-ports) (ice-9 regex)) (let* ((regexp (make-regexp "^GENERAL\\.CONNECTION:[[:space:]]+TLAN$" regexp/newline)) (pipe (open-pipe* OPEN_READ #$(file-append network-manager "/bin/nmcli") "device" "show" "wlp3s0")) (at-home? (regexp-exec regexp (get-string-all pipe)))) (close-pipe pipe) ;; Only offload to vin when at home, as the network connection is too bad otherwise. (if at-home? (list vin) (list lud)))))) ;; Set up a secrets config for WireGuard to extend. (service secrets-service-type (secrets-configuration (host-key "/etc/secrets.key"))) ; we have no SSH host keys, so use a custom key (modify-services (append %system-channel-services %desktop-services) ;; Let sane find the airscan backend. ipp-usb needs to be running separately. (sane-service-type _ => sane-backends/airscan) (gdm-service-type config => (gdm-configuration (inherit config) (auto-login? #f) (default-user "timo") (xorg-configuration custom-xorg-config))) (geoclue-service-type config => (geoclue-configuration (inherit config) (applications (cons* (geoclue-application "redshift" #:system? #f) %standard-geoclue-applications)))) (login-service-type config => (login-configuration (inherit config) (motd (plain-file "no-motd" "")) (allow-empty-passwords? #f)))))))) %frm-system