#+TITLE: GUIX System Configuration
#+AUTHOR: Daniel Ziltener
#+PROPERTY: scheme-implementation guile
#+PROPERTY: header-args:scheme :comments both

#+begin_src emacs-lisp :results none
  (org-babel-lob-ingest "./library.org")
#+end_src

* Makefile

#+begin_src makefile :tangle Makefile
  ~/.config/guix/channels.scm:
          mkdir -p ~/.config/guix
          cp channels.scm ~/.config/guix/channels.scm

  install:
          guix archive --authorize < signing-key.pub
          guix system reconfigure ./config.scm --substitute-urls='https://ci.guix.gnu.org https://bordeaux.guix.gnu.org https://substitutes.nonguix.org'
#+end_src

* System Installation Script

This is to be run after setting up the partitions.

#+begin_src sh :tangle sysinst.sh
  #!/bin/sh
  herd start cow-store /mnt
  mkdir -p ~/.config/guix
  cp channels.scm ~/.config/guix/channels.scm
  guix pull
  sed -i 's|/etc/config.scm|/mnt/etc/config.scm|g' ./config.scm
  guix system init ./config.scm /mnt
#+end_src

* Modules

#+NAME: module-list
- gnu
- gnu image
- gnu services authentication
- gnu services base
- gnu services dbus
- gnu services desktop
- gnu services linux
- gnu services networking
- gnu services pm
- gnu services virtualization
- gnu services xorg
- gnu system nss
- nongnu packages linux
- nongnu system linux-initrd

#+begin_src scheme :noweb yes :exports none :results code pp :tangle config.scm
  <<list-to-use(use-call="use-modules",entries=module-list,all-parens=1)>>
#+end_src

** Service Modules

#+NAME: service-module-list
- desktop
- xorg

#+begin_src scheme :noweb yes :exports none :results code pp :tangle config.scm
  <<list-to-use(use-call="use-service-modules",entries=service-module-list)>>
#+end_src

**  Package Modules

#+NAME: package-module-list
- bootloaders
- certs
- emacs
- emacs-xyz
- fonts
- readline
- terminals
- version-control
- wm
- xorg

#+begin_src scheme :noweb yes :exports none :results code pp :tangle config.scm
  <<list-to-use(use-call="use-package-modules",entries=package-module-list)>>
#+end_src

* Configuration Definitions

** File System

The variable ~%local-filesystem~ extracts the file system definitions from the installer-provided
=config.scm= file.

#+begin_src scheme :tangle config.scm
  (define %local-filesystem
    (call-with-input-file "/etc/config.scm"
      (lambda (port)
        (read port)
        (read port)
        (eval (cadar (last-pair (read port)))
              (interaction-environment)))))
#+end_src

As a sibling to the former, the variable ~%local-swap~ does the same with the swap partition.

#+begin_src scheme :tangle config.scm
  (define %local-swap
    (call-with-input-file "/etc/config.scm"
      (lambda (port)
        (read port)
        (read port)
        (let* ((os-list (read port))
               (os-list-length (length os-list)))
          (eval
           (cadr
            (list-ref os-list
                      (- os-list-length 2)))
           (interaction-environment))))))
#+end_src

** Channels

This adds the Nonguix channel.

#+begin_src scheme :tangle channels.scm
  ;; Copy this to ~/.config/guix/channels.scm.
  (cons* (channel
        (name 'nonguix)
        (url "https://gitlab.com/nonguix/nonguix")
        ;; Enable signature verification:
        (introduction
         (make-channel-introduction
          "897c1a470da759236cc11798f4e0a5f7d4d59fbc"
          (openpgp-fingerprint
           "2A39 3FFF 68F4 EF7A 3D29  12AF 6F51 20A0 22FB B2D5"))))
       %default-channels)
#+end_src

** Packages

#+NAME: root-packages
- emacs
- emacs-desktop-environment
- font-terminus
- git
- hwdata
- nss-certs
- readline
- swayfx

#+NAME: root-package-block
#+begin_src scheme :noweb no-export
  (packages
   (append
    <<org-to-scheme-sym-list(input=root-packages)>>
    %base-packages))
#+end_src

** Services

#+NAME: root-services-block
#+begin_src scheme :noweb yes :exports none :results code
  (services
   (append
    <<root-modified-desktop-services>>
    <<root-simple-service-block>>
    (list
     <<greeter-service>>)
    (list
     <<screen-lock-service>>)
    ))
#+end_src

*** Simple Services

These services are unmodified, or have just few settings.

#+NAME: root-simple-services
| Service     | Options                                              |
|-------------+------------------------------------------------------|
| tlp         | ()                                                   |
| thermald    | ((adaptive? #t))                                     |
| bluetooth   | ()                                                   |
| earlyoom    | ((minimum-available-memory 5) (minimum-free-swap 5)) |
| inputattach | ()                                                   |
| libvirt     | ((unix-sock-group "libvirt"))                        |
| fstrim      | ()                                                   |
| fprintd     | ()                                                   |

#+NAME: root-simple-service-block
#+begin_src scheme :noweb yes :exports none :results code
  <<service-converter(input=root-simple-services)>>
#+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: root-modified-desktop-services
#+begin_src scheme :exports none :results code
    (modify-services
     %desktop-services
     (delete login-service-type)
     (delete mingetty-service-type)
     (delete console-font-service-type)
     (guix-service-type config => (guix-configuration
                                   (inherit config)
                                   (substitute-urls
                                    (append (list "https://substitutes.nonguix.org")
                                            %default-substitute-urls))
                                   (authorized-keys
                                    (append (list (plain-file "non-guix.pub"
                                                              "<<nonguix-pubkey>>")))))))
#+end_src

*** Greeter Service

=greetd= is a broken mess, yet here we are.

#+NAME: greeter-service
#+begin_src scheme
  (service greetd-service-type
           (greetd-configuration
            (greeter-supplementary-groups
             (list "video" "input"))
            (terminals
             (list
              (greetd-terminal-configuration
               (terminal-vt "1"))
              (greetd-terminal-configuration
               (terminal-vt "2"))
              (greetd-terminal-configuration
               (terminal-vt "3"))
              (greetd-terminal-configuration
               (terminal-vt "4"))
              #;(greetd-terminal-configuration
              (terminal-vt "7")
              (terminal-switch #t)
              (default-session-command
              (greetd-wlgreet-session
              (command
              (file-append swayfx "/bin/sway")))))
              (greetd-terminal-configuration
               (terminal-vt "8"))))))
#+end_src

*** Screen Locker Service

For some reason, this service runs on root level for Guix.

#+NAME: screen-lock-service
#+begin_src scheme
  (service screen-locker-service-type
           (screen-locker-configuration
            (name "swaylock")
            (program
             (file-append swaylock-effects "/bin/swaylock"))
            (using-setuid? #f)))
#+end_src

* Operating System

This is the full operating system specification.

#+begin_src scheme :noweb no-export :results code :tangle config.scm
  (operating-system
   (host-name "ziltis-machine")
   (timezone "Europe/Berlin")
   (locale "de_DE.utf8")
   (keyboard-layout
    (keyboard-layout "de" #:options '("caps:swapescape")))
   (kernel linux)
   (initrd microcode-initrd)
   (firmware (list linux-firmware))
   (bootloader
    (bootloader-configuration
     (bootloader grub-efi-bootloader)
     (targets
      '("/boot/efi"))
     (keyboard-layout keyboard-layout)))
   (file-systems %local-filesystem)
   (swap-devices %local-swap)
   (users
    (cons*
     (user-account
      (name "zilti")
      (group "users")
      (supplementary-groups
       '("wheel" "netdev" "audio" "video" "libvirt")))
     %base-user-accounts))
    <<root-package-block>>
    <<root-services-block>>
   (name-service-switch %mdns-host-lookup-nss))
#+end_src