(service (@ (gnu services mail) opensmtpd-service-type) ((@ (gnu services mail) opensmtpd-configuration) (config-file …)))
"...as I think Guix services ought to faithfully wrap the native syntax whenever possible (implement alternative simple APIs on top of that — fine)."
-nckx from irc on #guix
Before I was following nckx's advice on the opensmtpd-service-type, a 1-1 mapping of the smtpd.conf syntax. I was avoiding doing something like this.
(service email-service-type
(email-configuration
(domains (list "gnucode.me" "gnu-hurd.com"))
(use-letsencrypt #t)))
(service opensmtpd-service
(opensmtpd-configuration
(includes ...)
(tables ...)
(pkis ...)
(filters ...)
(listen-on ...)
(actions ...)
(matches ...)))
This would eliminate misspelling errors and ensure each has a corresponding and give appropriate error messages. The goal of a lot of this is to minimize the number of times a user has to grok the service's original non-guile syntax file.
Why don't I delete the opensmtpd-configuration's fieldnames 'filters', 'pkis', 'actions', 'mda-wrapper', 'cas'?
(service opensmtpd-service-type
(opensmtpd-configuration
(pkis (list
(opensmtpd-pki
...)))
(tables (list
(opensmtpd-table
...)
(opensmtpd-table
...)))
(listen-ons
(list
(opensmtpd-listen-on
...)
(opensmtpd-listen-on
...)))
(actions
(list
(opensmtpd-action
...)
(opensmtpd-action
...)))
(matches (list
(opensmtpd-match
...)
(opensmtpd-match
...)))
(filter-chains
(list
(opensmtpd-filter-chain
(name "dropDumbEmails")
(filter-names (list "nofcrdnsDisconnect"
"nordnsDisconnect")))))
(filter-phases
(list (opensmtpd-filter-phase
...)
(opensmtpd-filter-phase
...)))))
(service opensmtpd-service-type
(opensmtpd-configuration
(listen-ons
(list (opensmtpd-listen-on
(interface "eth0")
(filter
(opensmtpd-filter-chain-configuration
(list
(opensmtpd-filter-phase
...)
(opensmtpd-filter-phase
...))))
(hostnames (opensmtpd-table-configuration
(values "gnucode.me" "gnu-hurd.com")))
(ca
(opensmtpd-ca-configuration ...))
(pkis
(list
(opensmtpd-pki-configuration
...)
(opensmtpd-pki-configuration
...))))))
(matches
(list
(opensmtpd-match
(for (opensmtpd-match-option-configuration ...)
(action
(opensmtpd-action
(opensmtpd-local-delivery-configuration
(method
(opensmtpd-maildir-configuration
...))
(alias (opensmtpd-table
...))))))
This is done, I just need to test it.
(service opensmtpd-service-type
(opensmtpd-configuration
(pkis (list
(opensmtpd-pki
(domain "smtp.gnucode.me")
(cert "/etc/letsencrypt/live/gnucode.me/fullchain.pem")
(key "/etc/letsencrypt/live/gnucode.me/privkey.pem"))))
(listen-ons
(list
(opensmtpd-listen-on
(interface "eth0")
(port 465)
(secure-connection "smtps")
(pki "smtp.gnucode.me")
(auth "creds"))
(opensmtpd-listen-on
(interface "eth0")
(port 587)
(secure-connection "tls-require")
(pki "smtp.gnucode.me")
(auth "creds"))))))
(let ([gnucode.me (opensmtpd-pki
(domain "smtp.gnucode.me") ;; could potentially remove 'domain' fieldname.
(cert "/etc/letsencrypt/live/gnucode.me/fullchain.pem")
(key "/etc/letsencrypt/live/gnucode.me/privkey.pem"))])
(service opensmtpd-service-type
(opensmtpd-configuration
(listen-ons
(list
(opensmtpd-listen-on
(interface "eth0")
(port 465)
(secure-connection "smtps")
(pki gnucode.me)
(auth "creds"))
(opensmtpd-listen-on
(interface "eth0")
(port 587)
(secure-connection "tls-require")
(pki gnucode.me)
(auth "creds")))))))
write the same pki more verbosely.
(service opensmtpd-service-type
(opensmtpd-configuration
(listen-ons
(list
(opensmtpd-listen-on
(interface "eth0")
(port 465)
(secure-connection "smtps")
(pki (opensmtpd-pki ;; this pki is written twice
(domain "smtp.gnucode.me")
(cert "/etc/letsencrypt/live/gnucode.me/fullchain.pem")
(key "/etc/letsencrypt/live/gnucode.me/privkey.pem")))
(auth "creds"))
(opensmtpd-listen-on
(interface "eth0")
(port 587)
(secure-connection "tls-require")
(pki (opensmtpd-pki ;; this pki is written twice
(domain "smtp.gnucode.me")
(cert "/etc/letsencrypt/live/gnucode.me/fullchain.pem")
(key "/etc/letsencrypt/live/gnucode.me/privkey.pem")))
(auth "creds"))))))
Basically, there is an opensmtpd-match that calls an opensmtpd-action "send". BUT there is no such action defined. This error will not be possible when, task: remove opensmtpd-configuration-actions. Instead add a "action" fieldname to opensmtpd-match. is done.
(service opensmtpd-service-type
(opensmtpd-configuration
(tables (list
(opensmtpd-table
(name "aliases")
(values
(list
(cons "webmaster" "root")
(cons "postmaster" "root")
(cons "abuse" "root"))))
(opensmtpd-table
(name "creds")
(values
(list
(cons "joshua"
"$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86."))))
(opensmtpd-table
(name "vdoms")
(values (list "gnucode.me"
"gnu-hurd.com")))
(opensmtpd-table
(name "vusers")
(values (list (cons "joshua@gnucode.me" "joshua")
(cons "jbranso@gnucode.me" "joshua")
(cons "postmaster@gnucode.me" "joshua"))))))
(listen-ons
(list
;; this forum help suggests that I listen on 0.0.0.0 and NOT eth0
;; https://serverfault.com/questions/726795/opensmtpd-wont-work-at-reboot
;; this listens for email from the outside world
(opensmtpd-listen-on
(interface interface)
(port 25)
(secure-connection "tls")
(pki smtp.gnucode.me)
)
;; this lets local users logged into the system via ssh send email
(opensmtpd-listen-on
(interface "lo")
(port 25)
(secure-connection "tls")
(pki smtp.gnucode.me))
(opensmtpd-listen-on
(interface interface)
(port 465)
(secure-connection "smtps")
(pki smtp.gnucode.me)
(auth "creds"))
(opensmtpd-listen-on
(interface interface)
(port 587)
(secure-connection "tls-require")
(pki smtp.gnucode.me)
(auth "creds"))))
(actions
(list
(opensmtpd-action
(name "receive")
(method
(opensmtpd-local-delivery-configuration
(method (opensmtpd-maildir-configuration
(pathname "/home/%{rcpt.user}/Maildir")
(junk #t)))
(virtual "vusers"))))
))
(matches (list
(opensmtpd-match
(name "send")
(for "for any")
(from "from any")
(auth #t))
(opensmtpd-match
(name "receive")
(from "from any")
(for "for domain <vdoms>"))
(opensmtpd-match
(name "receive")
(for "for local"))))
(filter-chains
(list
(opensmtpd-filter-chain
(name "dropDumbEmails")
(filter-names (list "nofcrdnsDisconnect"
"nordnsDisconnect")))))
(filter-phases
(list (opensmtpd-filter-phase
(name "nofcrdnsDisconnect")
(phase-name "connect")
(conditions (list "!fcrdns"))
(decision "disconnect")
(message "You have not set up forward confirmed DNS."))
(opensmtpd-filter-phase
(name "nordnsDisconnect")
(phase-name "connect")
(conditions (list "!rdns"))
(decision "reject")
(message "You have not set up reverse DNS."))))))
For example, this is incorrect.
(service opensmtpd-service-type
(listen-on (pki "smtpd.gnucode.me")))
But this is correct
(service opensmtpd-service-type
(pkis
(list (opensmtpd-pki
(cert "/path/to/cert")
(key "/path/to/key"))))
(listen-on (pki "smtpd.gnucode.me")))
Perhaps I should sanitize the opensmtpd-listen-on pki fieldname. I should check to see if that pki name is in the opensmtpd-configuration-pkis list.
Here is a big example that makes this mistake.
(opensmtpd-configuration
(mta-max-deferred 50)
(queue
(opensmtpd-queue-configuration
(compression #t)))
(smtp
(opensmtpd-smtp-configuration
(max-message-size "10M")))
(srs
(opensmtpd-srs-configuration
(ttl-delay "5d")))
;; (pkis (list
;; (opensmtpd-pki
;; (domain "smtpd.gnucode.me")
;; (cert "/etc/letsencrypt/live/gnucode.me/fullchain.pem")
;; (key "/etc/letsencrypt/live/gnucode.me/privkey.pem"))))
(tables (list
(opensmtpd-table
(name "aliases")
(values
(list
(cons "webmaster" "root")
(cons "postmaster" "root")
(cons "abuse" "root"))))
(opensmtpd-table
(name "creds")
(values
(list
(cons "joshua"
"$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86."))))
(opensmtpd-table
(name "vdoms")
(values (list "gnucode.me"
"gnu-hurd.com")))
(opensmtpd-table
(name "vusers")
(values (list (cons "joshua@gnucode.me" "joshua")
(cons "jbranso@gnucode.me" "joshua")
(cons "postmaster@gnucode.me" "joshua"))))))
(listen-ons
(list
;; this forum help suggests that I listen on 0.0.0.0 and NOT eth0
;; https://serverfault.com/questions/726795/opensmtpd-wont-work-at-reboot
;; this listens for email from the outside world
(opensmtpd-listen-on
(interface interface)
(port 25)
(secure-connection "tls")
(pki "smtp.gnucode.me"))
;; this lets local users logged into the system via ssh send email
(opensmtpd-listen-on
(interface "lo")
(port 25)
(secure-connection "tls")
(pki "smtp.gnucode.me"))
(opensmtpd-listen-on
(interface interface)
(port 465)
(secure-connection "smtps")
(pki "smtp.gnucode.me")
(auth "<creds>"))
(opensmtpd-listen-on
(interface interface)
(port 587)
(secure-connection "tls-require")
(pki "smtp.gnucode.me")
(auth "<creds>"))))
(actions
(list
(opensmtpd-action
(name "receive")
(method
(opensmtpd-local-delivery-configuration
(method (opensmtpd-maildir-configuration
(pathname "/home/%{rcpt.user}/Maildir")
(junk #t)))
(virtual "vusers"))))
(opensmtpd-action
(name "send")
(method (opensmtpd-relay-configuration)))))
(matches (list
(opensmtpd-match
(name "send")
(for "for any")
(from "from any")
(auth "auth"))
(opensmtpd-match
(name "receive")
(from "from any")
(for "for domain <vdoms>"))
(opensmtpd-match
(name "receive")
(for "for local"))))
(filter-chains
(list
(opensmtpd-filter-chain
(name "dropDumbEmails")
(filter-names (list "nofcrdnsDisconnect"
"nordnsDisconnect")))))
(filter-phases
(list (opensmtpd-filter-phase
(name "nofcrdnsDisconnect")
(phase-name "connect")
(conditions (list "!fcrdns"))
(decision "disconnect")
(message "You have not set up forward confirmed DNS."))
(opensmtpd-filter-phase
(name "nordnsDisconnect")
(phase-name "connect")
(conditions (list "!rdns"))
(decision "reject")
(message "You have not set up reverse DNS.")))))
But string? lets me test the config locally.
For example, opensmtpd-configuration-pkis returns a list of opensmtpd-configuration-pkis...What if this particular configuration does NOT have any defined pkis? What if it is only for serving local mail?
What about opensmtpd-configuration-filters->string is this assuming that there are filters?
What about opensmtpd-configuration-listen-ons? It's possible that the user uses the default listen-on-socket.
Instead add a fieldname 'filters' to .
This
(opensmtpd-configuration
(opensmtpd-listen-ons
(list (opensmtpd-listen-on
(interface "eth0")
(filter (filter-proc
(name "name")
(command "command")))))))
instead of
(opensmtpd-configuration
(procs (list
(filter-proc (name "name")
(command "command"))))
(opensmtpd-listen-ons
(list (opensmtpd-listen-on
(filter "name")))))
filter-proc is not like the other filters...
A filter proc refers to a line like:
proc "proc-name" command
which allows different filters to use the same process.
This would eleminate the possibility of errors such as creating a table name and then misspelling the table name later on in the configuration. Or defining a table but never using it.
For example, this is probably easier
(opensmtpd-configuration
(actions (list
(opensmtpd-action
(name "relay")
(method (opensmtpd-relay-configuration
(domain (opensmtpd-table
;;(name "domains") ;; with some smart coding, the name would NOT be needed.
(values (list
"gnucode.me"
"gnu-hurd.com"))))))))))
than the alternative:
(opensmtpd-configuration
(tables (list
(opensmtpd-table
(name "domains")
(values (list
"gnucode.me"
"gnu-hurd.com")))))
(actions (list
(opensmtpd-action
(name "relay")
(method (opensmtpd-relay-configuration
(domain "domains")))))))
(openmstpd-match (for (list 'not "for domain regex" (opensmtpd-table (values (list "gnucode.me" "gnu-hurd.com")))))
(openmstpd-match
(for
(list "! for domain"
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
* opensmtpd-match-options-configuration approach I like this one quite a bit.
This method is a little bit more verbose. Well I guess it's a lot more verbose. But it's easier for me to properly parse what the user wants.
I would sanitize the the match-options in the opensmtpd-match-for, openmsmtpd-match-from, opensmtpd-match-auth, opensmtpd-match-helo, opensmtpd-match-mail-from, opensmtpd-match-rcpt-to fieldnames. ********** for
(openmstpd-match
(for
(opensmtpd-match-options-configuration
(not #t)
(method "domain regex") ;; valid options for "for" are "domain" or "domain regex"
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
Do I want a regex fieldname? Probably not. It makes it more verbose...
(openmstpd-match
(for
(opensmtpd-match-options-configuration
(not #t)
(regex #t)
(method "domain") ;; valid options for "for" are "domain"
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
** from
(openmstpd-match
(from
(opensmtpd-match-options-configuration
(not #t)
(method "rdns regex") ;;valid options for from are "auth" "auth regex", "mail-from" "mail-from regex",
;; "rdns", "rdns regex", "src", "src regex"
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
Do I want a regex fieldname?
(openmstpd-match
(from
(opensmtpd-match-options-configuration
(not #t)
(regex #t)
(method "rdns") ;;valid options for from are "auth", "mail-from", "rdns", "src"
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
** auth
(openmstpd-match
(auth
(opensmtpd-match-options-configuration
(not #t)
(method "auth regex")
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
Do I want a regex fieldname?
(openmstpd-match
(auth
(opensmtpd-match-options-configuration
(not #t)
(regex #t)
(method "auth") ;; valid options for auth are "auth" or this method can be left blank.
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
** mail-from
(openmstpd-match
(mail-from
(opensmtpd-match-options-configuration
(not #t)
(method "mail from")
(opensmtpd-table
(values (list "gnucode.me" "gnu-hurd.com"))))))
** I tweak opensmtpd-match record and add a opensmtpd-match-options
(opensmtpd-match
(name "action-name")
(options
(list
(opensmtpd-match-options-configuration
(method "for domain regex")))
))
given an , I would need to find all of the tables, and print out the tables.
This is quite a LOT of changes.
I would also have to find a way to make sure that even though some directives share the same table, that only one table is exported in the file. OR they are both exported, but are exported under different names.
I would also have to change the way I do matches. I currently have fieldname 'for', which is just a string. I would have to change that to something that optionally accepts a table
Instead when something wants to use a table, let the object use the record directly.
For example instead of
a directive refers to an opensmtpd-table-name, that we check to make sure that a table with that name exists.
This would approach the same benefit that we would get with allowing directives to have a value of , which is essentially ensuring that no would even contain data that would translate into a broken smtpd.conf file.
The downside is that I would not be able to sanitize match records very well.
I AM NOT DOING THIS. I am just going to let fieldnames have a value of .
is there a way to loop through each fieldname of a record? Suppose you don't want to hard-code each record name by hand, but instead wanted to loop through each fieldname of a record that anyone wrote. [15:02] any particular sort of record? [15:03] RhodiumToad: yes. [15:05] I'm thinking in the context of (guix records). specifically for my opensmtpd service https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org#todo-it-might-be-a-good-idea-to-completely-rethink-how-i-am-making-this-service various fieldnames need a . It would be nice to take a look at the and get a list of all of the records. [15:06] I can create a function that hardcodes and checks various places for tables, but it would be nice to programmatically do that instead. [15:07] I don't do guix myself, so I don't know what its records are; but what you wanted is doable in, I believe, all the record implementations in the guile distribution [15:19] RhodiumToad: can you send me a pastebin, or point in the direction of the procedure that I may want to use? [15:21] jab: do you mean something like enum.values() in Java? [15:25] jab: for native records and srfi-9 records, something like (map (lambda (f) ((record-accessor (record-type-descriptor fred) f) fred)) (record-type-fields (record-type-descriptor fred))) will give the values of a record [15:26] ArneBab: that should work. RhodiumToad: thanks! for rnrs records, there are similar functions might even be the same functions, I didn't check the definitions [15:27] Would be nice to have a function that works for them all … of course if you have structs or goops classes then you have a different problem or smobs [15:28] it looks like the equivalent functions for rnrs records require you to check the parent record type yourself, i.e. you get only the fields of the most-derived type, and then have to recurse to the parent [15:33] RhodiumToad: thanks [15:42] ERC>
(opensmtpd-configuration
(matches
(list
(opensmtpd-match
(options (list
(opensmtpd-option ...)
(opensmtpd-option ...)))
(action
(opensmtpd-action
(name "some action")
(method (opensmtpd-relay-configuration
...)))))
(opensmtpd-match
(options (list
(opensmtpd-option ...)
(opensmtpd-option ...)))
(opensmtpd-action
(name "some action")
(method (opensmtpd-local-delivery-configuration
...)))))))
once remove opensmtpd-action and replace it with is done, the above could become:
(opensmtpd-configuration
(matches
(list
(opensmtpd-match
(options (list
(opensmtpd-option ...)
(opensmtpd-option ...)))
(action
(opensmtpd-action-relay-configuration
...)))
(opensmtpd-match
(options (list
(opensmtpd-option ...)
(opensmtpd-option ...)))
(action
(opensmtpd-action-local-delivery-configuration
...))))))
return all of the unique s.
eg:
(service opensmtpd-service-type)
turns into an opensmtpd config file of:
listen on lo
action inbound mbox
match for local action inbound
action outbound relay
match from local for any action outbound
(actions opensmtpd-configuration-actions
(default (list (opensmtpd-action
(name "local")
(method (opensmtpd-local-delivery-configuration
(method "mbox"))))
(opensmtpd-action
(name "outbound")
(method (opensmtpd-relay-configuration))))))
(opensmtpd-match
(action (opensmtpd-action
...))
(options
(list
(opensmtpd-match-option)
(opensmtpd-match-option)
(opensmtpd-match-option))))
This one is perhaps more verbose but it makes it easier to sanitize and it makes it harder for people to put in the wrong values or bad data.
(opensmtpd-match
(action (opensmtpd-action-configuration))
(for
(opensmtpd-match-option))
(from
(opensmtpd-match-option))
(auth
(opensmtpd-match-option))
(helo
(opensmtpd-match-option))
(mail-from
(opensmtpd-match-option))
(rcpt-to
(opensmtpd-match-option))
(tag
(opensmtpd-match-option))
(tls
(opensmtpd-match-option)))
Here is a more flushed out example:
(opensmtpd-match
(action (opensmtpd-action-configuration))
(for
(opensmtpd-match-option-configuration
(option "domain")
(not #t)
(regex #t)
(value (opensmtpd-table
(name "creds")
(values (list "somerexg" "another regex"))))))
(from
(opensmtpd-match-option-configuration
(option "auth")
(not #t)
(regex #t)
(value (opensmtpd-table
(name "users")
(values (list "somerexg" "another regex"))))))
(auth
(opensmtpd-match-option
(option "auth")))
(helo
(opensmtpd-match-option))
(mail-from
(opensmtpd-match-option))
(rcpt-to
(opensmtpd-match-option))
(tag
(opensmtpd-match-option))
(tls
(opensmtpd-match-option)))
(opensmtpd-match
(for
(opensmtpd-match-option))
(from
(opensmtpd-match-option))
(options (list
(opensmtpd-match-option)
(opensmtpd-match-option)
(opensmtpd-match-option))))
CLOSED: [2021-11-10 Wed 17:57]
opensmtpd-action-local-delivery and opensmtpd-action-relay-configuration
Anything that accepts an will now have to support taking an , or .
Or I can derive create a parent record that has only one fieldname: 'name'...and both opensmtpd-action-local-delivery and opensmtpd-action-relay-configuration can inherit from that common record. BUT (guix records) might not support this...
It made sense to have opensmtpd-action
opensmtpd-action-name
opensmtpd-action-method
|
/ \
/ \
/ \
<local-delivery-configuration> <relay-configuration>
same thing as same thing as
<opensmtpd-local-delivery-action> <opensmtpd-relay-configuration-action>
It made sense because, local-delivery-configuration has options that apply only it. And relay-configuration has options that apply only to it. But why have 3 records when you could have have two?
To make this change, I'll need to add the 'name' fieldname to and .
(display
(opensmtpd-smtp-configuration->string
(opensmtpd-smtp-configuration
(limit-max-mails 10)
(limit-max-rcpt 10)
(max-message-size 10))))
(opensmtpd-configuration->mixed-text-file example-opensmtpd-config) ice-9/boot-9.scm:1685:16: In procedure raise-exception: In procedure opensmtpd-configuration-smtp: Wrong type argument: #< type: # value: #< package: # config-file: #f bounce: #f cas: #f filter-procs: #f listen-ons: (#< interface: "wlp2s0" family: #f auth: #f auth-optional: #f filter: #f hostname: #f hostnames: #f mask-src: #f no-dsn: #f pki: #< domain: "smtp.gnucode.me" cert: "opensmtpd.scm" key: "opensmtpd.scm" dhe: #f> port: 25 proxy-v2: #f received-auth: #f senders: #f secure-connection: "tls" tag: #f protocols: #f ciphers: #f> #< interface: "lo" family: #f auth: #f auth-optional: #f filter: #f hostname: #f hostnames: #f mask-src: #f no-dsn: #f pki: #< domain: "smtp.gnucode.me" cert: "opensmtpd.scm" key: "opensmtpd.scm" dhe: #f> port: 25 proxy-v2: #f received-auth: #f senders: #f secure-connection: "tls" tag: #f protocols: #f ciphers: #f> #< interface: "wlp2s0" family: #f auth: "creds" auth-optional: #f filter: #f hostname: #f hostnames: #f mask-src: #f no-dsn: #f pki: #< domain: "smtp.gnucode.me" cert: "opensmtpd.scm" key: "opensmtpd.scm" dhe: #f> port: 465 proxy-v2: #f received-auth: #f senders: #f secure-connection: "smtps" tag: #f protocols: #f ciphers: #f> #< interface: "wlp2s0" family: #f auth: "creds" auth-optional: #f filter: #f hostname: #f hostnames: #f mask-src: #f no-dsn: #f pki: #< domain: "smtp.gnucode.me" cert: "opensmtpd.scm" key: "opensmtpd.scm" dhe: #f> port: 587 proxy-v2: #f received-auth: #f senders: #f secure-connection: "tls-require" tag: #f protocols: #f ciphers: #f>) listen-on-socket: #< filter: #f mask-src: #f tag: #f> includes: #f matches: (#< action: #< name: "send" backup: #f backup-mx: #f helo: #f domain: #f host: #f pki: #f srs: #f tls: #f protocols: #f ciphers: #f auth: #f mail-from: #f src: #f> for: "'s fieldname \n'for' is of type . AND the \n's fieldname 'option' can be one of the \nfollowing strings: 'for any', 'for local', 'for domain', 'for rcpt-to'.\n" from: "'s fieldname \n'from' is of type . AND the \n's fieldname 'option' can be one of the \nfollowing strings: 'from any', 'from auth', 'from local', 'from mail-from', 'from rdns', 'from socket', or 'from src'.\n" auth: #< option: "auth" not: #f regex: #f value: #f> helo: #f mail-from: #f rcpt-to: #f tag: #f tls: #f> #< action: #< name: "receive" method: #< pathname: "/home/%{rcpt.user}/Maildir" junk: #t> alias: #f ttl: #f user: #f userbase: #f virtual: "vusers" wrapper: #f> for: "'s fieldname \n'for' is of type . AND the \n's fieldname 'option' can be one of the \nfollowing strings: 'for any', 'for local', 'for domain', 'for rcpt-to'.\n" from: "'s fieldname \n'from' is of type . AND the \n's fieldname 'option' can be one of the \nfollowing strings: 'from any', 'from auth', 'from local', 'from mail-from', 'from rdns', 'from socket', or 'from src'.\n" auth: #f helo: #f mail-from: #f rcpt-to: #f tag: #f tls: #f> #< action: #< name: "receive" method: #< pathname: "/home/%{rcpt.user}/Maildir" junk: #t> alias: #f ttl: #f user: #f userbase: #f virtual: "vusers" wrapper: #f> for: "'s fieldname \n'for' is of type . AND the \n's fieldname 'option' can be one of the \nfollowing strings: 'for any', 'for local', 'for domain', 'for rcpt-to'.\n" from: #f auth: #f helo: #f mail-from: #f rcpt-to: #f tag: #f tls: #f>) mda-wrappers: #f mta-max-deferred: 100 procs: #f queue: #f smtp: #f srs: #f tables: (#< name: "aliases" file: #f file-db: #f values: (("webmaster" . "root") ("postmaster" . "root") ("abuse" . "root")) type: #> #< name: "creds" file: #f file-db: #f values: (("joshua" . "$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86.")) type: #> #< name: "vdoms" file: #f file-db: #f values: ("gnucode.me" "gnu-hurd.com") type: #> #< name: "vusers" file: #f file-db: #f values: (("joshua@gnucode.me" . "joshua") ("jbranso@gnucode.me" . "joshua") ("postmaster@gnucode.me" . "joshua")) type: #>)>>
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
Provide appropriate error messages.
There is a trend of guix services that "work" but are not dummy proof. For example, the XMPP service wants a cert in the format of "
Shepherd will not tell you the configuration file. You have to manually go searching for the config file. Then you have to manually check the configuration syntax of the file, though the command to start the service may have a flag to check the syntax. Anyway it's annoying. Guix services should be able to get a record and just by looking at the record tell if you have done something silly that will make the service refuse to start or behave in a weird way and provide you appropriate error messages so you don't have to go syntax hunting.
Examples:
Opensmtpd service users, may want to consider defining the service
in a (let )
statement, like the following example:
(services
(list
(service earlyoom-service-type
(earlyoom-configuration
(prefer-regexp "icecat|chromium|firefox")))
(let ([interface "wlp2s0"]
[smtp.gnucode.me (opensmtpd-pki
(domain "smtp.gnucode.me")
(cert "sway.scm")
(key "sway-service.scm"))])
(service opensmtpd-service-type
(opensmtpd-configuration
(tables (list
(opensmtpd-table
(name "aliases")
(values
(list
(cons "webmaster" "root")
(cons "postmaster" "root")
(cons "abuse" "root"))))
(opensmtpd-table
(name "creds")
(values
(list
(cons "joshua"
"$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86."))))
(opensmtpd-table
(name "vdoms")
(values (list "gnucode.me"
"gnu-hurd.com")))
(opensmtpd-table
(name "vusers")
(values (list (cons "joshua@gnucode.me" "joshua")
(cons "jbranso@gnucode.me" "joshua")
(cons "postmaster@gnucode.me" "joshua"))))))
(listen-ons
(list
;; this forum help suggests that I listen on 0.0.0.0 and NOT eth0
;; https://serverfault.com/questions/726795/opensmtpd-wont-work-at-reboot
;; this listens for email from the outside world
(opensmtpd-listen-on
(interface interface)
(port 25)
(secure-connection "tls")
(pki smtp.gnucode.me)
)
;; this lets local users logged into the system via ssh send email
(opensmtpd-listen-on
(interface "lo")
(port 25)
(secure-connection "tls")
(pki smtp.gnucode.me))
(opensmtpd-listen-on
(interface interface)
(port 465)
(secure-connection "smtps")
(pki smtp.gnucode.me)
(auth "creds"))
(opensmtpd-listen-on
(interface interface)
(port 587)
(secure-connection "tls-require")
(pki smtp.gnucode.me)
(auth "creds"))))
(actions
(list
(opensmtpd-action
(name "receive")
(method
(opensmtpd-local-delivery-configuration
(method (opensmtpd-maildir-configuration
(pathname "/home/%{rcpt.user}/Maildir")
(junk #t)))
(virtual "vusers"))))
;; (opensmtpd-action
;; (name "send")
;; (method (opensmtpd-relay-configuration)))
))
(matches (list
(opensmtpd-match
(name "send")
(for "for any")
(from "from any")
(auth #t))
(opensmtpd-match
(name "receive")
(from "from any")
(for "for domain <vdoms>"))
(opensmtpd-match
(name "receive")
(for "for local"))))))))
%desktop-services)
This is the type of the OpenSMTPD (https://www.opensmtpd.org) service, whose
value should be an opensmtpd-configuration
object as in this example:
,#+BEGIN_SRC scheme (service opensmtpd-service-type (opensmtpd-configuration (pkis (list ...)) (listen-ons (list ...)) (filters (list ...)) (matches (list ...)) (actions (list ...)))) #+END_SRC
Data type representing the configuration of opensmtpd.
package
(default: OPENSMTPD)Package object of the OpenSMTPD SMTP server.
config-file
(default: #f
) File-like object of the OpenSMTPD configuration file to use. 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. Run man smtpd.conf
for more information.
actions
default: #+BEGIN_SRC scheme (list (opensmtpd-action (name "local") (method (opensmtpd-local-delivery-configuration (method "mbox")))) (opensmtpd-action (name "outbound") (method (opensmtpd-relay-configuration)))) #+END_SRC
A list of <opensmtpd-action>
records.
The data type representing the configuration of an ~~ record.
<opensmtpd-action>
: name
(default: "local"
)The string name of the of the action.
<opensmtpd-action> : ~method
(default:The local delivery configuration, which is either a
<opensmtpd-local-delivery-configuration>
or a
<opensmtpd-relay-configuration>
record.
The data type representing the configuration of an
<opensmtpd-local-delivery-configuration>
record.
<opensmtpd-local-delivery-configuration>
: method
(default:The local delivery method. Either "mbox"
, "expand-only"
,
"forward-only"
, <opensmtpd-lmtp-configuration>
,
<opensmtpd-maildir-configuration>
, or
<opensmtpd-mda-configuration>
.
alias
(default: #f
) Use the mapping table for aliases expansion. alias
is a string
table name. The string must begin with "<" and end with ">". For
example "".
ttl
(default: )user
(default: )userbase
(default: )virtual
(default: )wrapper
(default: )