(define-module (systems izumi system-configuration) #:use-module (suweren commons sudoers)) (define smtpd-keys "/secrets/smtpd") (define radicale-keys "/secrets/radicale/keys") (define dovecot-keys "/secrets/dovecot") ( use-modules ( 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 nginx-accounts (list (user-group (name "nginx") (system? #t)) (user-account (name "nginx") (group "nginx") (supplementary-groups '("git")) (system? #t) (comment "nginx server user") (home-directory "/var/empty") (shell (file-append (specification->package "shadow") "/sbin/nologin"))))) (define nginx-service-type* (service-type (inherit nginx-service-type) (extensions (map (lambda (extension) (if (eq? (service-extension-target extension) account-service-type) (service-extension account-service-type (const nginx-accounts)) extension)) (service-type-extensions nginx-service-type))))) (define hosts-izumi (local-file "system-files/hosts")) ( define-record-type* 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 ( ( $ 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 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 ( ( $ 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 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 \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 \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 \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 mail-from \"@marekpasnikowski.pl\" for any reject\n" "\n" "# If it comes from someone on the blacklist\n" "match from any mail-from 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" "/secrets/dovecot" ) ) ( 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 " ( 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 (service-type (inherit certbot-service-type) (extensions (map (lambda (extension) (if (eq? (service-extension-target extension) nginx-service-type) (service-extension nginx-service-type* (@@ (gnu services certbot) certbot-nginx-server-configurations)) extension)) (service-type-extensions 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 "marek@marekpasnikowski.pl" ) ( webroot "/srv/www/marek/marekpasnikowski.pl" ) ) ) (service (service-type (inherit cgit-service-type) (extensions (map (lambda (extension) (if (eq? (service-extension-target extension) nginx-service-type) (service-extension nginx-service-type* cgit-configuration-nginx-config) extension)) (service-type-extensions cgit-service-type)))) ( cgit-configuration ( nginx ( list ( nginx-server-configuration ( locations ( list ( git-http-nginx-location-configuration ( git-http-configuration ( git-root "/var/lib/gitolite/repositories" ) ( uri-path "/git" ) ) ) ( 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 fcgiwrap-service-type (fcgiwrap-configuration (user "git") (group "git"))) ( service gitolite-service-type ( gitolite-configuration ( rc-file ( gitolite-rc-file ( umask #o0027 ) ) ) ( admin-pubkey ( plain-file "gitolite-admin.pub" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK4THTYnHCc/ihCJNKJtGTNu1zCnLndbMHnxnrxzJk+N marek@izumi\n") ) ) ) ( 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 ( auth ( radicale-auth-configuration ( type 'htpasswd ) ( htpasswd-filename radicale-keys ) ( htpasswd-encryption 'plain ) ) ) ) ) ( 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" ) ) ) ) ) ) ) ( sudoers-file %sudoers-specification* ) ( 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" ) ) ) ) ) ) )