summaryrefslogtreecommitdiff
path: root/izumi.org
diff options
context:
space:
mode:
Diffstat (limited to 'izumi.org')
-rw-r--r--izumi.org977
1 files changed, 977 insertions, 0 deletions
diff --git a/izumi.org b/izumi.org
new file mode 100644
index 0000000..25cf9ab
--- /dev/null
+++ b/izumi.org
@@ -0,0 +1,977 @@
+#+TITLE: Configuration of the Izumi computer
+#+AUTHOR: Marek Paśnikowski
+#+STARTUP: content
+#+PROPERTY: header-args:scheme :noweb yes
+#+PROPERTY: header-args:scheme+ :noweb-prefix yes
+
+* DONE The Monolith
+
+#+NAME: OPERATING-SYSTEM
+#+BEGIN_SRC scheme :tangle system-configuration.scm
+ ( add-to-load-path "/home/marek/Dokumenty/secrets/" )
+
+ ( use-modules
+ ( marek )
+ ( gnu )
+ ( guix records )
+ ( ice-9 match )
+ ( nongnu packages linux )
+ ( nongnu system linux-initrd ) )
+
+ ( use-package-modules
+ admin certs kde-frameworks kde-multimedia kde-pim kde-plasma kde-utils mail
+ version-control )
+
+ ( use-service-modules
+ base certbot cgit desktop mail shepherd ssh version-control web xorg )
+
+ ( define-record-type*
+ <dkimproxy-out-signature-configuration>
+ dkimproxy-out-signature-configuration
+ make-dkimproxy-out-signature-configuration
+ dkimproxy-out-signature-configuration?
+ ( type
+ dkimproxy-out-signature-configuration-type
+ ( default 'dkim ) )
+ ( key
+ dkimproxy-out-signature-configuration-key
+ ( default #f ) )
+ ( algorithm
+ dkimproxy-out-signature-configuration-algorithm
+ ( default #f ) )
+ ( method
+ dkimproxy-out-signature-configuration-method
+ ( default #f) )
+ ( domain
+ dkimproxy-out-signature-configuration-domain
+ ( default #f ) )
+ ( identity
+ dkimproxy-out-signature-configuration-identity
+ ( default #f ) )
+ ( selector
+ dkimproxy-out-signature-configuration-selector
+ ( default #f ) ) )
+
+ ( define generate-dkimproxy-out-signature-configuration
+ ( match-lambda
+ ( ( $
+ <dkimproxy-out-signature-configuration>
+ type
+ key
+ algorithm
+ method
+ domain
+ identity
+ selector )
+ ( string-append
+ ( match type
+ ( 'dkim "dkim" )
+ ( 'domainkeys "domainkeys" ) )
+ ( if ( or key algorithm method domain identity selector )
+ ( string-append
+ "("
+ ( string-join
+ `( ,@ ( if key
+ ( list ( string-append "key=" key ) )
+ '() )
+ ,@ ( if algorithm
+ ( list ( string-append "a=" algorithm ) )
+ '() )
+ ,@ ( if method
+ ( list ( string-append "c=" method ) )
+ '() )
+ ,@ ( if domain
+ ( list ( string-append "d=" domain ) )
+ '() )
+ ,@ ( if identity
+ ( list ( string-append "i=" identity ) )
+ '() )
+ ,@ ( if selector
+ ( list ( string-append "s=" selector ) )
+ '() ) )
+ "," )
+ ")" )
+ "" ) ) ) ) )
+
+ ( define-record-type*
+ <dkimproxy-out-configuration>
+ dkimproxy-out-configuration
+ make-dkimproxy-out-configuration
+ dkimproxy-out-configuration?
+ ( package
+ dkimproxy-out-configuration-package
+ ( default dkimproxy ) )
+ ( listen
+ dkimproxy-out-configuration-listen
+ ( default #f ) )
+ ( relay
+ dkimproxy-out-configuration-relay
+ ( default #f ) )
+ ( list-id-map
+ dkimproxy-out-configuration-list-id-map
+ ( default '() ) )
+ ( sender-map
+ dkimproxy-out-configuration-sender-map
+ ( default '() ) )
+ ( reject-error?
+ dkimproxy-out-configuration-sender-reject-error?
+ ( default #f ) )
+ ( config-file
+ dkimproxy-out-configuration-config-file
+ ( default #f ) ) )
+
+ ( define ( generate-map-file config filename )
+ ( apply
+ plain-file
+ filename
+ ( map ( lambda ( config )
+ ( match config
+ ( ( selector ( config ... ) )
+ ( string-append
+ selector " "
+ ( string-join
+ ( map
+ generate-dkimproxy-out-signature-configuration
+ config )
+ "\n") ) )
+ ( ( selector config )
+ ( string-append
+ selector " "
+ ( generate-dkimproxy-out-signature-configuration
+ config ) ) ) ) )
+ config ) ) )
+
+ ( define dkimproxy-out-shepherd-service
+ ( match-lambda
+ ( ( $
+ <dkimproxy-out-configuration>
+ package
+ listen
+ relay
+ list-id-map
+ sender-map
+ reject-error?
+ config-file )
+ ( list
+ ( shepherd-service
+ ( provision '( dkimproxy-out ) )
+ ( requirement '( loopback ) )
+ ( documentation "Outbound DKIM proxy." )
+ ( start
+ ( let ( ( proxy ( file-append package "/bin/dkimproxy.out" ) ) )
+ ( if config-file
+ #~
+ ( make-forkexec-constructor
+ ( list
+ #$
+ proxy
+ ( string-append "--conf_file=" #$ config-file )
+ "--pidfile=/var/run/dkimproxy.out.pid"
+ "--user=dkimproxy" "--group=dkimproxy" )
+ #:pid-file "/var/run/dkimproxy.out.pid" )
+ ( let*
+ ( ( first-signature
+ ( match sender-map
+ ( ( ( sender ( signature _ ... ) ) _ ... ) signature )
+ ( ( ( sender signature ) _ ... ) signature ) ) )
+ ( domains
+ ( apply append
+ ( map
+ ( lambda ( sender )
+ ( match sender
+ ( ( ( domains ... ) config ) domains )
+ ( ( domain config ) domain ) ) )
+ sender-map ) ) )
+ ( sender-map
+ ( generate-map-file sender-map "sender.map" ) )
+ ( listid-map
+ ( if ( null? list-id-map )
+ #f
+ ( generate-map-file list-id-map "listid.map" ) ) )
+ ( keyfile
+ ( dkimproxy-out-signature-configuration-key
+ first-signature ) )
+ ( selector
+ ( dkimproxy-out-signature-configuration-selector
+ first-signature ) )
+ ( method
+ ( dkimproxy-out-signature-configuration-method
+ first-signature ) )
+ ( signature
+ ( match ( dkimproxy-out-signature-configuration-type
+ first-signature )
+ ( 'dkim "dkim" )
+ ( 'domainkeys "domainkeys" ) ) ) )
+ #~
+ ( make-forkexec-constructor
+ `( ,#$
+ proxy
+ "--pidfile=/var/run/dkimproxy.out.pid"
+ "--user=dkimproxy" "--group=dkimproxy"
+ ,( string-append "--listen=" #$ listen )
+ ,( string-append "--relay=" #$ relay )
+ ,( string-append "--sender_map=" #$ sender-map )
+ ,@ ( if #$ listid-map
+ ( list
+ ( string-append "--listid_map=" #$ listid-map ) )
+ '() )
+ ,( string-append "--domain=" #$ domains )
+ ,( string-append "--keyfile=" #$ keyfile )
+ ,( string-append "--selector=" #$ selector )
+ ,@ ( if #$ method
+ ( list
+ ( string-append "--method=" #$ method ) )
+ '() )
+ ,@ ( if #$ reject-error?
+ '( "--reject_error" )
+ '() )
+ ,@ ( if #$ signature
+ ( list
+ ( string-append "--signature=" #$ signature ) )
+ '() ) ) ) ) ) ) )
+ ( stop #~ ( make-kill-destructor ) ) ) ) ) ) )
+
+ ( define %dkimproxy-accounts
+ ( list ( user-group
+ ( name "dkimproxy" )
+ ( system? #t ) )
+ ( user-account
+ ( name "dkimproxy" )
+ ( group "dkimproxy" )
+ ( system? #t )
+ ( comment "Dkimproxy user" )
+ ( home-directory "/var/empty" )
+ ( shell ( file-append shadow "/sbin/nologin" ) ) ) ) )
+
+ ( define dkimproxy-out-service-type
+ ( service-type
+ ( name 'dkimproxy-out )
+ ( description "stub" )
+ ( extensions
+ ( list
+ ( service-extension
+ account-service-type
+ ( const %dkimproxy-accounts ) )
+ ( service-extension
+ shepherd-root-service-type
+ dkimproxy-out-shepherd-service ) ) ) ) )
+
+ ( define aliases-file
+ ( mixed-text-file "aliases" "@ vmail\n" ) )
+
+ ( define relays-file
+ ( mixed-text-file
+ "other-relays"
+ "mx1.forwardemail.net\n"
+ "mx2.forwardemail.net\n" ) )
+
+ ( define blacklist-file
+ ( mixed-text-file
+ "blacklist"
+ "@yahoo.com.cn\n"
+ "@qq.com\n"
+ "@fnac.com\n"
+ "@just-aero.us\n"
+ "@elitetorrent1.com\n" ) )
+
+ ( define ( opensmtpd-conf interface domain )
+ ( mixed-text-file
+ "smtpd.conf"
+ "# This is the smtpd server system-wide configuration file.\n"
+ "# See smtpd.conf(5) for more information.\n"
+ "\n"
+ "# My TLS certificate and key\n"
+ "pki marekpasnikowski.pl cert \"/etc/letsencrypt/live/" domain "/fullchain.pem\"\n"
+ "pki marekpasnikowski.pl key \"/etc/letsencrypt/live/" domain "/privkey.pem\"\n"
+ "\n"
+ "# Edit this file to add add more virtual users (passwords are read in that file\n"
+ "# instead of /etc/passwd\n"
+ "table passwd file:" smtpd-keys "\n"
+ "\n"
+ "table other-relays file:" relays-file "\n"
+ "table blacklist file:" blacklist-file "\n"
+ "\n"
+ "# A simple spam filter\n"
+ "# filter spam-filter phase mail-from match mail-from <blacklist> reject \"555\"\n"
+ "\n"
+ "# port 25 is used only for receiving from external servers, and they may start\n"
+ "# a TLS session if they want.\n"
+ "listen on " interface " port 25 # tls pki marekpasnikowski.pl filter spam-filter\n"
+ "\n"
+ "# For sending messages from outside of this server, you need to authenticate and\n"
+ "# use TLS.\n"
+ "listen on " interface " port 465 smtps pki marekpasnikowski.pl mask-src auth <passwd>\n"
+ "\n"
+ "# Localhost is used by the .onion, so we use the same configuration for \n"
+ "# local connections."
+ "listen on lo port 25 tls pki marekpasnikowski.pl filter spam-filter\n"
+ "# Since incoming connection uses tor, we don't need tls, but still require\n"
+ "# authentication; we're not a relay\n"
+ "# listen on lo port 587 tls pki marekpasnikowski.pl mask-src auth <passwd>\n"
+ "\n"
+ "# DKIMproxy\n"
+ "listen on lo port 10028 tag DKIM_OUT\n"
+ "\n"
+ "# The socket is considered an internal connection\n"
+ "listen on socket mask-src\n"
+ "\n"
+ "# Maybe it'll work better if we connect to gmail only with v4?\n"
+ "# limit mta for domain gmail.com inet4\n"
+ "\n"
+ "# TODO: manage these files directly in the configuration?\n"
+ "# If you edit the file, you have to run \"smtpctl update table aliases\"\n"
+ "table aliases file:" aliases-file "\n"
+ "\n"
+ "# We define some actions\n"
+ "action receive lmtp \"/var/run/dovecot/lmtp\" rcpt-to virtual <aliases>\n"
+ "action outbound relay helo \"" domain "\"\n"
+ "action godkim relay host smtp://127.0.0.1:10027\n"
+ "\n"
+ "# We accept to relay any mail from authenticated users\n"
+ "match for any from any auth action godkim\n"
+ "match tag DKIM_OUT for any action outbound\n"
+ "\n"
+ "# Then, we reject on some other conditions:\n"
+ "\n"
+ "# If the mail tries to impersonate us\n"
+ "# match !from src <other-relays> mail-from \"@marekpasnikowski.pl\" for any reject\n"
+ "\n"
+ "# If it comes from someone on the blacklist\n"
+ "match from any mail-from <blacklist> reject\n"
+ "\n"
+ "# Finally, if we accept incoming messages\n"
+ "match from any for domain \"marekpasnikowski.pl\" action receive\n"
+ "match for local action receive\n" ) )
+
+ ( define ( wip-dkim-service domain )
+ ( service dkimproxy-out-service-type
+ ( dkimproxy-out-configuration
+ ( listen "127.0.0.1:10027" )
+ ( relay "127.0.0.1:10028" )
+ ( sender-map
+ `( ( ,domain
+ ( ,( dkimproxy-out-signature-configuration
+ ( algorithm "rsa-sha256" )
+ ( key "/etc/mail/dkim/marekpasnikowski.pl.key" )
+ ( method "relaxed" )
+ ( selector "dkim" )
+ ( type 'dkim ) )
+ ,( dkimproxy-out-signature-configuration
+ ( method "mofws" )
+ ( type 'domainkeys ) ) ) ) ) ) ) ) )
+
+ ( define ( wip-imap-service domain )
+ ( service dovecot-service-type
+ ( dovecot-configuration
+ ( disable-plaintext-auth? #t )
+ ( mail-location "maildir:~/Maildir" )
+ ( namespaces
+ ( list
+ ( namespace-configuration
+ ( name "inbox" )
+ ( inbox? #t )
+ ( mailboxes
+ ( list
+ ( mailbox-configuration
+ ( name "Archive" )
+ ( auto "subscribe" )
+ ( special-use ( list "\\Archive" ) ) )
+ ( mailbox-configuration
+ ( name "Drafts" )
+ ( auto "subscribe" )
+ ( special-use ( list "\\Drafts" ) ) )
+ ( mailbox-configuration
+ ( name "Junk" )
+ ( auto "subscribe" )
+ ( special-use ( list "\\Junk" ) ) )
+ ( mailbox-configuration
+ ( name "Sent" )
+ ( auto "subscribe" )
+ ( special-use ( list "\\Sent" ) ) )
+ ( mailbox-configuration
+ ( name "Trash" )
+ ( auto "subscribe" )
+ ( special-use ( list "\\Trash" ) ) ) ) ) ) ) )
+ ( passdbs
+ ( list
+ ( passdb-configuration
+ ( args ( list "username_format=%n" "/etc/dovecot-passwd" ) )
+ ( driver "passwd-file" ) ) ) )
+ ( protocols
+ ( list
+ ( protocol-configuration ( name "imap" ) )
+ ( protocol-configuration ( name "lmtp" ) ) ) )
+ ( services
+ ( list
+ ( service-configuration
+ ( kind "lmtp" )
+ ( listeners
+ ( list
+ ( inet-listener-configuration
+ ( address "192.168.10.2 127.0.0.1" )
+ ( port 24 )
+ ( protocol "lmtp" ) )
+ ( unix-listener-configuration
+ ( group "vmail" )
+ ( mode "0666" )
+ ( path "lmtp" )
+ ( user "vmail" ) ) ) ) )
+ ( service-configuration
+ ( kind "imap-login" )
+ ( listeners
+ ( list
+ ( inet-listener-configuration
+ ( address "192.168.10.2" )
+ ( port 993 )
+ ( protocol "imaps" )
+ ;; How does the boolean type map to
+ ;; the three configuration options?
+ ;; ( ssl? "required" )
+ ) ) ) ) ) )
+ ( ssl? "required" )
+ ( ssl-cert
+ ( string-append
+ "</etc/letsencrypt/live/"
+ domain
+ "/fullchain.pem" ) )
+ ( ssl-key
+ ( string-append
+ "</etc/letsencrypt/live/"
+ domain
+ "/privkey.pem" ) )
+ ( ssl-min-protocol "TLSv1.2" )
+ ( userdbs
+ ( list
+ ( userdb-configuration
+ ( args ( list "gid=vmail" "home=/home/vmail/%n" "uid=vmail" ) )
+ ( driver "static" ) ) ) ) ) ) )
+
+ ( define ( wip-smtp-service interface domain )
+ ( service opensmtpd-service-type
+ ( opensmtpd-configuration
+ ( config-file ( opensmtpd-conf interface domain ) ) ) ) )
+
+ ( define* ( wip-mail-services #:key interface domain )
+ ( list
+ ( wip-dkim-service domain )
+ ( wip-imap-service domain )
+ ( wip-smtp-service interface domain ) ) )
+
+ ( operating-system
+ ( bootloader
+ ( bootloader-configuration
+ ( bootloader grub-efi-bootloader )
+ ( keyboard-layout ( keyboard-layout "pl" ) )
+ ( targets ( list "/boot/efi" ) ) ) )
+ ( mapped-devices
+ ( list
+ ( mapped-device
+ ( source "/dev/sda2" )
+ ( target "izumi" )
+ ( type luks-device-mapping ) ) ) )
+ ( file-systems
+ ( append
+ %base-file-systems
+ ( list
+ ( file-system
+ ( device "/dev/sda1" )
+ ( mount-point "/boot/efi" )
+ ( type "vfat" ) )
+ ( file-system
+ ( dependencies mapped-devices )
+ ( device "/dev/mapper/izumi" )
+ ( mount-point "/" )
+ ( type "xfs" ) ) ) ) )
+ ( firmware ( list linux-firmware ) )
+ ( groups
+ ( append
+ %base-groups
+ ( list
+ ( user-group
+ ( name "vmail" )
+ ( system? #t ) )) ) )
+ ( host-name "izumi" )
+ ( initrd microcode-initrd )
+ ( kernel linux )
+ ( keyboard-layout ( keyboard-layout "pl" ) )
+ ( locale "pl_PL.utf8" )
+ ( services
+ ( append
+ ( modify-services
+ %desktop-services
+ ( elogind-service-type
+ configuration =>
+ ( elogind-configuration
+ ( inherit configuration )
+ ( handle-lid-switch 'ignore )
+ ( handle-lid-switch-docked 'ignore )
+ ( handle-lid-switch-external-power 'ignore ) ) )
+ ( gdm-service-type
+ configuration =>
+ ( gdm-configuration
+ ( inherit configuration )
+ ( auto-suspend? #f )
+ ( wayland? #t ) ) )
+ ( guix-service-type
+ configuration =>
+ ( let*
+ ( ( non-guix.pub
+ ( string-append
+ "( public-key ( ecc ( curve Ed25519 )"
+ "( q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98# ) ) )" ) )
+ ( authorized-keys
+ ( append
+ %default-authorized-guix-keys
+ ( list ( plain-file "non-guix.pub" non-guix.pub ) ) ) )
+ ( extra-options
+ ( list "--gc-keep-derivations=yes" "--gc-keep-outputs=yes" ) )
+ ( substitute-urls
+ ( append
+ %default-substitute-urls
+ ( list "https://substitutes.nonguix.org" ) ) ) )
+ ( guix-configuration
+ ( inherit configuration )
+ ( authorized-keys authorized-keys )
+ ( extra-options extra-options )
+ ( substitute-urls substitute-urls ) ) ) ) )
+ ( wip-mail-services
+ #:interface "enp1s0"
+ #:domain "marekpasnikowski.pl" )
+ ( list
+ ( service certbot-service-type
+ ( certbot-configuration
+ ( certificates
+ ( list
+ ( certificate-configuration
+ ( deploy-hook
+ ( program-file
+ "nginx-deploy-hook"
+ #~
+ ( let
+ ( ( pid ( call-with-input-file "/var/run/nginx/pid" read ) ) )
+ ( kill pid SIGHUP ) ) ) )
+ ( domains
+ ( list
+ "marekpasnikowski.pl"
+ "git.marekpasnikowski.pl"
+ "radicale.marekpasnikowski.pl" ) ) ) ) )
+ ( email certbot-mail )
+ ( webroot "/srv/www/marek/marekpasnikowski.pl" ) ) )
+ ( service cgit-service-type
+ ( cgit-configuration
+ ( nginx
+ ( list
+ ( nginx-server-configuration
+ ( locations
+ ( list
+ ( nginx-location-configuration
+ ( body
+ ( list
+ "fastcgi_param HTTP_HOST $server_name ;"
+ "fastcgi_param PATH_INFO $uri ;"
+ "fastcgi_param QUERY_STRING $args ;"
+ "fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi ;"
+ "fastcgi_pass 127.0.0.1:9000 ;" ) )
+ ( uri "@cgit" ) )
+ ( nginx-location-configuration
+ ( body ( list "root /srv/www/marek/marekpasnikowski.pl/ ;" ) )
+ ( uri "/.well-known" ) ) ) )
+ ( listen ( list "192.168.10.2:443 ssl" ) )
+ ( root cgit )
+ ( server-name ( list "git.marekpasnikowski.pl" ) )
+ ( ssl-certificate
+ "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem" )
+ ( ssl-certificate-key
+ "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem" )
+ ( try-files ( list "$uri" "@cgit" ) ) ) ) )
+ ( repositories
+ ( list
+ ( repository-cgit-configuration
+ ( hide? #t )
+ ( path "/srv/git/marek/packages" ) ) ) )
+ ( repository-directory "/var/lib/gitolite/repositories" ) ) )
+ ( service gitolite-service-type
+ ( gitolite-configuration
+ ( admin-pubkey gitolite-keys )
+ ( rc-file ( gitolite-rc-file ( umask #o0022 ) ) ) ) )
+ ( service gnome-desktop-service-type )
+ ( service nginx-service-type
+ ( nginx-configuration
+ ( server-blocks
+ ( list
+ ;; Top-Level
+ ( nginx-server-configuration
+ ( locations
+ ( list
+ ( nginx-location-configuration
+ ( uri "/.well-known" )
+ ( body
+ ( list "root /srv/www/marek/marekpasnikowski.pl ;" ) ) ) ) )
+ ( listen ( list "192.168.10.2:443 ssl" ) )
+ ( root "/srv/www/marek/marekpasnikowski.pl" )
+ ( server-name ( list "marekpasnikowski.pl" ) )
+ ( ssl-certificate
+ "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem" )
+ ( ssl-certificate-key
+ "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem" ) )
+ ;; Radicale
+ ( nginx-server-configuration
+ ( locations
+ ( list
+ ( nginx-location-configuration
+ ( body
+ ( list
+ "proxy_pass http://localhost:5232/ ;"
+ "proxy_set_header X-Script-Name \"\" ;"
+ "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;"
+ "proxy_set_header Host $http_host ;"
+ "proxy_pass_header Authorization ;" ) )
+ ( uri "/" ) )
+ ( nginx-location-configuration
+ ( body
+ ( list "root /srv/www/marek/marekpasnikowski.pl ;" ) )
+ ( uri "/.well-known" ) ) ) )
+ ( listen ( list "192.168.10.2:443 ssl" ) )
+ ( server-name ( list "radicale.marekpasnikowski.pl" ) ) ) ) ) ) )
+ ( service openssh-service-type )
+ ( service radicale-service-type
+ ( radicale-configuration
+ ( config-file
+ ( mixed-text-file
+ "radicale.conf"
+ "[auth]\n"
+ "type = htpasswd\n"
+ "htpasswd_filename = " radicale-keys "\n"
+ "htpasswd_encryption = plain\n"
+ "\n"
+ "[server]\n"
+ "hosts = localhost:5232\n" ) ) ) )
+ ( simple-service 'base-profile profile-service-type
+ ( append %base-packages
+ ( list ) ) )
+ ( simple-service
+ 'nss-profile
+ profile-service-type
+ ( list nss-certs ) )
+ ( simple-service
+ 'etc-files
+ etc-service-type
+ ( list
+ `( "mailname" ,( plain-file "mailname" "marekpasnikowski.pl\n" ) )
+ `( "dovecot-passwd" ,dovecot-keys ) ) ) ) ) )
+ ( sudoers-file ( local-file "system-files/sudoers" ) )
+ ( swap-devices
+ ( list
+ ( swap-space
+ ( target "/dev/sda3" ) ) ) )
+ ( timezone "Europe/Warsaw" )
+ ( users
+ ( append
+ %base-user-accounts
+ ( list
+ ( user-account
+ ( comment "vmail" )
+ ( group "vmail" )
+ ( home-directory "/home/vmail" )
+ ( name "vmail" )
+ ( system? #t ) )
+ ( user-account
+ ( comment "Marek Paśnikowski" )
+ ( group "users" )
+ ( home-directory "/home/marek" )
+ ( name "marek" )
+ ( supplementary-groups
+ ( list "audio" "netdev" "video" "wheel" ) ) ) ) ) ) )
+#+END_SRC
+
+#+NAME: OPENSMTPD-CONFIGURATION-FILE
+#+BEGIN_SRC conf :tangle system-files/smtpd.conf
+ # The prefix on GUIX is not the default one — it is /etc .
+ table aliases file:/etc/aliases
+
+ # The mail certificates are issued by Let‘s Encrypt and served by NGINX
+ pki marekpasnikowski.pl cert "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem"
+ pki marekpasnikowski.pl key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem"
+
+ # Listen for local messages.
+ listen on lo
+
+ # Listen for messages from the internet.
+ listen on enp1s0 tls port 25 pki "marekpasnikowski.pl"
+ listen on enp1s0 smtps port 465 pki "marekpasnikowski.pl"
+
+ # There is no filtering in the design, so the two actions are enough.
+ action receive maildir alias <aliases>
+ action send relay
+
+ # Match incoming messages.
+ match from local for local action receive
+ match from any for domain "marekpasnikowski.pl" action receive
+
+ # Match outgoing messages.
+ match for any action send
+#+END_SRC
+
+* [[https://guix.gnu.org/manual/en/html_node/Home-Configuration.html][13 Home Configuration]]
+
+#+BEGIN_SRC scheme :tangle home-configuration.scm
+ (use-modules
+ (gnu home services shells)
+ (gnu packages)
+ (gnu packages emacs)
+ (gnu packages fonts)
+ (gnu packages gnome)
+ (gnu packages gnupg)
+ (gnu packages noweb)
+ (gnu packages version-control)
+ (nongnu packages mozilla))
+
+ <<EMACS-GUIX-MODULES>>
+ <<EMACS-ORG-FC-TN-MODULES>>
+ <<ESSENTIAL-HOME-MODULES>>
+ <<SHELLS-MODULES>>
+
+ (home-environment
+ (packages
+ (list
+ dconf-editor
+ emacs
+ emacs-org-modern
+ emacs-paredit
+ firefox
+ font-google-noto
+ font-google-noto-emoji
+ font-google-noto-sans-cjk
+ font-google-noto-serif-cjk
+ git
+ gnupg
+ gnome-tweaks
+ noweb
+ pinentry
+ pwgen))
+ (services
+ (append
+ <<ESSENTIAL-HOME-SERVICES>>
+ <<SHELLS>>)))
+#+END_SRC
+
+** [[https://guix.gnu.org/manual/en/html_node/Home-Services.html][13.3 Home Services]]
+
+#+NAME: ESSENTIAL-HOME-SERVICES
+#+BEGIN_SRC scheme
+ (list
+ <<EMACS-HOME-PROFILE>>
+ <<HOME-FILES-SERVICE-TYPE>>
+ (simple-service
+ 'environment-variables
+ home-environment-variables-service-type
+ `(("EDITOR" . "emacsclient -nw"))))
+#+END_SRC
+
+#+NAME: SHELLS
+#+BEGIN_SRC scheme
+ (list
+ <<HOME-BASH-SERVICE-TYPE>>)
+#+END_SRC
+
+*** [[https://guix.gnu.org/manual/en/html_node/Essential-Home-Services.html][13.3.1 Essential Home Services]]
+
+#+NAME: ESSENTIAL-HOME-MODULES
+#+BEGIN_SRC scheme
+ (use-modules
+ (gnu services)
+ (gnu home services)
+ (gnu packages password-utils)
+ (guix gexp))
+#+END_SRC
+
+#+NAME: EMACS-HOME-PROFILE
+#+BEGIN_SRC scheme
+ (simple-service
+ 'emacs-home-profile
+ home-profile-service-type
+ (append
+ <<EMACS-GUIX-PACKAGES>>
+ <<EMACS-ORG-FC-TN-PACKAGES>>))
+#+END_SRC
+
+#+NAME: HOME-FILES-SERVICE-TYPE
+#+BEGIN_SRC scheme
+ ( simple-service
+ 'home-files
+ home-files-service-type
+ ( list
+ ( list ".emacs" ( local-file "home-files/emacs-configuration.el" ) )
+ ( list ".config/guix/channels.scm" ( local-file "channels.scm" ) )
+ ( list ".gitconfig" ( local-file "home-files/gitconfig"))
+ ( list
+ ".config/git/ignore"
+ ;; https://github.com/github/gitignore/blob/main/Global/Emacs.gitignore
+ ( local-file "home-files/git-ignore.conf" ) ) ) )
+#+END_SRC
+
+*** [[https://guix.gnu.org/manual/en/html_node/Shells-Home-Services.html][13.3.2 Shells]]
+
+#+NAME: SHELLS-MODULES
+#+BEGIN_SRC scheme
+ (use-modules
+ (gnu home services shells)
+ (gnu services))
+#+END_SRC
+
+#+NAME: HOME-BASH-SERVICE-TYPE
+#+BEGIN_SRC scheme
+ (let*
+ ((and "&& ")
+ (collect-garbage "sudo guix gc -d 7d ")
+ (configuration-prefix "/home/marek/src/izumi/")
+ (pull-guix "guix pull ")
+ (reconfigure-home
+ (string-append
+ "guix home reconfigure "
+ configuration-prefix
+ "home-configuration.scm "))
+ (reconfigure-system
+ (string-append
+ "sudo guix system reconfigure "
+ configuration-prefix
+ "system-configuration.scm "
+ and
+ "sudo chmod 751 /var/lib/gitolite "
+ and
+ "echo 'WARNING: Upstream the correct permission bits to gitolite.'"))
+ (update-system
+ (string-append
+ pull-guix
+ and
+ reconfigure-system
+ and
+ reconfigure-home
+ and
+ collect-garbage)))
+ (simple-service
+ 'bash-extension
+ home-bash-service-type
+ (home-bash-extension
+ (aliases
+ `(("collect-garbage" . ,collect-garbage)
+ ("edit" . "$EDITOR")
+ ("pull-guix" . ,pull-guix)
+ ("reconfigure-home" . ,reconfigure-home)
+ ("reconfigure-system" . ,reconfigure-system)
+ ("update-system" . ,update-system)))
+ (bashrc (list (plain-file "source-home-profile" "source ~/.profile\n"))))))
+#+END_SRC
+
+* [[https://www.leonrische.me/fc/][Emacs-Org-FC-TN]]
+
+#+NAME: EMACS-ORG-FC-TN-MODULES
+#+BEGIN_SRC scheme
+ (use-modules
+ (gnu)
+ (gnu home services)
+ (guix build-system emacs)
+ (guix git-download)
+ ((guix licenses)
+ #:prefix license:)
+ (guix packages))
+
+ (use-package-modules base emacs-xyz gawk)
+#+END_SRC
+
+#+NAME: EMACS-ORG-FC-TN-PACKAGES
+#+BEGIN_SRC scheme
+ (list
+ (let
+ ((commit* "wip-algo-tn"))
+ (package
+ (name "emacs-org-fc")
+ (version (git-version "0.1.0" "0" commit*))
+ (source
+ (origin
+ (method git-fetch)
+ (uri
+ (git-reference
+ (url "https://git.marekpasnikowski.pl/org-fc.git")
+ (commit commit*)))
+ (file-name (git-file-name name version))
+ (sha256 (base32 "0x8bxjh4r1wqh48f69x8k6gxfpixhwci365n0rh827csfjaqs5hg"))))
+ (build-system emacs-build-system)
+ (arguments
+ (list
+ #:include #~ (cons* "\\.awk$" "\\.org$" %default-include)
+ #:exclude #~ (cons "^test/" %default-exclude)
+ #:tests? #t
+ #:test-command
+ #~
+ (list
+ "emacs"
+ "--batch"
+ "-L" "."
+ "-L" "tests/"
+ "-l" "tests/org-fc-filter-test.el"
+ "-l" "tests/org-fc-indexer-test.el"
+ "-l" "tests/org-fc-review-data-test.el"
+ "-f" "ert-run-tests-batch-and-exit")
+ #:phases
+ #~
+ (modify-phases
+ %standard-phases
+ (add-after
+ 'unpack
+ 'qualify-paths
+ (lambda*
+ (#:key inputs
+ #:allow-other-keys)
+ (substitute*
+ "org-fc-awk.el"
+ (("\"find ")
+ (string-append
+ "\""
+ (search-input-file inputs "/bin/find")
+ " "))
+ (("\"gawk ")
+ (string-append
+ "\""
+ (search-input-file inputs "/bin/gawk")
+ " "))
+ (("\"xargs ")
+ (string-append
+ "\""
+ (search-input-file inputs "/bin/xargs")
+ " "))))))))
+ (inputs (list findutils gawk))
+ (propagated-inputs (list emacs-hydra))
+ (home-page "https://www.leonrische.me/fc/index.html")
+ (synopsis "Spaced repetition system for Emacs Org mode")
+ (description
+ (string-append
+ "Org-fc is a spaced-repetition system for Emacs' Org mode.\n"
+ "It allows you to mark headlines in a file as flashcards, turning pieces of\n"
+ "knowledge you want to learn into a question-answer test. These cards are\n"
+ "reviewed at regular interval. After each review, the next review interval is\n"
+ "calculated based on how well you remembered the contents of the card.\n"))
+ (license license:gpl3+))))
+#+END_SRC
+
+* [[https://emacs-guix.gitlab.io/website/manual/latest/html_node/index.html][Emacs-Guix]]
+
+** [[https://emacs-guix.gitlab.io/website/manual/latest/html_node/Installation.html][2. Installation]]
+
+#+NAME: EMACS-GUIX-MODULES
+#+BEGIN_SRC scheme
+ (use-modules
+ (gnu)
+ (gnu home services))
+
+ (use-package-modules emacs-xyz)
+
+ (use-service-modules)
+#+END_SRC
+
+#+NAME: EMACS-GUIX-PACKAGES
+#+BEGIN_SRC scheme
+ (list emacs-guix emacs-nix-mode)
+#+END_SRC
+
+* EOF