diff mbox

services: Add opensmtpd-service.

Message ID 20161119072920.17518-1-iyzsong@gmail.com
State New
Headers show

Commit Message

宋文武 Nov. 19, 2016, 7:29 a.m. UTC
* gnu/services/mail.scm (<opensmtpd-configuration>): New record type.
(%default-opensmtpd-config-file, %opensmtpd-accounts): New variables.
(opensmtpd-shepherd-service, opensmtpd-activation): New procedures.
(opensmtpd-service-type): New variable.
(opensmtpd-service): New procedure.
* doc/guix.texi (Mail Services): Document it.
---
 doc/guix.texi         | 37 +++++++++++++++-----
 gnu/services/mail.scm | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 120 insertions(+), 10 deletions(-)

Comments

Ludovic Courtès Nov. 23, 2016, 10:24 p.m. UTC | #1
宋文武 <iyzsong@gmail.com> skribis:

> * gnu/services/mail.scm (<opensmtpd-configuration>): New record type.
> (%default-opensmtpd-config-file, %opensmtpd-accounts): New variables.
> (opensmtpd-shepherd-service, opensmtpd-activation): New procedures.
> (opensmtpd-service-type): New variable.
> (opensmtpd-service): New procedure.
> * doc/guix.texi (Mail Services): Document it.

Nice!

> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -9996,16 +9996,9 @@ For MariaDB, the root password is empty.
>  @cindex mail
>  @cindex email
>  The @code{(gnu services mail)} module provides Guix service definitions
> -for mail services.  Currently the only implemented service is Dovecot,
> -an IMAP, POP3, and LMTP server.
> +for following mail services:

I think we shouldn’t put a colon just before an @subsubheading.  How
about something like this instead:

  The @code{(gnu services mail)} module provides Guix service
  definitions for email services: IMAP, POP3, and LMTP servers, as well
  as mail transport agents (MTAs).  Lots of acronyms!  These services
  are detailed in the subsections below.

> +@subsubheading OpenSMTPD Service
> +
> +@deffn {Scheme Procedure} opensmtpd-service [#:config (opensmtpd-configuration)]
> +Return a service that runs the @command{smtpd} daemon of OpenSMTPD
> +package, an implementation of SMTP server as defined by RFC 5321.

s/OpenSMTP package/@uref{https://www.opensmtpd.org, OpenSMTPD}/

However, as discussed elsewhere, I prefer that we document
‘opensmtpd-service-type’ and not provide an ‘opensmtpd-service’
procedure at all.

> +(define opensmtpd-activation
> +  (match-lambda
> +    (($ <opensmtpd-configuration> package config-file)
> +     (let ((smtpd (file-append package "/sbin/smtpd")))
> +       #~(begin
> +           ;; Create the mbox directory.
> +           (mkdir-p "/var/mail")
> +           ;; Check the configuration file for validity.
> +           (system* #$smtpd "-n" "-f" #$config-file))))))

I think the configuration check belongs in the ‘start’ function of the
service rather than here.

Otherwise looks fine.

Could you send an updated patch?

Of course, bonus point if you can get a system test.  :-)

Thank you!

Ludo’.
=?utf-8?B?5a6L5paH5q2m?= Nov. 24, 2016, 2:10 p.m. UTC | #2
ludo@gnu.org (Ludovic Courtès) writes:

> 宋文武 <iyzsong@gmail.com> skribis:
>
>> * gnu/services/mail.scm (<opensmtpd-configuration>): New record type.
>> (%default-opensmtpd-config-file, %opensmtpd-accounts): New variables.
>> (opensmtpd-shepherd-service, opensmtpd-activation): New procedures.
>> (opensmtpd-service-type): New variable.
>> (opensmtpd-service): New procedure.
>> * doc/guix.texi (Mail Services): Document it.
>
> Nice!
>
>> --- a/doc/guix.texi
>> +++ b/doc/guix.texi
>> @@ -9996,16 +9996,9 @@ For MariaDB, the root password is empty.
>>  @cindex mail
>>  @cindex email
>>  The @code{(gnu services mail)} module provides Guix service definitions
>> -for mail services.  Currently the only implemented service is Dovecot,
>> -an IMAP, POP3, and LMTP server.
>> +for following mail services:
>
> I think we shouldn’t put a colon just before an @subsubheading.  How
> about something like this instead:
>
>   The @code{(gnu services mail)} module provides Guix service
>   definitions for email services: IMAP, POP3, and LMTP servers, as well
>   as mail transport agents (MTAs).  Lots of acronyms!  These services
>   are detailed in the subsections below.
>

Sure!

>> +@subsubheading OpenSMTPD Service
>> +
>> +@deffn {Scheme Procedure} opensmtpd-service [#:config (opensmtpd-configuration)]
>> +Return a service that runs the @command{smtpd} daemon of OpenSMTPD
>> +package, an implementation of SMTP server as defined by RFC 5321.
>
> s/OpenSMTP package/@uref{https://www.opensmtpd.org, OpenSMTPD}/
>
> However, as discussed elsewhere, I prefer that we document
> ‘opensmtpd-service-type’ and not provide an ‘opensmtpd-service’
> procedure at all.

Ah, OK, I was unaware of this.

>> +(define opensmtpd-activation
>> +  (match-lambda
>> +    (($ <opensmtpd-configuration> package config-file)
>> +     (let ((smtpd (file-append package "/sbin/smtpd")))
>> +       #~(begin
>> +           ;; Create the mbox directory.
>> +           (mkdir-p "/var/mail")
>> +           ;; Check the configuration file for validity.
>> +           (system* #$smtpd "-n" "-f" #$config-file))))))
>
> I think the configuration check belongs in the ‘start’ function of the
> service rather than here.

Right…  I find it always reports ‘lo’ is not a valid interface here.

(Now I think it’s not necessary to do an addition check, since it will
fail to start anyway.)

> Otherwise looks fine.
>
> Could you send an updated patch?

Sure.


> Of course, bonus point if you can get a system test.  :-)

Will look into it later :-)

Also, I find that my slow box is unable start this opensmtpd service
during a fresh boot.  ‘smtpd’ has a timeout of 10s hardcoded, I patched
that to 60s to make it fully start.  But it turns out that
‘read-pid-file’ of shepherd has a timeout of 5s, so I guess that’s why
the service is marked as stop when it actually running…



Thanks for the review!
Ludovic Courtès Nov. 26, 2016, 6:33 p.m. UTC | #3
iyzsong@member.fsf.org (宋文武) skribis:

> Also, I find that my slow box is unable start this opensmtpd service
> during a fresh boot.  ‘smtpd’ has a timeout of 10s hardcoded, I patched
> that to 60s to make it fully start.  But it turns out that
> ‘read-pid-file’ of shepherd has a timeout of 5s, so I guess that’s why
> the service is marked as stop when it actually running…

Oh that sounds like a bug: shepherd should kill(2) the process when the
PID file doesn’t show up on time.

Fixed in commit a8fa86bb23cc457e2cd603ad505c964bc8dc889e of the
Shepherd.

The previous commit allows you to select a timeout other than 5 seconds
too—wonderful.  ;-)

Thanks!

Ludo’.
=?utf-8?B?5a6L5paH5q2m?= Nov. 27, 2016, 2:22 a.m. UTC | #4
ludo@gnu.org (Ludovic Courtès) writes:

> iyzsong@member.fsf.org (宋文武) skribis:
>
>> Also, I find that my slow box is unable start this opensmtpd service
>> during a fresh boot.  ‘smtpd’ has a timeout of 10s hardcoded, I patched
>> that to 60s to make it fully start.  But it turns out that
>> ‘read-pid-file’ of shepherd has a timeout of 5s, so I guess that’s why
>> the service is marked as stop when it actually running…
>
> Oh that sounds like a bug: shepherd should kill(2) the process when the
> PID file doesn’t show up on time.
>
> Fixed in commit a8fa86bb23cc457e2cd603ad505c964bc8dc889e of the
> Shepherd.
>
> The previous commit allows you to select a timeout other than 5 seconds
> too—wonderful.  ;-)
>

Cool, thanks!
diff mbox

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 0e70830..34ac0b9 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -9996,16 +9996,9 @@  For MariaDB, the root password is empty.
 @cindex mail
 @cindex email
 The @code{(gnu services mail)} module provides Guix service definitions
-for mail services.  Currently the only implemented service is Dovecot,
-an IMAP, POP3, and LMTP server.
+for following mail services:
 
-Guix does not yet have a mail transfer agent (MTA), although for some
-lightweight purposes the @code{esmtp} relay-only MTA may suffice.  Help
-is needed to properly integrate a full MTA, such as Postfix.  Patches
-welcome!
-
-To add an IMAP/POP3 server to a GuixSD system, add a
-@code{dovecot-service} to the operating system definition:
+@subsubheading Dovecot Service
 
 @deffn {Scheme Procedure} dovecot-service [#:config (dovecot-configuration)]
 Return a service that runs the Dovecot IMAP/POP3/LMTP mail server.
@@ -11361,6 +11354,32 @@  could instantiate a dovecot service like this:
                   (string "")))
 @end example
 
+@subsubheading OpenSMTPD Service
+
+@deffn {Scheme Procedure} opensmtpd-service [#:config (opensmtpd-configuration)]
+Return a service that runs the @command{smtpd} daemon of OpenSMTPD
+package, an implementation of SMTP server as defined by RFC 5321.
+
+The optional @var{config} argument specifies the configuration for
+@command{smtpd}, which should be a @code{<opensmtpd-configuration>}
+object, by default it listens on the loopback network interface, and
+allows for mail from users and daemons on the local machine, as well as
+permitting email to remote servers.
+@end deffn
+
+@deftp {Data Type} opensmtpd-configuraiton
+Data type regresenting the configuraiton of opensmtpd.
+
+@table @asis
+@item @code{package} (default: @var{opensmtpd})
+Package object of the OpenSMTPD SMTP server.
+
+@item @code{config-file} (default: @var{%default-opensmtpd-file})
+File-like object of the OpenSMTPD configuration file to use.  Run
+@command{man smtpd.conf} for more information.
+
+@end table
+@end deftp
 
 @node Kerberos Services
 @subsubsection Kerberos Services
diff --git a/gnu/services/mail.scm b/gnu/services/mail.scm
index cb0f119..94b4c62 100644
--- a/gnu/services/mail.scm
+++ b/gnu/services/mail.scm
@@ -51,7 +51,12 @@ 
             protocol-configuration
             plugin-configuration
             mailbox-configuration
-            namespace-configuration))
+            namespace-configuration
+
+            opensmtpd-configuration
+            opensmtpd-service
+            opensmtpd-service-type
+            %default-opensmtpd-config-file))
 
 ;;; Commentary:
 ;;;
@@ -1691,3 +1696,89 @@  by @code{dovecot-configuration}.  @var{config} may also be created by
             (format #t "@end deftypevr\n\n")))
         fields))))
   (generate 'dovecot-configuration))
+
+
+;;;
+;;; OpenSMTPD.
+;;;
+
+(define-record-type* <opensmtpd-configuration>
+  opensmtpd-configuration make-opensmtpd-configuration
+  opensmtpd-configuration?
+  (package     opensmtpd-configuration-package
+               (default opensmtpd))
+  (config-file opensmtpd-configuration-config-file
+               (default %default-opensmtpd-config-file)))
+
+(define %default-opensmtpd-config-file
+  (plain-file "smtpd.conf" "
+listen on lo
+accept from any for local deliver to mbox
+accept from local for any relay
+"))
+
+(define opensmtpd-shepherd-service
+  (match-lambda
+    (($ <opensmtpd-configuration> package config-file)
+     (list (shepherd-service
+            (provision '(smtpd))
+            (requirement '(networking))
+            (documentation "Run the OpenSMTPD daemon.")
+            (start (let ((smtpd (file-append package "/sbin/smtpd")))
+                     #~(make-forkexec-constructor
+                        (list #$smtpd "-f" #$config-file)
+                        #:pid-file "/var/run/smtpd.pid")))
+            (stop #~(make-kill-destructor)))))))
+
+(define %opensmtpd-accounts
+  (list (user-group
+         (name "smtpq")
+         (system? #t))
+        (user-account
+         (name "smtpd")
+         (group "nogroup")
+         (system? #t)
+         (comment "SMTP Daemon")
+         (home-directory "/var/empty")
+         (shell (file-append shadow "/sbin/nologin")))
+        (user-account
+         (name "smtpq")
+         (group "smtpq")
+         (system? #t)
+         (comment "SMTPD Queue")
+         (home-directory "/var/empty")
+         (shell (file-append shadow "/sbin/nologin")))))
+
+(define opensmtpd-activation
+  (match-lambda
+    (($ <opensmtpd-configuration> package config-file)
+     (let ((smtpd (file-append package "/sbin/smtpd")))
+       #~(begin
+           ;; Create the mbox directory.
+           (mkdir-p "/var/mail")
+           ;; Check the configuration file for validity.
+           (system* #$smtpd "-n" "-f" #$config-file))))))
+
+(define opensmtpd-service-type
+  (service-type
+   (name 'opensmtpd)
+   (extensions
+    (list (service-extension account-service-type
+                             (const %opensmtpd-accounts))
+          (service-extension activation-service-type
+                             opensmtpd-activation)
+          (service-extension profile-service-type
+                             (compose list opensmtpd-configuration-package))
+          (service-extension shepherd-root-service-type
+                             opensmtpd-shepherd-service)))))
+
+(define* (opensmtpd-service #:key (config (opensmtpd-configuration)))
+  "Return a service that runs the @command{smtpd} daemon of OpenSMTPD package,
+an implementation of SMTP server as defined by RFC 5321.
+
+The optional @var{config} argument specifies the configuration for
+@command{smtpd}, which should be a @code{<opensmtpd-configuration>} object, by
+default it listens on the loopback network interface, and allows for mail from
+users and daemons on the local machine, as well as permitting email to remote
+servers."
+  (service opensmtpd-service-type config))