aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/xyz/euandreh/queue.scm796
1 files changed, 749 insertions, 47 deletions
diff --git a/src/xyz/euandreh/queue.scm b/src/xyz/euandreh/queue.scm
index 7a5f60d..a752b2d 100644
--- a/src/xyz/euandreh/queue.scm
+++ b/src/xyz/euandreh/queue.scm
@@ -1,6 +1,6 @@
(define-module (xyz euandreh queue)
+ #:use-module ((gnu build linux-container) #:prefix container:)
#:use-module ((guix licenses) #:prefix license:)
- ;; #:use-module ((nonguix licenses) #:prefix ng-license:)
#:use-module ((srfi srfi-1) #:prefix srfi-1:)
#:use-module (guix build-system gnu)
#:use-module (guix build-system python)
@@ -360,7 +360,7 @@ collections.OrderedDict that works in Python 2.4-2.6.")
python-pytz
python-tornado))
(home-page "https://python-telegram-bot.org/")
- (synopsis "We have made you a wrapper you can't refuse")
+ (synopsis "Python library to interface with the Telegram Bot API")
(description "We have made you a wrapper you can't refuse")
(license #f)))
@@ -384,7 +384,7 @@ collections.OrderedDict that works in Python 2.4-2.6.")
#~(begin
(use-modules (guix build utils))
(format (current-error-port)
- "Setting ownership and permission for \"/etc/passwd\".~%")
+ "Setting ownership and permission for \"/etc/shadow\".~%")
(chown "/etc/shadow"
(passwd:uid (getpwnam "root"))
(group:gid (getgrnam #$group)))
@@ -429,14 +429,22 @@ collections.OrderedDict that works in Python 2.4-2.6.")
(supplementary-groups cyrus-sasl-configuration-supplementary-groups (default '("etc-shadow")))
(authmech cyrus-sasl-configuration-authmech (default "shadow"))
(services cyrus-sasl-configuration-services (default '()))
- (state-dir cyrus-sasl-configuration-state-dir (default "/var/lib/saslauthd")))
+ (config-dirname cyrus-sasl-configuration-config-dirname (default "sasl2"))
+ (run-directory cyrus-sasl-configuration-run-directory (default "/var/run/saslauthd"))
+ (run-in-container? cyrus-sasl-configuration-run-in-container? (default #t))
+ (container-name cyrus-sasl-configuration-container-name (default "saslauthd"))
+ (container-namespaces cyrus-sasl-configuration-container-namespaces (default %namespaces))
+ (extra-mappings cyrus-sasl-configuration-extra-mappings (default '())))
+
(define (cyrus-sasl-etc-files config)
+ ;; FIXME: support opaque files
+ ;; FIXME: extend this with postfix instead of making postfix add here
(match-record config <cyrus-sasl-configuration>
- (services state-dir)
- `(("sasl2"
+ (services config-dirname run-directory)
+ `((,config-dirname
,(file-union
- "cyrus-sasl"
+ config-dirname
(map (lambda (service-config)
(match-record service-config <cyrus-service-configuration>
(name authmech log-level)
@@ -445,21 +453,21 @@ collections.OrderedDict that works in Python 2.4-2.6.")
(format #f
"pwcheck_method: ~a~%saslauthd_path: ~a/mux~%log_level: ~a~%"
authmech
- state-dir
+ run-directory
log-level)))))
services))))))
(define (cyrus-sasl-activation config)
(match-record config <cyrus-sasl-configuration>
- (user state-dir)
+ (user run-directory)
#~(begin
(use-modules (guix build utils))
(let ((user (getpwnam #$user)))
(format (current-error-port)
- "Creating Cyrus SASL socket directory: \"~a\".~%" #$state-dir)
- (mkdir-p #$state-dir)
- (chown #$state-dir (passwd:uid user) (passwd:gid user))
- (chmod #$state-dir #o755)))))
+ "Creating Cyrus SASL socket directory: \"~a\".~%" #$run-directory)
+ (mkdir-p #$run-directory)
+ (chown #$run-directory (passwd:uid user) (passwd:gid user))
+ (chmod #$run-directory #o755)))))
(define (cyrus-sasl-accounts config)
(match-record config <cyrus-sasl-configuration>
@@ -471,31 +479,60 @@ collections.OrderedDict that works in Python 2.4-2.6.")
(supplementary-groups supplementary-groups)
(comment "Cyrus SASL system user")
(home-directory "/var/empty")
- (shell (file-append shadow "/sbin/nologin"))
+ (create-home-directory? #f)
+ (shell
+ (file-append shadow "/sbin/nologin"))
(system? #t))
(user-group
(name group)
(system? #t)))))
+
(define (cyrus-sasl-shepherd-service config)
(match-record config <cyrus-sasl-configuration>
- (cyrus-sasl user group supplementary-groups authmech state-dir)
- (list
- (shepherd-service
- (provision '(cyrus-sasl))
- (documentation "FIXME:DOCUMENTATION")
- (start #~(make-forkexec-constructor
- (list
- #$(file-append cyrus-sasl "/sbin/saslauthd")
- "-a"
- #$authmech
- "-d"
- "-m"
- #$state-dir)
- #:user #$user
- #:group #$group
- #:supplementary-groups '(#$@supplementary-groups)))
- (stop #~(make-kill-destructor))))))
+ (cyrus-sasl user group supplementary-groups authmech config-dirname run-directory
+ services run-in-container? container-name container-namespaces extra-mappings)
+ (let* ((config-dir (string-append "/etc/" config-dirname))
+ (bin (file-append cyrus-sasl "/sbin/saslauthd"))
+ (cmd (if (not run-in-container?)
+ bin
+ (least-authority-wrapper
+ bin
+ #:name container-name
+ #:mappings (append
+ (list
+ (file-system-mapping
+ (source run-directory)
+ (target source)
+ (writable? #t))
+ (file-system-mapping
+ (source "/etc/passwd")
+ (target source))
+ (file-system-mapping
+ (source "/etc/shadow")
+ (target source)))
+ extra-mappings)
+ #:namespaces container-namespaces))))
+ (list
+ (shepherd-service
+ (provision '(cyrus-sasl))
+ (documentation "FIXME:DOCUMENTATION")
+ (start #~(make-forkexec-constructor
+ (list #$cmd "-a" #$authmech "-d" "-m" #$run-directory)
+ #:user #$user
+ #:group #$group
+ #:supplementary-groups '(#$@supplementary-groups)))
+ (stop #~(make-kill-destructor))
+ (actions
+ (list
+ (shepherd-action
+ (name 'configuration)
+ (documentation "FIXME:DOCUMENTATION")
+ (procedure
+ #~(lambda _
+ (for-each (lambda (name)
+ (format #t "~a/~a~%" #$config-dir name))
+ (map cyrus-service-configuration-name #$services))))))))))))
(define cyrus-sasl-service-type
(service-type
@@ -528,16 +565,20 @@ collections.OrderedDict that works in Python 2.4-2.6.")
dkimproxyout-configuration
make-dkimproxyout-configuration
dkimproxyout-configuration?
- (dkimproxy dkimproxyout-configuration-dkimproxy (default dkimproxy))
- (user dkimproxyout-configuration-user (default "dkimproxyout"))
- (group dkimproxyout-configuration-group (default "dkimproxyout"))
- (config-name dkimproxyout-configuration-config-name (default "dkimproxyout.conf"))
- (listen dkimproxyout-configuration-listen (default "127.0.0.1:10027"))
- (relay dkimproxyout-configuration-relay (default "127.0.0.1:10028"))
- (domains dkimproxyout-configuration-domains (default (list (gethostname))))
- (selector dkimproxyout-configuration-selector (default "dkimproxyout"))
- (key-size dkimproxyout-configuration-key-size (default 2048))
- (data-directory dkimproxyout-configuration-data-directory (default "/var/lib/dkimproxyout")))
+ (dkimproxy dkimproxyout-configuration-dkimproxy (default dkimproxy))
+ (user dkimproxyout-configuration-user (default "dkimproxyout"))
+ (group dkimproxyout-configuration-group (default "dkimproxyout"))
+ (config-name dkimproxyout-configuration-config-name (default "dkimproxyout.conf"))
+ (listen dkimproxyout-configuration-listen (default "127.0.0.1:10027"))
+ (relay dkimproxyout-configuration-relay (default "127.0.0.1:10028"))
+ (domains dkimproxyout-configuration-domains (default (list (gethostname))))
+ (selector dkimproxyout-configuration-selector (default "dkimproxyout"))
+ (key-size dkimproxyout-configuration-key-size (default 2048))
+ (data-directory dkimproxyout-configuration-data-directory (default "/var/lib/dkimproxyout"))
+ (run-in-container? dkimproxyout-configuration-run-in-container? (default #f))
+ (container-name dkimproxyout-configuration-container-name (default "dkimproxyout"))
+ (container-namespaces dkimproxyout-configuration-container-namespaces (default (srfi-1:fold delq %namespaces '(net))))
+ (extra-mappings dkimproxyout-configuration-extra-mappings (default '())))
(define (generate-out.cf config)
(match-record config <dkimproxyout-configuration>
@@ -578,7 +619,9 @@ keyfile ~a/private.key
(group group)
(comment "DKIMproxy.out signing system user")
(home-directory "/var/empty")
- (shell (file-append shadow "/sbin/nologin"))
+ (create-home-directory? #f)
+ (shell
+ (file-append shadow "/sbin/nologin"))
(system? #t))
(user-group
(name group)
@@ -599,6 +642,8 @@ keyfile ~a/private.key
(let ((private-key (string-append #$data-directory "/private.key"))
(public-key (string-append #$data-directory "/public.key")))
(unless (file-exists? private-key)
+ (format (current-error-port)
+ "The public/private keypair doesn't exist yet. Generating one...~%")
(cond
((zero? (system* #$(file-append openssl "/bin/openssl")
"genrsa"
@@ -624,18 +669,35 @@ keyfile ~a/private.key
(chmod private-key #o400)
(chmod public-key #o644))))))
+
(define (dkimproxyout-shepherd-service config)
(match-record config <dkimproxyout-configuration>
- (dkimproxy user group config-name)
- (let ((config-file (string-append "/etc/" config-name)))
+ (dkimproxy user group config-name data-directory
+ run-in-container? container-name container-namespaces extra-mappings)
+ (let* ((config-file (string-append "/etc/" config-name))
+ (bin (file-append dkimproxy "/bin/dkimproxy.out"))
+ (cmd (if (not run-in-container?)
+ bin
+ (least-authority-wrapper
+ bin
+ #:name container-name
+ #:mappings (append
+ (list
+ (file-system-mapping
+ (source config-file)
+ (target source))
+ (file-system-mapping
+ (source
+ (string-append data-directory "/private.key"))
+ (target source)))
+ extra-mappings)
+ #:namespaces container-namespaces))))
(list
(shepherd-service
(provision '(dkimproxyout))
(documentation "FIXME:DOCUMENTATION")
(start #~(make-forkexec-constructor
- (list
- #$(file-append dkimproxy "/bin/dkimproxy.out")
- "--conf_file" #$config-file)
+ (list #$cmd "--conf_file" #$config-file)
#:user #$user
#:group #$group))
(stop #~(make-kill-destructor))
@@ -648,6 +710,7 @@ keyfile ~a/private.key
#~(lambda _
(format #t "~a~%" #$config-file)))))))))))
+
(define-public dkimproxyout-service-type
(service-type
(name 'dkimproxyout)
@@ -668,6 +731,645 @@ keyfile ~a/private.key
+
+
+
+
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Postfix ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+(define-record-type* <postfix-configuration>
+ postfix-configuration
+ make-postfix-configuration
+ postfix-configuration?
+ (postfix postfix-configuration-postfix (default postfix))
+ (set-sendmail? postfix-configuration-set-sendmail? (default #t))
+ (master.cf-file postfix-configuration-master.cf-file (default #f))
+ (main.cf-file postfix-configuration-main.cf-file (default #f))
+ (master.cf-extra postfix-configuration-master.cf-extra (default ""))
+ (main.cf-extra postfix-configuration-main.cf-extra (default ""))
+ (config-dirname postfix-configuration-config-dirname (default "postfix"))
+ (data-directory postfix-configuration-data-directory (default "/var/lib/postfix"))
+ (queue-directory postfix-configuration-queue-directory (default "/var/spool/postfix"))
+ (user postfix-configuration-user (default "postfix"))
+ (group postfix-configuration-group (default "postfix"))
+ (setgid-group postfix-configuration-setgid-group (default "postdrop"))
+ (root-aliases postfix-configuration-root-aliases (default '("abuse" "admin" "hostmaster" "postmaster")))
+ (cert-file postfix-configuration-cert-file (default #f))
+ (key-file postfix-configuration-key-file (default #f))
+ (hostname postfix-configuration-hostname (default (gethostname)))
+ (run-in-container? postfix-configuration-run-in-container? (default #f))
+ (container-name postfix-configuration-container-name (default "postfix"))
+ (container-namespaces postfix-configuration-container-namespaces (default (srfi-1:fold delq %namespaces '(net))))
+ (extra-mappings postfix-configuration-extra-mappings (default '())))
+
+; FIXME: hardcoded value of dkimproxy listen and relay
+(define (generate-master.cf config)
+ (match-record config <postfix-configuration>
+ (master.cf-extra)
+ (format #f
+ #"-
+ # ============================================================================================================
+ # service type private unpriv chroot wakeup maxproc command + args
+ # (yes) (yes) (no) (never) (100)
+ # =============================================================================================================
+
+
+ anvil unix - - n - 1 anvil
+ bounce unix - - n - 0 bounce
+ cleanup unix n - n - 0 cleanup
+ defer unix - - n - 0 bounce
+ discard unix - - n - - discard
+ error unix - - n - - error
+ flush unix n - n 1000? 0 flush
+ lmtp unix - - n - - lmtp
+ local unix - n n - - local
+ # FIXME: replace 127.0.0.1 with localhost
+ pickup unix n - n 60 1 pickup
+ -o content_filter=dksign:[127.0.0.1]:10027
+ proxymap unix - - n - - proxymap
+ proxywrite unix - - n - 1 proxymap
+ qmgr unix n - n 300 1 qmgr
+ relay unix - - n - - smtp -o syslog_name=postfix/relay
+ retry unix - - n - - error
+ rewrite unix - - n - - trivial-rewrite
+ scache unix - - n - 1 scache
+ showq unix n - n - - showq
+ smtp inet n - n - - smtpd -o syslog_name=postfix/smtp
+ smtp unix - - n - - smtp
+ submission inet n - n - - smtpd -o syslog_name=postfix/submission
+ -o smtpd_tls_security_level=encrypt
+ -o content_filter=dksign:[127.0.0.1]:10027
+ tlsmgr unix - - n 1000? 1 tlsmgr
+ trace unix - - n - 0 bounce
+ verify unix - - n - 1 verify
+ virtual unix - n n - - virtual
+ postlog unix-dgram n - n - 1 postlogd
+
+ # FIXME: doesn't work for sendmail -t in localhost
+ dksign unix - - n - - smtp
+ -o syslog_name=postfix/dkimproxyout-listen
+ -o smtp_send_xforward_command=yes
+ -o smtp_discard_ehlo_keywords=8bitmime,starttls
+ 127.0.0.1:10028 inet n - n - - smtpd
+ -o syslog_name=postfix/dkimproxyout-relay
+ -o content_filter=
+ -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
+ -o smtpd_helo_restrictions=
+ -o smtpd_client_restrictions=
+ -o smtpd_sender_restrictions=
+ -o smtpd_recipient_restrictions=permit_mynetworks,reject
+ -o mynetworks=127.0.0.0/8
+ -o smtpd_authorized_xforward_hosts=127.0.0.0/8
+ ~a
+ "#
+ master.cf-extra)))
+
+(define (cert-for config)
+ (match-record config <postfix-configuration>
+ (cert-file hostname)
+ (or cert-file (format #f "/etc/letsencrypt/live/~a/fullchain.pem" hostname))))
+
+(define (key-for config)
+ (match-record config <postfix-configuration>
+ (key-file hostname)
+ (or key-file (format #f "/etc/letsencrypt/live/~a/privkey.pem" hostname))))
+
+(define (generate-main.cf config)
+ (match-record config <postfix-configuration>
+ (postfix queue-directory data-directory user setgid-group hostname main.cf-extra)
+ (format #f
+ #"-
+ compatibility_level = 3.6
+
+ queue_directory = ~a
+ data_directory = ~a
+ mail_owner = ~a
+ setgid_group = ~a
+
+ myhostname = ~a
+ mydestination = $myhostname, $mydomain, localhost.$mydomain, localhost
+
+ alias_maps = hash:/etc/aliases
+ # alias_maps = hash:/etc/aliases, static:andreh
+
+ mail_spoo_directory = /var/mail/
+
+ header_checks = regexp:{ { /^Received:.*/ IGNORE }, { /^X-Originating-IP:.*/ IGNORE } }
+
+ smtpd_use_tls = yes
+ smtpd_tls_cert_file = ~a
+ smtpd_tls_key_file = ~a
+ smtp_use_tls = $smtpd_use_tls
+ smtp_tls_cert_file = $smtpd_tls_cert_file
+ smtp_tls_key_file = $smtpd_tls_key_file
+
+ smtp_tls_security_level = may
+
+ recipient_delimiter = +
+
+ # smtpd_sasl_security_options = FIXME: deny all
+ smtpd_sasl_tls_security_options = noanonymous
+ # FIXME: shouldn't this be "encrypt"?
+ smtpd_tls_security_level = may
+ smtpd_tls_auth_only = yes
+
+ smtpd_relay_restrictions = $smtpd_recipient_restrictions
+ smtpd_recipient_restrictions = permit_mynetworks,
+ permit_sasl_authenticated, reject_unauth_destination
+ smtpd_sasl_auth_enable = yes
+ cyrus_sasl_config_path = /etc/sasl2
+ debug_peer_list = 127.0.0.1
+
+ milter_default_action = accept
+ # smtpd_milters = FIXME
+ ~a
+ "#
+ queue-directory
+ data-directory
+ user
+ setgid-group
+ hostname
+
+ (cert-for config)
+ (key-for config)
+ main.cf-extra)))
+
+(define (postfix-etc-files config)
+ (match-record config <postfix-configuration>
+ (master.cf-file main.cf-file config-dirname)
+ `((,config-dirname
+ ,(file-union
+ config-dirname
+ `(("master.cf" ,(plain-file "master.cf" (or master.cf-file (generate-master.cf config))))
+ ("main.cf" ,(plain-file "main.cf" (or main.cf-file (generate-main.cf config))))))))))
+
+(define (postfix-accounts config)
+ (match-record config <postfix-configuration>
+ (user group setgid-group)
+ (list
+ (user-account
+ (name user)
+ (group group)
+ (comment "Postfix system user")
+ (home-directory "/var/empty")
+ (create-home-directory? #f)
+ (shell
+ (file-append shadow "/sbin/nologin"))
+ (system? #t))
+ (user-group
+ (name group)
+ (system? #t))
+ (user-group
+ (name setgid-group)
+ (system? #t)))))
+
+(define (postfix-setuid-programs config)
+ (match-record config <postfix-configuration>
+ (postfix setgid-group set-sendmail?)
+ (append
+ (list
+ (setuid-program
+ (program (file-append postfix "/sbin/postdrop"))
+ (setuid? #f)
+ (setgid? #t)
+ (group setgid-group))
+ (setuid-program
+ (program (file-append postfix "/sbin/postqueue"))
+ (setuid? #f)
+ (setgid? #t)
+ (group setgid-group)))
+ (if set-sendmail?
+ (list
+ (setuid-program
+ (program (file-append postfix "/sbin/sendmail"))
+ (setuid? #f)
+ (setgid? #t)
+ (group setgid-group)))
+ '()))))
+
+(define (postfix-activation config)
+ (match-record config <postfix-configuration>
+ (queue-directory)
+ #~(begin
+ (use-modules (guix build utils))
+ (let ((user (getpwnam "root")))
+ (format (current-error-port)
+ "Creating Postfix queue directory: \"~a\".~%" #$queue-directory)
+ (mkdir-p #$queue-directory)
+ (chown #$queue-directory (passwd:uid user) (passwd:gid user))
+ (chmod #$queue-directory #o755)
+ (format (current-error-port)
+ "Creating email spool director: \"/var/mail\".~%")
+ (mkdir-p "/var/mail")
+ (format (current-error-port)
+ "Updating /etc/aliases: FIXME.~%")
+ ;; FIXME: add -c option
+#;
+ (invoke #$(file-append postfix "/sbin/postalias") "/etc/aliases")))))
+
+(define (postfix-shepherd-service config)
+ (match-record config <postfix-configuration>
+ (postfix config-dirname data-directory queue-directory
+ run-in-container? container-name container-namespaces extra-mappings)
+ (let* ((config-dir (string-append "/etc/" config-dirname))
+ (bin (file-append postfix "/sbin/postfix"))
+ (cmd (if (not run-in-container?)
+ bin
+ (least-authority-wrapper
+ bin
+ #:name container-name
+ #:mappings (append
+ (list
+ (file-system-mapping
+ (source data-directory)
+ (target source)
+ (writable? #t))
+ (file-system-mapping
+ (source queue-directory)
+ (target source)
+ (writable? #t)))
+ extra-mappings)
+ #:namespaces container-namespaces))))
+ (list
+ (shepherd-service
+ (provision '(postfix))
+ (documentation
+ #"-
+ Run the Postfix MTA.
+
+ This is the entrypoint for starting the "master" process. Then the
+ "master" process itself takes responsability of starting all the
+ required daemons and commands."#)
+ (start #~(make-forkexec-constructor
+ (list
+ #$(file-append postfix "/sbin/postfix")
+ "-c"
+ #$config-dir
+ "start-fg")
+ #:pid-file "/var/lib/postfix/master.lock"))
+ (stop #~(make-kill-destructor SIGKILL))
+ (actions
+ (list
+ (shepherd-action
+ (name 'configuration)
+ (documentation
+ #"-
+ FIXME:DOCUMENTATION
+ "#)
+ (procedure
+ #~(lambda _
+ (format #t "~a/master.cf~%" #$config-dir)
+ (format #t "~a/main.cf~%" #$config-dir))))
+ (shepherd-action
+ (name 'reload)
+ (documentation
+ #"-
+ Re-read the "master.cf" and "main.cf" configuration files.
+
+ Daemon processes terminate when possible, and when restarted
+ use the values of the new configuration files.
+
+ This live-reload option is usually preferable over a stop/start
+ cycle, as it incurs in no interruption of the running service."#)
+ (procedure
+ #~(lambda _
+ (invoke #$(file-append postfix "/sbin/postfix")
+ "-c"
+ #$config-dir
+ "reload")))))))))))
+
+(define (postfix-aliases config)
+ (match-record config <postfix-configuration>
+ (root-aliases)
+ (map (lambda (alias)
+ `(,alias "root"))
+ root-aliases)))
+
+
+(define (postfix-nginx-locations config)
+ (match-record config <postfix-configuration>)
+ (hostname)
+ (nginx-server-configuration
+ (server-name (list (string-append "mta-sts." hostname)))
+ (listen '("[::]:443 ssl http2" "443 ssl http2"))
+ (ssl-certificate (cert-for config))
+ (ssl-certificate-key (key-for config))
+ (locations
+ (list
+ (nginx-location-configuration
+ (uri "= /.well-known/mta-sts.txt")
+ (body
+ (list
+ (list "alias "
+ (plain-file
+ "mta-sts.txt"
+ (format #f #"-
+ version: STSv1
+ mode: enforce
+ mx: ~a
+ max_age: 604800
+ "#
+ hostname))
+ ";"))))))))
+
+(define (postfix-certificates config)
+ (match-record config <postfix-configuration>
+ (hostname)
+ (list
+ (certificate-configuration
+ (domains (list hostname (string-append "mta-sts." hostname)))))))
+
+(define (postfix-sasl-service _config)
+ (list
+ (cyrus-service-configuration
+ (name "smtpd.conf"))))
+
+
+(define postfix-service-type
+ (service-type
+ (name 'postfix)
+ (extensions
+ (list
+ (service-extension etc-service-type
+ postfix-etc-files)
+ (service-extension account-service-type
+ postfix-accounts)
+ (service-extension setuid-program-service-type
+ postfix-setuid-programs)
+ (service-extension activation-service-type
+ postfix-activation)
+ (service-extension mail-aliases-service-type
+ postfix-aliases)
+ (service-extension profile-service-type
+ (compose list postfix-configuration-postfix))
+ (service-extension shepherd-root-service-type
+ postfix-shepherd-service)
+ (service-extension nginx-service-type
+ postfix-nginx-locations)
+ (service-extension certbot-service-type
+ postfix-certificates)
+ (service-extension cyrus-sasl-service-type
+ postfix-sasl-services)))
+ (default-value (postfix-configuration))
+ (description
+ #"-
+ Run the Postfix MTA.
+
+ This is the top-level system service for Postfix.
+
+ It includes:
+ - populating /etc/postfix/ with read-only configuration files;
+ - the user and groups used by Postfix when handling email delivery;
+ - the special setgid binaries for daily usage, such as "sendmail";
+ - the Shepherd service for starting, stopping and *reloading* the
+ service without restarting it;
+ - the activation script for creating the required directories and
+ configuring them with the correct permissions;
+ - the binaries in the system profile so that one doesn't need to explicilty
+ include the package when the service is already enabled.
+
+ An extension to the log-rotation service isn't included: the default
+ rottlog configuration already includes /var/log/maillog in its routine,
+ so it is kept out.
+
+ The defaults of <postfix-configuration> provide sane default values for
+ most things, such as group names, data and queue directories, etc. When
+ used as-is, it creates a Postfix server that sends email from local users
+ of the domain provided by "/etc/hostname"."#)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dovecot ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+(define-record-type* <dovecot2-configuration>
+ dovecot2-configuration
+ make-dovecot2-configuration
+ dovecot2-configuration?
+ (dovecot2 dovecot2-configuration-dovecot2 (default dovecot))
+ (raw-file dovecot2-configuration-raw-file (default #f))
+ (extra-content dovecot2-configuration-extra-content (default ""))
+ (config-name dovecot2-configuration-config-name (default "dovecot2.conf"))
+ (user dovecot2-configuration-user (default "dovecot2"))
+ (group dovecot2-configuration-group (default "dovecot2"))
+ (auth-worker-group dovecot2-configuration-auth-worker-group (default "etc-shadow"))
+ (untrusted-user dovecot2-configuration-untrusted-user (default "dovenull2"))
+ (untrusted-group dovecot2-configuration-untrusted-group (default "dovenull2"))
+ (base-dir dovecot2-configuration-base-dir (default "/var/run/dovecot2"))
+ (state-dir dovecot2-configuration-state-dir (default "/var/lib/dovecot2"))
+ (hostname dovecot2-configuration-hostname (default (gethostname))))
+
+(define (generate-dovecot-config config)
+ (match-record config <dovecot2-configuration>
+ (user group auth-worker-group untrusted-user
+ hostname base-dir state-dir extra-content)
+ (format #f
+ #"-
+ protocols = imap
+
+ default_internal_user = ~a
+ default_internal_group = ~a
+ default_login_user = ~a
+ auth_mechanisms = plain login
+ auth_username_format = %n
+
+ passdb {
+ driver = shadow
+ }
+ userdb {
+ driver = passwd
+ }
+ service auth-worker {
+ group = ~a
+ }
+
+
+ ssl = required
+ ssl_cert = </etc/letsencrypt/live/~a/fullchain.pem
+ ssl_key = </etc/letsencrypt/live/~a/privkey.pem
+ ssl_dh = <~a/dhparam.pem
+
+ base_dir = ~a
+ state_dir = ~a
+
+ verbose_proctitle = yes
+
+ # FIXMEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
+ # mail_location = maildir:~~/Mail:INBOX=~~/Mail/Inbox:LAYOUT=fs
+ # mail_location = maildir:~~/Mail:INBOX=~~/Mail/Inbox:LAYOUT=fs
+
+ # FIXME:
+ # mail_plugins
+
+
+ namespace inbox {
+ inbox = yes
+ mailbox Drafts {
+ special_use = \Drafts
+ auto = subscribe
+ }
+ mailbox Sent {
+ special_use = \Sent
+ auto = subscribe
+ }
+ mailbox Archive {
+ special_use = \Archive
+ auto = subscribe
+ }
+ mailbox Spam {
+ special_use = \Junk
+ auto = subscribe
+ autoexpunge = 30d
+ }
+ mailbox Trash {
+ special_use = \Trash
+ auto = subscribe
+ }
+ }
+ ~a
+ "#
+ user
+ group
+ untrusted-user
+ auth-worker-group
+ hostname
+ hostname
+ state-dir
+ base-dir
+ state-dir
+ extra-content)))
+
+(define (dovecot2-etc-files config)
+ (match-record config <dovecot2-configuration>
+ (raw-file config-name)
+ `((,config-name ,(plain-file config-name
+ (or raw-file
+ (generate-dovecot-config config)))))))
+
+(define (dovecot2-accounts config)
+ (match-record config <dovecot2-configuration>
+ (user group untrusted-user untrusted-group)
+ (list
+ (user-account
+ (name user)
+ (group group)
+ (comment "Dovecot system user")
+ (home-directory "/var/empty")
+ (create-home-directory? #f)
+ (shell
+ (file-append shadow "/sbin/nologin"))
+ (system? #t))
+ (user-account
+ (name untrusted-user)
+ (group untrusted-group)
+ (comment "Dovecot user for untrusted logins")
+ (home-directory "/var/empty")
+ (create-home-directory? #f)
+ (shell
+ (file-append shadow "/sbin/nologin"))
+ (system? #t))
+ (user-group
+ (name group)
+ (system? #t))
+ (user-group
+ (name untrusted-group)
+ (system? #t)))))
+
+(define (dovecot2-activation config)
+ (match-record config <dovecot2-configuration>
+ (base-dir state-dir)
+ #~(begin
+ (use-modules (guix build utils))
+ (let ((user (getpwnam "root")))
+ (format (current-error-port)
+ "Creating Dovecot base_dir directory: \"~a\".~%" #$base-dir)
+ (mkdir-p #$base-dir)
+ (let ((dhparam.pem (string-append #$state-dir "/dhparam.pem")))
+ (unless (file-exists? dhparam.pem)
+ (format (current-error-port)
+ "dhparam.pem file doesn't exist yet. Generating one...~%")
+ (cond
+ ((zero? (system* (string-append #$openssl "/bin/openssl")
+ "dhparam" "-out" dhparam.pem "2048"))
+ (format (current-error-port)
+ "Dovecot2 dhparam.pem file created: \"~a\".~%" dhparam.pem))
+ (else
+ (format (current-error-port)
+ "Failed to create dhparam.pem file: \"~a\".~%" dhparam.pem)))))))))
+
+(define (dovecot2-shepherd-service config)
+ (match-record config <dovecot2-configuration>
+ (dovecot2 config-name)
+ (let ((config-file (string-append "/etc/" config-name)))
+ (list
+ (shepherd-service
+ (provision '(dovecot2))
+ (documentation "FIXME:DOCUMENTATION: heredoc syntax")
+ (start #~(make-forkexec-constructor
+ (list
+ #$(file-append dovecot2 "/sbin/dovecot")
+ "-F"
+ "-c"
+ #$config-file)))
+ (stop #~(make-kill-destructor))
+ (actions
+ (list
+ (shepherd-action
+ (name 'configuration)
+ (documentation "FIXME:DOCUMENTATION: heredoc syntax")
+ (procedure
+ #~(lambda _
+ (format #t "~a~%" #$config-file))))
+ (shepherd-action
+ (name 'reload)
+ (documentation "FIXME:DOCUMENTATION: heredoc syntax")
+ (procedure
+ #~(lambda _
+ (invoke #$(file-append dovecot "/bin/doveadm")
+ "-c"
+ #$config-file
+ "reload")))))))))))
+
+(define dovecot2-service-type
+ (service-type
+ (name 'dovecot2)
+ (extensions
+ (list
+ (service-extension etc-service-type
+ dovecot2-etc-files)
+ (service-extension account-service-type
+ dovecot2-accounts)
+ (service-extension activation-service-type
+ dovecot2-activation)
+ (service-extension profile-service-type
+ (compose list dovecot2-configuration-dovecot2))
+ (service-extension shepherd-root-service-type
+ dovecot2-shepherd-service)))
+ (default-value (dovecot2-configuration))
+ (description "FIXME:DOCUMENTATION: heredoc syntax")))
+
+;; FIXME
+;; automate personal server with:
+;; - euandreh:git-service-type
+;; - euandreh:mail-service-type
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; OS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
(list
postfix
python-telegram-bot)