diff --git a/config.org b/config.org index 667b51a..c3a593e 100644 --- a/config.org +++ b/config.org @@ -1,13 +1,70 @@ #+TITLE: GUIX System Configuration #+AUTHOR: Daniel Ziltener #+PROPERTY: scheme-implementation guile -#+PROPERTY: header-args:scheme :comments none :session *guile* +#+PROPERTY: header-args:scheme :comments none :session *guile* :prologue "(use-modules (ice-9 pretty-print))" -#+begin_src emacs-lisp :results none - (org-babel-lob-ingest "./library.org") +* Daniel Ziltener's System Configuration + +This is an attempt to fit my entire system's configuration in a file. Let's see how that turns out. + +** Emacs Lisp Helpers + +To be able to use Org-Mode lists and tables, I need a few helpers for the conversion. + +*** Converting Lists + +A sample list for testing purposes: + +#+NAME: list-sample +- Entry 1 +- Entry 2 + +First, a function that converts org lists into guile ~use-~ calls. + +#+NAME: org-list-to-use +#+begin_src scheme :var use-call="use-modules" :var entries='() :var all-parens=0 :results output + (pretty-print + `(,(string->symbol use-call) + ,@(map (lambda (x) + (let ((splits (string-split x #\ ))) + (if (and (= (length splits) 1) + (= 0 all-parens)) + (string->symbol (car splits)) + (map (lambda (y) (string->symbol y)) + splits)))) + entries))) #+end_src -* Makefile +Sometimes, I need lists of ~string->symbol~ calls. + +#+NAME: org-to-scheme-sym-list +#+begin_src scheme :var input=list-sample :results output + (pretty-print + `(list ,@(map string->symbol input))) +#+end_src + +*** Converting Tables + +**** Services + +This function converts a table of simple services into service definitions. + +#+NAME: service-converter +#+begin_src scheme :var input='() :colnames yes :results output + (pretty-print + `(list + ,@(map + (lambda (row) + (let ((service-name (car row)) + (configuration (cadr row))) + `(service ,(string->symbol (string-append service-name "-service-type")) + (,(string->symbol (string-append service-name "-configuration")) + ,@(call-with-input-string configuration + read))))) + input))) +#+end_src + +** Makefile #+begin_src makefile :tangle Makefile reconfigure: @@ -19,7 +76,7 @@ reconfigure: flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo #+end_src -* System Installation Script +** System Installation Script This is to be run after setting up the partitions. @@ -30,85 +87,380 @@ This is to be run after setting up the partitions. mkdir -p /mnt/boot/efi mount /dev/disk/by-label/EFI /mnt/boot/efi herd start cow-store /mnt + guix pull -C channels.scm GUIX_PROFILE="/root/.config/guix/current" . "$GUIX_PROFILE/etc/profile" hash guix guix system -L. init config.scm /mnt --substitute-urls="https://ci.guix.gnu.org https://bordeaux.guix.gnu.org https://substitutes.nonguix.org" #+end_src -* Modules +** The Feature Record Type -There are many community modules at [[https://whereis.みんな/][Whereis]]. +This record type exists to facilitate grouping together configuration related to a specific feature. -#+NAME: module-list -- gnu -- gnu image -- gnu system nss -- guix channels -- rosenthal packages wm -- zilti packages hyprland -- nongnu packages firmware -- nongnu packages linux -- nongnu system linux-initrd - -#+begin_src scheme :noweb yes :exports none :results output :tangle config.scm - <> +#+NAME: feature-record +#+begin_src scheme + (define-record-type* + feature make-feature + feature? + (name feature-name + (default #f)) + (root-packages feature-root-packages + (default '())) + (packages feature-packages + (default '())) + (files feature-files + (default '())) + (xdg-config-files feature-xdg-config-files + (default '())) + (service feature-service + (default '())) + (home-service feature-home-service + (default '())) + (environment feature-environment + (default '()))) #+end_src -#+RESULTS: +Since the records get written into a separate file to be consumed later, this helper function is necessary to do exactly that: -** Service Modules - -#+NAME: service-module-list -- admin -- authentication -- base -- configuration -- dbus -- desktop -- docker -- linux -- networking -- nix -- pm -- sddm -- sound -- virtualization -- xorg - -#+begin_src scheme :noweb yes :exports none :results output :tangle config.scm - <> +#+NAME: record-load-helper +#+begin_src scheme :noweb strip-export + <> + (define* (consume-file fobj #:optional (result '())) + (let ((next-elem (read fobj))) + (if (eof-object? next-elem) + (reverse result) + (consume-file fobj (cons next-elem result))))) + <> #+end_src -** Package Modules +And ultimately, this function turns a list of features into a list of whatever is needed at that place. -#+NAME: package-module-list -- bootloaders -- certs -- containers -- freedesktop -- fonts -- gl -- gnome -- kde-frameworks -- linux -- pciutils -- qt -- readline -- terminals -- version-control -- virtualization -- wm -- xdisorg -- xorg - -#+begin_src scheme :noweb yes :exports none :results output :tangle config.scm - <> +#+NAME: features-to-list +#+begin_src scheme + (define (features->list features get-fn) + (filter + (negate unspecified?) + (fold append '() + (map get-fn + (filter + (negate unspecified?) + features))))) #+end_src -* Configuration Definitions +** Features -** File System +*** Git + +Git configuration file: + +#+begin_src :tagle xdg-config/git/config :mkdir-p yes +[commit] + gpgSign = true + user = dziltener@lyrion.ch +[core] + pager = "diff-so-fancy | less '--tabs=4' '-RFX'" +[diff-so-fancy] + changeHunkIndicators = true + markEmptyLines = true + stripLeadingSymbols = true + useUnicodeRuler = true +[gpg] + program = "gpg" +[interactive] + diffFilter = "diff-so-fancy --patch" +[pull] + rebase = true +[push] + autoSetupRemote = true +[rebase] + autoStash = true +[sendemail] +# sendmailCmd = msmtp -t + annotate = yes + smtpServer = lyrion.ch + smtpUser = dziltener + smtpEncryption = ssl + smtpServerPort = 465 +[credential] + helper = cache + helper = !pass-git-helper $@ +[tag] + gpgSign = true +[user] + email = "dziltener@lyrion.ch" + name = "Daniel Ziltener" + signingKey = "37F655BAF43BC0FF300A91A1B38976E82C9DAE42" +[init] + defaultBranch = master +[github] + user = dziltener@lyrion.ch +[gitlab] + user = zilti +#+end_src + +I am using [[https://github.com/languitar/pass-git-helper][pass-git-helper]] to use Pass for git credentials. + +#+begin_src :tangle xdg-config/pass-git-helper/git-pass-mapping.ini :mkdir-p yes +[*dziltener@lyrion.ch*] +target=Privat/Mailaccount +#+end_src + +Git service configuration: + +#+begin_src scheme :tangle features.scm + (feature + (name 'git) + (root-packages '(git)) + (packages '(git git:send-email pass-git-helper)) + (xdg-config-files '(("git/config" ,(local-file "./xdg-config/git/config")) + ("pass-git-helper/git-pass-mapping.ini" ,(local-file "./xdg-config/pass-git-helper/git-pass-mapping.ini"))))) +#+end_src + +*** Hyprland + +An amazing [[https://hyprland.org/][tiling compositor for Wayland]]. + +#+begin_src :tangle xdg-config/hypr/hyprland.conf :mkdir-p yes +# See https://wiki.hyprland.org/Configuring/Monitors/ +monitor=eDP-1,2880x1800@90.0,0x1930,1.333333 + +# See https://wiki.hyprland.org/Configuring/Keywords/ for more + +# Execute your favorite apps at launch +# exec-once = waybar & hyprpaper & firefox + +# Source a file (multi-file configs) +# source = ~/.config/hypr/myColors.conf + +# Set programs that you use +$terminal = kitty +$fileManager = dolphin +$menu = fuzzel + +# Some default env vars. +env = XCURSOR_SIZE,24 +env = HYPRCURSOR_SIZE,24 +env = HYPRCURSOR_THEME,hyprcursor_Dracula +env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that +env = MOZ_ENABLE_WAYLAND,1 +env = XDG_SESSION_TYPE,wayland +env = CLUTTER_BACKEND,wayland +env = SDL_VIDEODRIVER,wayland +env = LIBGL_DRI3_ENABLE,1 +env = GDK_BACKEND,wayland +env = XKB_DEFAULT_RULES,evdev +env = QT_QPA_PLATFORM,wayland +env = WLR_DRM_NO_ATOMIC,1 +env = SSH_AUTH_SOCK,/run/user/1000/gnupg/S.gpg-agent.ssh + +# For all categories, see https://wiki.hyprland.org/Configuring/Variables/ +input { + kb_layout = de + kb_variant = + kb_model = + kb_options = caps:swapescape + kb_rules = + + follow_mouse = 1 + + touchpad { + natural_scroll = no + } + + sensitivity = 0 # -1.0 - 1.0, 0 means no modification. +} + +general { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + + gaps_in = 15 + gaps_out = 20 + border_size = 2 + col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg + col.inactive_border = rgba(595959aa) + + layout = master + + # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on + allow_tearing = false +} + +decoration { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + + rounding = 10 + + blur { + enabled = true + size = 3 + passes = 1 + } + + drop_shadow = yes + shadow_range = 4 + shadow_render_power = 3 + col.shadow = rgba(1a1a1aee) +} + +animations { + enabled = yes + + # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more + + bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + + animation = windows, 1, 7, myBezier + animation = windowsOut, 1, 7, default, popin 80% + animation = border, 1, 10, default + animation = borderangle, 1, 8, default + animation = fade, 1, 7, default + animation = workspaces, 1, 6, default +} + +dwindle { + # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more + pseudotile = no # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below + preserve_split = yes # you probably want this + force_split = 0 + default_split_ratio = 1.5 +} + +master { + # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more + new_is_master = false + orientation = center + workspace = w[t2], layoutopt:orientation:left + always_center_master = true + mfact = 0.5 + special_scale_factor = 0.8 +} + +gestures { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + workspace_swipe = off +} + +misc { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers + vfr = true + vrr = 1 + animate_manual_resizes = true +} + +# Example windowrule v1 +# windowrule = float, ^(kitty)$ +# Example windowrule v2 +# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ +# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more +#windowrulev2 = nomaximizerequest, class:.* # You'll probably like this. + +# See https://wiki.hyprland.org/Configuring/Keywords/ for more +$mainMod = SUPER + +# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more +bind = $mainMod, Q, exec, $terminal +bind = $mainMod, C, killactive, +bind = $mainMod, M, exec, wlogout +bind = $mainMod, E, exec, $fileManager +bind = $mainMod, V, togglefloating, +bind = $mainMod, R, exec, $menu +bind = $mainMod SHIFT, L, exec, hyprlock +bind = $mainMod, PRINT, exec, grim -l 9 -g "`slurp`" - | swappy -f - +bind = $mainMod, P, pseudo, # dwindle +bind = $mainMod, J, togglesplit, # dwindle +bind = $mainMod, T, togglegroup, +bind = $mainMod, A, layoutmsg, swapwithmaster master +bind = $mainMod, I, layoutmsg, orientationcenter +bind = $mainMod, H, layoutmsg, orientationleft +bind = $mainMod, L, layoutmsg, orientationright + +# Move focus with mainMod + arrow keys +bind = $mainMod, left, movefocus, l +bind = $mainMod, right, movefocus, r +bind = $mainMod, up, movefocus, u +bind = $mainMod, down, movefocus, d + +# Move windows inside a workspace +bind = $mainMod SHIFT, a, movewindoworgroup, l +bind = $mainMod SHIFT, d, movewindoworgroup, r + +# Handle tabbed windows +bind = $mainMod, tab, changegroupactive, +bind = $mainMod SHIFT, t, lockactivegroup, toggle + +# Switch workspaces with mainMod + [0-9] +bind = $mainMod, 1, split:workspace, 1 +bind = $mainMod, 2, split:workspace, 2 +bind = $mainMod, 3, split:workspace, 3 +bind = $mainMod, 4, split:workspace, 4 +bind = $mainMod, 5, split:workspace, 5 +bind = $mainMod, 6, split:workspace, 6 +bind = $mainMod, 7, split:workspace, 7 +bind = $mainMod, 8, split:workspace, 8 +bind = $mainMod, 9, split:workspace, 9 +bind = $mainMod, 0, split:workspace, 10 + +# Move active window to a workspace with mainMod + SHIFT + [0-9] +bind = $mainMod SHIFT, 1, split:movetoworkspace, 1 +bind = $mainMod SHIFT, 2, split:movetoworkspace, 2 +bind = $mainMod SHIFT, 3, split:movetoworkspace, 3 +bind = $mainMod SHIFT, 4, split:movetoworkspace, 4 +bind = $mainMod SHIFT, 5, split:movetoworkspace, 5 +bind = $mainMod SHIFT, 6, split:movetoworkspace, 6 +bind = $mainMod SHIFT, 7, split:movetoworkspace, 7 +bind = $mainMod SHIFT, 8, split:movetoworkspace, 8 +bind = $mainMod SHIFT, 9, split:movetoworkspace, 9 +bind = $mainMod SHIFT, 0, split:movetoworkspace, 10 + +# Example special workspace (scratchpad) +bind = ALT SHIFT, RETURN, togglespecialworkspace, magic +bind = $mainMod SHIFT, S, movetoworkspace, special:magic + +# Scroll through existing workspaces with mainMod + scroll +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 + +# Move/resize windows with mainMod + LMB/RMB and dragging +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow + +# Autostart +exec-once = hyprctl dispatch togglespecialworkspace; sleep 1; $terminal; hyprctl dispatch layoutmsg orientationleft; hyprctl dispatch togglespecialworkspace +exec-once = hyprpaper +exec-once = waybar +exec-once = daemon syncthing serve +exec-once = hypridle & +exec-once = swaync & +exec-once = emacs --daemon +exec-once = hyprctl plugin load "$(find /gnu/store/ -name 'libhyprsplit.so' | head -n1)" +#+end_src + +Wallpaper via Hyprpaper + +#+begin_src :tangle xdg-config/hypr/hyprland.conf :mkdir-p yes + preload = /home/zilti/config/wallpapers/Next/contents/images/5120x2880.png + wallpaper = ,/home/zilti/config/wallpapers/Next/contents/images/5120x2880.png + splash = true +#+end_src + +Main configuration + +#+begin_src scheme :tangle features.scm + (feature + (name 'hyprland) + (root-packages 'hyprland-xwayland) + (packages '(hyprcursor + hyprpaper + hypridle + hyprlock + hyprland-xwayland-plugin-hyprsplit))) +#+end_src + +** Operating System Definitions + +*** File System Update the file system labels: #+begin_src shell @@ -138,9 +490,9 @@ Update the file system labels: (list (swap-space (target (file-system-label "swap"))))) #+end_src -** Channels +*** Channels -This adds the Nonguix channel. +This adds useful package channels. #+NAME: root-channels #+begin_src scheme :tangle channels.scm @@ -176,11 +528,107 @@ This adds the Nonguix channel. %default-channels) #+end_src -#+RESULTS: root-channels :tangle channels.scm +Here are the corresponding pubkeys: -#+RESULTS: root-channels +#+NAME: nonguix-pubkey +#+begin_src scheme :tangle keys/non-guix.pub :mkdirp yes + (public-key + (ecc + (curve Ed25519) + (q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#) + ) + ) +#+end_src -** Packages +#+NAME: guix-ci-pubkey +#+begin_src scheme :tangle keys/guix-ci.pub :mkdirp yes + (public-key + (ecc + (curve Ed25519) + (q #8D156F295D24B0D9A86FA5741A840FF2D24F60F7B6C4134814AD55625971B394#) + ) + ) +#+end_src + +#+NAME: guix-bordeaux-pubkey +#+begin_src scheme :tangle keys/guix-bordeaux.pub :mkdirp yes + (public-key + (ecc + (curve Ed25519) + (q #7D602902D3A2DBB83F8A0FB98602A754C5493B0B778C8D1DD4E0F41DE14DE34F#) + ) + ) +#+end_src + +*** Modules + +There are many community modules at [[https://whereis.みんな/][Whereis]]. + +#+NAME: module-list +- gnu +- gnu image +- gnu system nss +- guix channels +- rosenthal packages wm +- zilti packages hyprland +- nongnu packages firmware +- nongnu packages linux +- nongnu system linux-initrd + +#+begin_src scheme :noweb yes :exports none :results output :tangle config.scm + <> +#+end_src + +**** Service Modules + +#+NAME: service-module-list +- admin +- authentication +- base +- configuration +- dbus +- desktop +- docker +- linux +- networking +- nix +- pm +- sddm +- sound +- virtualization +- xorg + +#+begin_src scheme :noweb yes :exports none :results output :tangle config.scm + <> +#+end_src + +**** Package Modules + +#+NAME: package-module-list +- bootloaders +- certs +- containers +- freedesktop +- fonts +- gl +- gnome +- kde-frameworks +- linux +- pciutils +- qt +- readline +- terminals +- version-control +- virtualization +- wm +- xdisorg +- xorg + +#+begin_src scheme :noweb yes :exports none :results output :tangle config.scm + <> +#+end_src + +*** Root Packages #+NAME: root-packages - bluez-firmware @@ -225,7 +673,7 @@ This adds the Nonguix channel. #+RESULTS: root-package-block -** Services +*** Services #+NAME: root-services-block #+begin_src scheme :noweb yes :exports none :results code @@ -242,7 +690,7 @@ This adds the Nonguix channel. <>))) #+end_src -*** Simple Services +**** Simple Services These services are unmodified, or have just few settings. @@ -265,7 +713,7 @@ These services are unmodified, or have just few settings. <> #+end_src -*** Unattended Upgrade Service +**** Unattended Upgrade Service #+NAME: unattended-upgrade #+begin_src scheme :noweb no-export @@ -276,7 +724,7 @@ These services are unmodified, or have just few settings. <>))) #+end_src -*** Hosts File +**** Hosts File #+NAME: hosts-file-service #+begin_src scheme :noweb no-export @@ -286,37 +734,7 @@ These services are unmodified, or have just few settings. (host "::1" "l.redsky.io" '("ld.redsky.io")))) #+end_src -*** Modified Desktop Services - -#+NAME: nonguix-pubkey -#+begin_src scheme :tangle keys/non-guix.pub :mkdirp yes - (public-key - (ecc - (curve Ed25519) - (q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#) - ) - ) -#+end_src - -#+NAME: guix-ci-pubkey -#+begin_src scheme :tangle keys/guix-ci.pub :mkdirp yes - (public-key - (ecc - (curve Ed25519) - (q #8D156F295D24B0D9A86FA5741A840FF2D24F60F7B6C4134814AD55625971B394#) - ) - ) -#+end_src - -#+NAME: guix-bordeaux-pubkey -#+begin_src scheme :tangle keys/guix-bordeaux.pub :mkdirp yes - (public-key - (ecc - (curve Ed25519) - (q #7D602902D3A2DBB83F8A0FB98602A754C5493B0B778C8D1DD4E0F41DE14DE34F#) - ) - ) -#+end_src +**** Modified Desktop Services #+NAME: root-modified-desktop-services #+begin_src scheme :exports none :results code :noweb no-export @@ -336,7 +754,7 @@ These services are unmodified, or have just few settings. %default-authorized-guix-keys))))) #+end_src -*** Screen Locker Service +**** Screen Locker Service For some reason, this service runs on root level for Guix. @@ -350,7 +768,7 @@ For some reason, this service runs on root level for Guix. (using-setuid? #f))) #+end_src -* Operating System +*** Operating System This is the full operating system specification. @@ -386,3 +804,35 @@ This is the full operating system specification. <> (name-service-switch %mdns-host-lookup-nss)) #+end_src + + +** Guix Home + +This is the main home configuration. First, all the imports: + +#+NAME: home-module-list +- gnu packages +- gnu packages gnupg +- gnu packages linux +- gnu packages shellutils +- nongnu packages game-client +- gnu services +- guix gexp +- guix channels +- gnu home +- gnu home services +- gnu home services desktop +- gnu home services gnupg +- gnu home services guix +- gnu home services mail +- gnu home services mcron +- gnu home services pm +- gnu home services shells +- gnu home services shepherd +- gnu home services sound +- gnu home services ssh +- gnu home services syncthing + +#+begin_src scheme :noweb yes :exports none :results output :mkdir-p yes :tangle home/home-configuration.scm + <> +#+end_src diff --git a/home/home-configuration.scm b/home/home-configuration.scm index af412ac..c765983 100644 --- a/home/home-configuration.scm +++ b/home/home-configuration.scm @@ -31,8 +31,7 @@ (home-environment ;; Below is the list of Home services. To search for available ;; services, run 'guix home search KEYWORD' in a terminal. - ( -services + (services (list (service home-shepherd-service-type) (service home-msmtp-service-type @@ -273,4 +272,6 @@ services (service home-dbus-service-type) (service home-pipewire-service-type (home-pipewire-configuration - (wireplumber wireplumber-minimal)))))) + (wireplumber wireplumber-minimal))) + ) +))