services: Add rspamd-service-type.
* gnu/services/mail.scm (rspamd-service-type): New variable. * gnu/tests/mail.scm (%test-rspamd): New variable. * doc/guix.texi: Document it. Co-authored-by: Saku Laesvuori <saku@laesvuori.fi> Change-Id: I7196643f087ffe9fc91aab231b69d5ed8dc9d198 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
parent
7ce0c79e7a
commit
b681e339fa
|
@ -120,6 +120,8 @@ Copyright @copyright{} 2023 Zheng Junjie@*
|
|||
Copyright @copyright{} 2023 Brian Cully@*
|
||||
Copyright @copyright{} 2023 Felix Lechner@*
|
||||
Copyright @copyright{} 2023 Foundation Devices, Inc.@*
|
||||
Copyright @copyright{} 2023 Thomas Ieong@*
|
||||
Copyright @copyright{} 2023 Saku Laesvuori@*
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
|
@ -27639,6 +27641,66 @@ on TCP port 5232 of @code{localhost} and use the @code{htpasswd} file at
|
|||
@end table
|
||||
@end deftp
|
||||
|
||||
@subsubheading Rspamd Service
|
||||
@cindex email
|
||||
@cindex spam
|
||||
|
||||
@defvar rspamd-service-type
|
||||
This is the type of the @uref{https://rspamd.com/, Rspamd} filtering
|
||||
system whose value should be a @code{rspamd-configuration}.
|
||||
@end defvar
|
||||
|
||||
@c %start of fragment
|
||||
|
||||
@deftp {Data Type} rspamd-configuration
|
||||
Available @code{rspamd-configuration} fields are:
|
||||
|
||||
@table @asis
|
||||
@item @code{package} (default: @code{rspamd}) (type: file-like)
|
||||
The package that provides rspamd.
|
||||
|
||||
@item @code{config-file} (default: @code{%default-rspamd-config-file}) (type: file-like)
|
||||
File-like object of the configuration file to use. By default all
|
||||
workers are enabled except fuzzy and they are binded to their usual
|
||||
ports, e.g localhost:11334, localhost:11333 and so on
|
||||
|
||||
@item @code{local.d-files} (default: @code{()}) (type: directory-tree)
|
||||
Configuration files in local.d, provided as a list of two element lists
|
||||
where the first element is the filename and the second one is a
|
||||
file-like object. Settings in these files will be merged with the
|
||||
defaults.
|
||||
|
||||
@item @code{override.d-files} (default: @code{()}) (type: directory-tree)
|
||||
Configuration files in override.d, provided as a list of two element
|
||||
lists where the first element is the filename and the second one is a
|
||||
file-like object. Settings in these files will override the defaults.
|
||||
|
||||
@item @code{user} (default: @code{%default-rspamd-account}) (type: user-account)
|
||||
The user to run rspamd as.
|
||||
|
||||
@item @code{group} (default: @code{%default-rspamd-group}) (type: user-group)
|
||||
The group to run rspamd as.
|
||||
|
||||
@item @code{debug?} (default: @code{#f}) (type: boolean)
|
||||
Force debug output.
|
||||
|
||||
@item @code{insecure?} (default: @code{#f}) (type: boolean)
|
||||
Ignore running workers as privileged users.
|
||||
|
||||
@item @code{skip-template?} (default: @code{#f}) (type: boolean)
|
||||
Do not apply Jinja templates.
|
||||
|
||||
@item @code{shepherd-requirements} (default: @code{(loopback)}) (type: list-of-symbols)
|
||||
This is a list of symbols naming Shepherd services that this service
|
||||
will depend on.
|
||||
|
||||
@end table
|
||||
|
||||
@end deftp
|
||||
|
||||
|
||||
@c %end of fragment
|
||||
|
||||
@node Messaging Services
|
||||
@subsection Messaging Services
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;;; Copyright © 2017, 2020 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2019 Kristofer Buffington <kristoferbuffington@gmail.com>
|
||||
;;; Copyright © 2020 Jonathan Brielmaier <jonathan.brielmaier@web.de>
|
||||
;;; Copyright © 2023 Thomas Ieong <th.ieong@free.fr>
|
||||
;;; Copyright © 2023 Saku Laesvuori <saku@laesvuori.fi>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
|
@ -80,7 +82,13 @@
|
|||
radicale-configuration
|
||||
radicale-configuration?
|
||||
radicale-service-type
|
||||
%default-radicale-config-file))
|
||||
%default-radicale-config-file
|
||||
|
||||
rspamd-configuration
|
||||
rspamd-service-type
|
||||
%default-rspamd-account
|
||||
%default-rspamd-config-file
|
||||
%default-rspamd-group))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
|
@ -1987,3 +1995,193 @@ hosts = localhost:5232"))
|
|||
(service-extension account-service-type (const %radicale-accounts))
|
||||
(service-extension activation-service-type radicale-activation)))
|
||||
(default-value (radicale-configuration))))
|
||||
|
||||
;;;
|
||||
;;; Rspamd.
|
||||
;;;
|
||||
|
||||
(define (directory-tree? xs)
|
||||
(match xs
|
||||
((((? string?) (? file-like?)) ...) #t)
|
||||
(_ #f)))
|
||||
|
||||
(define-configuration/no-serialization rspamd-configuration
|
||||
(package
|
||||
(file-like rspamd)
|
||||
"The package that provides rspamd.")
|
||||
(config-file
|
||||
(file-like %default-rspamd-config-file)
|
||||
"File-like object of the configuration file to use. By default
|
||||
all workers are enabled except fuzzy and they are binded
|
||||
to their usual ports, e.g localhost:11334, localhost:11333 and so on")
|
||||
(local.d-files
|
||||
(directory-tree '())
|
||||
"Configuration files in local.d, provided as a list of two element lists where
|
||||
the first element is the filename and the second one is a file-like object. Settings
|
||||
in these files will be merged with the defaults.")
|
||||
(override.d-files
|
||||
(directory-tree '())
|
||||
"Configuration files in override.d, provided as a list of two element lists where
|
||||
the first element is the filename and the second one is a file-like object. Settings
|
||||
in these files will override the defaults.")
|
||||
(user
|
||||
(user-account %default-rspamd-account)
|
||||
"The user to run rspamd as.")
|
||||
(group
|
||||
(user-group %default-rspamd-group)
|
||||
"The group to run rspamd as.")
|
||||
(debug?
|
||||
(boolean #f)
|
||||
"Force debug output.")
|
||||
(insecure?
|
||||
(boolean #f)
|
||||
"Ignore running workers as privileged users.")
|
||||
(skip-template?
|
||||
(boolean #f)
|
||||
"Do not apply Jinja templates.")
|
||||
(shepherd-requirements
|
||||
(list-of-symbols '(loopback))
|
||||
"This is a list of symbols naming Shepherd services that this service
|
||||
will depend on."))
|
||||
|
||||
(define %default-rspamd-account
|
||||
(user-account
|
||||
(name "rspamd")
|
||||
(group "rspamd")
|
||||
(system? #t)
|
||||
(comment "Rspamd daemon")
|
||||
(home-directory "/var/empty")
|
||||
(shell (file-append shadow "/sbin/nologin"))))
|
||||
|
||||
(define %default-rspamd-group
|
||||
(user-group
|
||||
(name "rspamd")
|
||||
(system? #t)))
|
||||
|
||||
(define %default-rspamd-config-file
|
||||
(plain-file "rspamd.conf" "
|
||||
.include \"$CONFDIR/common.conf\"
|
||||
|
||||
options {
|
||||
pidfile = \"$RUNDIR/rspamd.pid\";
|
||||
.include \"$CONFDIR/options.inc\"
|
||||
.include(try=true; priority=1,duplicate=merge) \"$LOCAL_CONFDIR/local.d/options.inc\"
|
||||
.include(try=true; priority=10) \"$LOCAL_CONFDIR/override.d/options.inc\"
|
||||
}
|
||||
|
||||
logging {
|
||||
type = \"file\";
|
||||
filename = \"$LOGDIR/rspamd.log\";
|
||||
.include \"$CONFDIR/logging.inc\"
|
||||
.include(try=true; priority=1,duplicate=merge) \"$LOCAL_CONFDIR/local.d/logging.inc\"
|
||||
.include(try=true; priority=10) \"$LOCAL_CONFDIR/override.d/logging.inc\"
|
||||
}
|
||||
|
||||
worker \"normal\" {
|
||||
bind_socket = \"localhost:11333\";
|
||||
.include \"$CONFDIR/worker-normal.inc\"
|
||||
.include(try=true; priority=1,duplicate=merge) \"$LOCAL_CONFDIR/local.d/worker-normal.inc\"
|
||||
.include(try=true; priority=10) \"$LOCAL_CONFDIR/override.d/worker-normal.inc\"
|
||||
}
|
||||
|
||||
worker \"controller\" {
|
||||
bind_socket = \"localhost:11334\";
|
||||
.include \"$CONFDIR/worker-controller.inc\"
|
||||
.include(try=true; priority=1,duplicate=merge) \"$LOCAL_CONFDIR/local.d/worker-controller.inc\"
|
||||
.include(try=true; priority=10) \"$LOCAL_CONFDIR/override.d/worker-controller.inc\"
|
||||
}
|
||||
|
||||
worker \"rspamd_proxy\" {
|
||||
bind_socket = \"localhost:11332\";
|
||||
.include \"$CONFDIR/worker-proxy.inc\"
|
||||
.include(try=true; priority=1,duplicate=merge) \"$LOCAL_CONFDIR/local.d/worker-proxy.inc\"
|
||||
.include(try=true; priority=10) \"$LOCAL_CONFDIR/override.d/worker-proxy.inc\"
|
||||
}
|
||||
|
||||
# Local fuzzy storage is disabled by default
|
||||
|
||||
worker \"fuzzy\" {
|
||||
bind_socket = \"localhost:11335\";
|
||||
count = -1; # Disable by default
|
||||
.include \"$CONFDIR/worker-fuzzy.inc\"
|
||||
.include(try=true; priority=1,duplicate=merge) \"$LOCAL_CONFDIR/local.d/worker-fuzzy.inc\"
|
||||
.include(try=true; priority=10) \"$LOCAL_CONFDIR/override.d/worker-fuzzy.inc\"
|
||||
}
|
||||
"))
|
||||
|
||||
(define (rspamd-accounts config)
|
||||
(match-record config <rspamd-configuration>
|
||||
(user group)
|
||||
(list group user)))
|
||||
|
||||
(define (rspamd-shepherd-service config)
|
||||
(match-record config <rspamd-configuration>
|
||||
(package config-file user group debug? insecure? skip-template?
|
||||
local.d-files override.d-files shepherd-requirements)
|
||||
(list
|
||||
(shepherd-service
|
||||
(provision '(rspamd))
|
||||
(documentation "Run the rspamd daemon.")
|
||||
(requirement shepherd-requirements)
|
||||
(start (let ((rspamd (file-append package "/bin/rspamd"))
|
||||
(local-confdir
|
||||
(file-union
|
||||
"rspamd-local-confdir"
|
||||
`(("local.d" ,(file-union "local.d" local.d-files))
|
||||
("override.d" ,(file-union "override.d" override.d-files))))))
|
||||
(with-imported-modules (source-module-closure '((gnu build activation)))
|
||||
#~(begin
|
||||
(use-modules (gnu build activation)) ; for mkdir-p/perms
|
||||
(let ((user (getpwnam #$(user-account-name user))))
|
||||
(mkdir-p/perms "/var/run/rspamd" user #o755)
|
||||
(mkdir-p/perms "/var/log/rspamd" user #o755)
|
||||
(mkdir-p/perms "/var/lib/rspamd" user #o755))
|
||||
(make-forkexec-constructor
|
||||
(list #$rspamd "--config" #$config-file
|
||||
"--var" (string-append "LOCAL_CONFDIR=" #$local-confdir)
|
||||
"--no-fork"
|
||||
#$@(if debug?
|
||||
'("--debug")
|
||||
'())
|
||||
#$@(if insecure?
|
||||
'("--insecure")
|
||||
'())
|
||||
#$@(if skip-template?
|
||||
'("--skip-template")
|
||||
'()))
|
||||
#:user #$(user-account-name user)
|
||||
#:group #$(user-group-name group))))))
|
||||
(stop #~(make-kill-destructor))
|
||||
(actions
|
||||
(list
|
||||
(shepherd-configuration-action config-file)
|
||||
(shepherd-action
|
||||
(name 'reload)
|
||||
(documentation "Reload rspamd.")
|
||||
(procedure
|
||||
#~(lambda (pid)
|
||||
(if pid
|
||||
(begin
|
||||
(kill pid SIGHUP)
|
||||
(display "Service rspamd has been reloaded"))
|
||||
(format #t "Service rspamd is not running.")))))
|
||||
(shepherd-action
|
||||
(name 'reopen)
|
||||
(documentation "Reopen log files.")
|
||||
(procedure
|
||||
#~(lambda (pid)
|
||||
(if pid
|
||||
(begin
|
||||
(kill pid SIGUSR1)
|
||||
(display "Reopening the logs for rspamd"))
|
||||
(format #t "Service rspamd is not running.")))))))))))
|
||||
|
||||
(define rspamd-service-type
|
||||
(service-type
|
||||
(name 'rspamd)
|
||||
(description "Run the rapid spam filtering system.")
|
||||
(extensions
|
||||
(list
|
||||
(service-extension shepherd-root-service-type rspamd-shepherd-service)
|
||||
(service-extension account-service-type rspamd-accounts)))
|
||||
(default-value (rspamd-configuration))))
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org>
|
||||
;;; Copyright © 2019 Christopher Baines <mail@cbaines.net>
|
||||
;;; Copyright © 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2023 Thomas Ieong <th.ieong@free.fr>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
|
@ -40,7 +41,8 @@
|
|||
#:export (%test-opensmtpd
|
||||
%test-exim
|
||||
%test-dovecot
|
||||
%test-getmail))
|
||||
%test-getmail
|
||||
%test-rspamd))
|
||||
|
||||
(define %opensmtpd-os
|
||||
(simple-operating-system
|
||||
|
@ -579,3 +581,66 @@ Subject: Hello Nice to meet you!")
|
|||
(name "getmail")
|
||||
(description "Connect to a running Getmail server.")
|
||||
(value (run-getmail-test))))
|
||||
|
||||
(define %rspamd-os
|
||||
(simple-operating-system
|
||||
(service rspamd-service-type)))
|
||||
|
||||
(define (run-rspamd-test)
|
||||
"Return a test of an OS running Rspamd service."
|
||||
|
||||
(define vm
|
||||
(virtual-machine
|
||||
(marionette-operating-system
|
||||
%rspamd-os
|
||||
#:imported-modules '((gnu services herd)))))
|
||||
|
||||
(define test
|
||||
(with-imported-modules '((gnu build marionette))
|
||||
#~(begin
|
||||
(use-modules (srfi srfi-64)
|
||||
(gnu build marionette))
|
||||
|
||||
(define marionette
|
||||
(make-marionette '(#$vm)))
|
||||
|
||||
(test-runner-current (system-test-runner #$output))
|
||||
(test-begin "rspamd")
|
||||
|
||||
(test-assert "service is running"
|
||||
(marionette-eval
|
||||
'(begin
|
||||
(use-modules (gnu services herd))
|
||||
(start-service 'rspamd))
|
||||
marionette))
|
||||
|
||||
(test-assert "rspamd socket ready"
|
||||
(wait-for-unix-socket
|
||||
"/var/lib/rspamd/rspamd.sock"
|
||||
marionette))
|
||||
|
||||
(test-assert "rspamd log file"
|
||||
(wait-for-file "/var/log/rspamd/rspamd.log" marionette))
|
||||
|
||||
;; Check that we can access the web ui
|
||||
|
||||
(test-equal "http-get"
|
||||
200
|
||||
(marionette-eval
|
||||
'(begin
|
||||
(use-modules (web client)
|
||||
(web response))
|
||||
;; HEAD returns 500 internal server error, so use GET even though
|
||||
;; only the headers are relevant
|
||||
(response-code (http-get "http://localhost:11334")))
|
||||
marionette))
|
||||
|
||||
(test-end))))
|
||||
|
||||
(gexp->derivation "rspamd-test" test))
|
||||
|
||||
(define %test-rspamd
|
||||
(system-test
|
||||
(name "rspamd")
|
||||
(description "Basic rspamd service test.")
|
||||
(value (run-rspamd-test))))
|
||||
|
|
Reference in New Issue