;; -*- mode: scheme; -*-
;; This is an operating system configuration template
;; for a "desktop" setup with GNOME and Xfce where the
;; root partition is encrypted with LUKS, and a swap file.
(define-module (config))
(use-modules
(guix gexp)
(nongnu packages linux)
(nongnu system linux-initrd)
(nongnu packages firmware)
(gnu)
(gnu system privilege)
(gnu packages admin)
(gnu system nss)
(guix derivations)
(guix store)
(guix transformations)
(guix monads)
(guix utils)
(guix packages)
(guix build-system gnu)
(guix build-system trivial)
(gnu system accounts)
(ruther services system)
(ruther services bind)
(ruther services nix-gl)
(ruther services nix)
(ruther services auto-login)
(ruther services netbird)
(ruther packages netbird)
(ruther bootloader grub)
(dfsg contrib services tailscale))
(use-service-modules desktop sddm xorg base nix pm virtualization vpn
sound dbus cups containers security-token networking
ssh databases linux docker)
(use-package-modules gnome package-management shells networking wm
vim wget curl bash compression glib
linux embedded finance python-xyz freedesktop
python-build haskell-apps commencement
polkit firmware databases guile security-token
docker base)
(define wireshark-patched
(package/inherit wireshark
(source (origin
(inherit (package-source wireshark))
(patches (cons*
(local-file "patches/wireshark.patch")
(origin-patches (package-source wireshark))))))
(arguments
(substitute-keyword-arguments (package-arguments wireshark)
((#:phases original-phases)
#~(modify-phases #$original-phases
(add-after 'qt-wrap 'unwrap-dumpcap
(lambda _
(delete-file (string-append #$output "/bin/dumpcap"))
(copy-file
(string-append #$output "/bin/.dumpcap-real")
(string-append #$output "/bin/dumpcap"))))))))))
(define %ruther/user
(user-account
(name "ruther")
(comment "Rutherther")
(group "users")
(supplementary-groups '("wheel" "netdev"
"audio" "video"
"libvirt" "dialout"
"kvm" "docker"))
(shell (file-append zsh "/bin/zsh"))))
;; Obsolete, only useful if just part of package's udev rules is desirable
;; (define (ruther/udev-rules-service name package rules-file)
;; (udev-rules-service
;; name
;; (file->udev-rule rules-file
;; (file-append package "/lib/udev/rules.d/" rules-file))))
(define %ruther/udev-services
(list
(udev-rules-service 'kmonad kmonad)
(udev-rules-service 'trezord trezord-udev-rules)
(udev-rules-service 'openocd openocd)
(udev-rules-service
'brightness brightnessctl
#:groups '("video"))
(udev-rules-service
'quartus-usbblaster
(file->udev-rule "51-usbblaster.rules" (local-file "udev/51-usbblaster.rules")))
(udev-rules-service
'pluto-sdr
(file->udev-rule "53-adi-plutosdr-usb.rules" (local-file "udev/53-adi-plutosdr-usb.rules")))
(udev-rules-service
'android
(file->udev-rule "51-android.rules" (local-file "udev/51-android.rules")))
(udev-rules-service
'ftdi
(file->udev-rule "51-ftdi.rules" (local-file "udev/51-ftdi.rules")))))
(define %ruther/container-virt-services
(list
(service containerd-service-type)
(service docker-service-type)
;; (service rootless-podman-service-type
;; (rootless-podman-configuration
;; (subgids
;; (list (subid-range (name "ruther"))
;; (subid-range (name "fbw"))))
;; (subuids
;; (list (subid-range (name "ruther"))
;; (subid-range (name "fbw"))))))
(service libvirt-service-type)
(service qemu-binfmt-service-type
(qemu-binfmt-configuration
(platforms
(lookup-qemu-platforms "arm" "aarch64"
"powerpc" "powerpc64le"
"riscv64" "mips64el"
"i586"))))))
(define %ruther/network-services
(list
(service wireguard-service-type
(wireguard-configuration
(private-key "/etc/wireguard/private.key")
(addresses '("192.168.32.25/32"))
(peers
(list
(wireguard-peer
(name "server")
(endpoint "159.195.49.157:51820")
(keep-alive 25)
(public-key "ZOVjmgUak67kLhNVgZwyb0bro3Yi4vCJbGArv+35IWQ=")
(allowed-ips '("192.168.32.0/24")))))))
(service tailscaled-service-type)
(service netbird-service-type)))
(define %ruther/laptop-gui-essential-services
(list
(service bluetooth-service-type
(bluetooth-configuration
(auto-enable? #t)))
(service cups-service-type
(cups-configuration
(web-interface? #t)))
(service power-profiles-daemon-service-type)
;; (service tlp-service-type
;; (tlp-configuration
;; (tlp-default-mode "BAT")
;; (disk-idle-secs-on-ac 1)
;; (stop-charge-thresh-bat0 80)
;; (start-charge-thresh-bat0 70)
;; (energy-perf-policy-on-ac "normal")
;; (sata-linkpwr-on-ac "medium")
;; (pcie-aspm-on-ac "default")
;; (radeon-power-profile-on-ac "mid")
;; (cpu-energy-perf-policy-on-ac "balance_power")
;; (cpu-energy-perf-policy-on-bat "power")))
(service screen-locker-service-type
(screen-locker-configuration
(name "swaylock")
(program (file-append swaylock "/bin/swaylock"))
(using-pam? #t)
(using-setuid? #f)))
;; For starting blueman mechanism.
;; It needs privileges, so cannot be started from a user dbus session.
(simple-service 'dbus-blueman
dbus-root-service-type
(list blueman))))
(define crypted-root
(mapped-device
(source (uuid "55787ccb-decb-46b6-a190-6597dff68c68"))
(target "cryptedguix")
(type luks-device-mapping)))
(define root-file-system
(file-system
(device (file-system-label "guix-root"))
;; (device "/dev/mapper/cryptedguix")
(mount-point "/")
(type "ext4")
(dependencies (list crypted-root))))
(define %ruther/base-laptop-os
(operating-system
(kernel linux-7.2)
(kernel-arguments
(cons* "amdgpu.dcdebugmask=0x10"
%default-kernel-arguments))
(initrd microcode-initrd)
(firmware (cons* linux-firmware
%base-firmware))
(host-name "laptop-ruther")
(timezone "Europe/Prague")
(locale "en_US.utf8")
;; Choose US English keyboard layout. The "altgr-intl"
;; variant provides dead keys for accented characters.
(keyboard-layout (keyboard-layout "us" "altgr-intl"))
;; Use the UEFI variant of GRUB with the EFI System
;; Partition mounted on /boot/efi.
(bootloader (bootloader-configuration
(bootloader grub-efi-copy-bootloader)
(targets '("/boot"))
(keyboard-layout keyboard-layout)))
;; Specify a mapped device for the encrypted root partition.
;; The UUID is that returned by 'cryptsetup luksUUID'.
(mapped-devices
(list crypted-root))
(file-systems (append
(list root-file-system
(file-system
(device (file-system-label "BOOT"))
(mount-point "/boot")
(type "vfat")))
%base-file-systems))
(swap-devices
(list (swap-space
(target "/swapfile")
(dependencies (list root-file-system)))))
;; Create user `bob' with `alice' as its initial password.
(users (cons* %ruther/user
(user-account
(name "fbw")
(comment "Work account")
(group "users")
(supplementary-groups '("netdev"
"audio" "video"
"libvirt" "dialout"
"kvm" "docker"))
(shell (file-append zsh "/bin/zsh")))
%base-user-accounts))
(groups %base-groups)
(privileged-programs
(cons*
(privileged-program
(program
(file-append inetutils "/bin/traceroute"))
(capabilities "cap_net_raw=eip"))
;; (privileged-program
;; (program
;; (file-append wireshark-patched "/bin/dumpcap"))
;; (capabilities "cap_net_raw,cap_net_admin=eip"))
%default-privileged-programs))
;; This is where we specify system-wide packages.
(packages (append (list
docker-compose
iptables
;; for user mounts
gvfs
zip unzip
wget curl
vim
polkit ;; get pktty
fwupd-nonfree
netbird
;; wireshark-patched
)
%base-packages))
(services
(append (list
(service openssh-service-type
(openssh-configuration
(password-authentication? #f)
(x11-forwarding? #t)))
(service core-dumps-service-type)
(service guix-shared-cache-service-type
(guix-shared-cache-config
(users
(cons*
(user-info
(user "ruther")
(home "/home/ruther"))
(user-info
(user "fbw")
(home "/home/fbw"))
%default-guix-shared-users))))
;; I give up! Let the download binaries run.
(extra-special-file "/lib64/ld-linux-x86-64.so.2"
(file-append glibc "/lib/ld-linux-x86-64.so.2"))
(extra-special-file "/lib/ld-linux-x86-64.so.2"
(file-append glibc "/lib/ld-linux-x86-64.so.2"))
;; Let's use GUI apps from Nixpkgs, because, why not?
nixos-opengl-driver-service
;; Prefer the builder's LAN address, then fall back to WireGuard.
(extra-special-file
"/root/.ssh/config"
(mixed-text-file
"root-ssh-config"
"Host edge-ruther-builder\n"
" HostName edge-ruther.local\n"
" HostKeyAlias edge-ruther.local\n"
" BatchMode yes\n"
" ConnectTimeout 5\n"
" ProxyUseFdpass yes\n"
" ProxyCommand "
(file-append bash "/bin/sh")
" -c '"
(file-append netcat-openbsd "/bin/nc")
" -F -w 2 edge-ruther.local %p || exec "
(file-append netcat-openbsd "/bin/nc")
" -F -w 10 192.168.32.12 %p'\n"))
(service nix-service-type/raised-nofile
(nix-configuration
(extra-config
'("experimental-features = nix-command flakes\n"
"extra-platforms = i686-linux aarch64-linux\n"
"keep-outputs = true\n"
"keep-derivations = true\n"
"extra-trusted-public-keys = edge-1:sGPnKl9kRZ1Tv8xqC8qdMfdpPpeZ0HDE38/eEmGOCGk=\n"
"fallback = true\n"
"builders = ssh-ng://nixremote@edge-ruther-builder x86_64-linux /root/.ssh/id_ed25519 8 2 big-parallel,kvm\n"
"builders-use-substitutes = true\n"))))
;; TODO: contribute this to the nix service
(simple-service 'nix-etc-d etc-profile-d-service-type
(list
(file-append nix "/etc/profile.d/nix-daemon.sh")
(file-append nix "/etc/profile.d/nix.sh")))
;; Vivado or Matlab can crash because they open too many files.
;; Note: @nixbld limits are set on the nix-daemon shepherd
;; service itself (see (ruther services nix)); PAM limits don't
;; apply because nixbld users never log in.
(service pam-limits-service-type
(list
(pam-limits-entry "@wheel" 'hard 'nofile '50000)
(pam-limits-entry "@wheel" 'soft 'nofile '10000)
(pam-limits-entry "@wheel" 'both 'core 'unlimited)))
(service pcscd-service-type)
(simple-service 'nonguix-substitute
guix-service-type
(guix-extension
(authorized-keys (list
(local-file "keys/nonguix-signing-key.pub")
(local-file "keys/rpi-local-key.pub")
(local-file "keys/orv2-local-key.pub")))
;; (substitute-urls '("https://nonguix-proxy.ditigal.xyz"))
(substitute-urls '("https://substitutes.nonguix.org"))
))
(service earlyoom-service-type
(earlyoom-configuration
(minimum-available-memory 10)
(minimum-free-swap 10)
(prefer-regexp "rustc|rust-analyzer|cargo")
(avoid-regexp "emacs")))
polkit-wheel-service
(simple-service 'dbus-fwupd
dbus-root-service-type
(list fwupd-nonfree))
(simple-service 'polkit-fwupd
polkit-service-type
(list fwupd-nonfree)))
%ruther/udev-services
%ruther/container-virt-services
%ruther/network-services
%ruther/laptop-gui-essential-services
(modify-services %desktop-services
(delete gdm-service-type)
(delete screen-locker-service-type)
(network-manager-service-type config => (network-manager-configuration
(inherit config)
(vpn-plugins
(list
network-manager-openvpn))))
(mingetty-service-type config => (if (string=? (mingetty-configuration-tty config) "tty1")
(mingetty-configuration
(inherit config)
(auto-login "auto")
(login-program (make-auto-login-program #:users '("ruther" "fbw")))
(login-pause? #f))
config))
(elogind-service-type config => (elogind-configuration
(handle-lid-switch-external-power 'ignore)))
(pulseaudio-service-type config => (pulseaudio-configuration
(inherit config)
(client-conf
(append
(pulseaudio-configuration-client-conf config)
'((autospawn . no)))))))))
;; Allow resolution of '.local' host names with mDNS.
(name-service-switch %mdns-host-lookup-nss)))
(define (derivation->drv-name drv)
(mlet* %store-monad
((drv drv))
(return (derivation-file-name drv))))
(use-modules (srfi srfi-9)
(ice-9 match)
(guix records))
(define (non-grafted file)
(computed-file
"non-grafted"
#~(symlink
#$(with-parameters
((%graft? #f))
file)
#$output)))
(define <operating-system> (@@ (gnu system) <operating-system>))
(define-gexp-compiler (os-compiler (os <operating-system>) system target)
(operating-system-derivation os))
;; Takes an operating system and gc roots its derivation
(define (operating-system-with-build-inputs os)
(operating-system
(inherit os)
(services
(cons*
(simple-service 'gc-root-system-derivation
gc-root-service-type
(list
(non-grafted os)
(libc-utf8-locales-for-target)
guile-3.0
;; (map
;; non-grafted
;; (list
;; guile-3.0
;; (libc-utf8-locales-for-target)
;; texinfo))
))
(operating-system-user-services os)))))
;; (operating-system-with-build-inputs %ruther/base-laptop-os)
%ruther/base-laptop-os