diff --git a/doc/guix.texi b/doc/guix.texi
index 05615b9549..c1070a5244 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -114,6 +114,7 @@
 Copyright @copyright{} 2023 Giacomo Leidi@*
 Copyright @copyright{} 2022 Antero Mejr@*
 Copyright @copyright{} 2023 Bruno Victal@*
+Copyright @copyright{} 2023 Thomas Ieong@*
 
 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -26365,6 +26366,48 @@ Mail Services
 @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
+
+@deftp {Data Type} rspamd-configuration
+Data type representing the configuration of @command{rspamd}.
+
+@table @asis
+@item @code{package} (default: @code{rspamd})
+The package that provides @command{rspamd}.
+
+@item @code{config-file} (default: @code{%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.
+
+@item @code{user} (default: @code{"rspamd"})
+The user to run rspamd as.
+
+@item @code{group} (default: @code{"rspamd"})
+The user to run rspamd as.
+
+@item @code{pid-file} (default: @code{"/var/run/rspamd/rspamd.pid"})
+Where to store the PID file.
+
+@item @code{debug?} (default: @code{#f})
+Force debug output.
+
+@item @code{insecure?} (default: @code{#f})
+Ignore running workers as privileged users (insecure).
+
+@item @code{skip-template?} (default: @code{#f})
+Do not apply Jinja templates.
+
+@end table
+@end deftp
+
 @node Messaging Services
 @subsection Messaging Services
 
diff --git a/gnu/services/mail.scm b/gnu/services/mail.scm
index 6f588679b1..8a4af26f66 100644
--- a/gnu/services/mail.scm
+++ b/gnu/services/mail.scm
@@ -5,6 +5,7 @@
 ;;; 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>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -79,7 +80,11 @@ (define-module (gnu services mail)
             radicale-configuration
             radicale-configuration?
             radicale-service-type
-            %default-radicale-config-file))
+            %default-radicale-config-file
+
+            rspamd-configuration
+	    rspamd-service-type
+	    %default-rspamd-config-file))
 
 ;;; Commentary:
 ;;;
@@ -1984,3 +1989,187 @@ (define radicale-service-type
           (service-extension account-service-type (const %radicale-accounts))
           (service-extension activation-service-type radicale-activation)))
    (default-value (radicale-configuration))))
+
+;;;
+;;; Rspamd.
+;;;
+
+(define-maybe boolean)
+
+(define-configuration rspamd-configuration
+  (package
+    (file-like rspamd)
+    "The package that provides rspamd."
+    empty-serializer)
+  (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")
+  (user
+   (string "rspamd")
+   "The user to run rspamd as."
+   empty-serializer)
+  (group
+   (string "rspamd")
+   "The group to run rspamd as."
+   empty-serializer)
+  (pid-file
+   (string "/var/run/rspamd/rspamd.pid")
+   "Where to store the PID file."
+   empty-serializer)
+  (debug?
+   maybe-boolean
+   "Force debug output."
+   empty-serializer)
+  (insecure?
+   maybe-boolean
+   "Ignore running workers as privileged users (insecure)."
+   empty-serializer)
+  (skip-template?
+   maybe-boolean
+   "Do not apply Jinja templates."
+   empty-serializer))
+
+(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 (user-group
+	   (name group)
+	   (system? #t))
+	  (user-account
+	   (name user)
+	   (group group)
+	   (system? #t)
+	   (comment "Rspamd daemon")
+	   (home-directory "/var/empty")
+	   (shell (file-append shadow "/sbin/nologin"))))))
+
+(define (rspamd-shepherd-service config)
+  (match-record config <rspamd-configuration>
+    (package config-file user group pid-file debug? insecure? skip-template?)
+    (list (shepherd-service
+	   (provision '(rspamd))
+	   (documentation "Run the rspamd daemon.")
+	   (requirement '(networking))
+	   (start (let ((rspamd (file-append package "/bin/rspamd")))
+		    #~(make-forkexec-constructor
+		       (list #$rspamd "-c" #$config-file
+			     #$@(if debug?
+				    '("--debug")
+				    '())
+			     #$@(if insecure?
+				    '("--insecure")
+				    '())
+			     #$@(if skip-template?
+				    '("--skip-template")
+				    '()))
+		       #:user #$user
+		       #:group #$group
+		       #:pid-file #$pid-file)))
+	   (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 'reopenlog)
+		   (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-activation config)
+  (match-record config <rspamd-configuration>
+    (package config-file user)
+    #~(begin
+	(use-modules (guix build utils)
+		     (ice-9 match))
+	(let ((user (getpwnam #$user)))
+	  (mkdir-p/perms "/etc/rspamd" user #o755)
+	  (mkdir-p/perms "/etc/rspamd/local.d" user #o755)
+	  (mkdir-p/perms "/etc/rspamd/override.d" user #o755)
+	  (mkdir-p/perms "/var/run/rspamd" user #o755)
+	  (mkdir-p/perms "/var/log/rspamd" user #o755)
+	  (mkdir-p/perms "/var/lib/rspamd" user #o755))
+	;; Check configuration file syntax.
+	(system* (string-append #$package "/bin/rspamadm")
+		 "configtest"
+		 "-c" #$config-file))))
+
+(define rspamd-profile
+  (compose list rspamd-configuration-package))
+
+(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)
+	  (service-extension activation-service-type rspamd-activation)
+	  (service-extension profile-service-type rspamd-profile)))
+   (default-value (rspamd-configuration))))
diff --git a/gnu/tests/mail.scm b/gnu/tests/mail.scm
index f13751b72f..f532d30805 100644
--- a/gnu/tests/mail.scm
+++ b/gnu/tests/mail.scm
@@ -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 @@ (define-module (gnu tests mail)
   #:export (%test-opensmtpd
             %test-exim
             %test-dovecot
-            %test-getmail))
+            %test-getmail
+            %test-rspamd))
 
 (define %opensmtpd-os
   (simple-operating-system
@@ -575,3 +577,86 @@ (define %test-getmail
    (name "getmail")
    (description "Connect to a running Getmail server.")
    (value (run-getmail-test))))
+
+(define %rspamd-os
+  (simple-operating-system
+   (service dhcp-client-service-type)
+   (service rspamd-service-type)))
+
+(define (run-rspamd-test)
+  "Return a test of an OS running Rspamd service."
+
+  (define rspamd-ports
+    '((22664 . 11332)    ;; proxy worker
+      (22666 . 11333)    ;; normal worker
+      (22668 . 11334)    ;; web controller
+      (22670 . 11335)))  ;; fuzzy worker
+
+  (define vm
+    (virtual-machine
+     (operating-system (marionette-operating-system
+                        %rspamd-os
+                        #:imported-modules '((gnu services herd))))
+     (port-forwardings rspamd-ports)))
+
+  (define test
+    (with-imported-modules '((gnu build marionette))
+      #~(begin
+          (use-modules (srfi srfi-64)
+                       (srfi srfi-11)
+                       (gnu build marionette)
+                       (web uri)
+                       (web client)
+                       (web response))
+
+          (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))
+
+
+          ;; Check mympd-service-type commit for reference
+          ;; TODO: For this test we need to authorize the controller to
+          ;; listen on other interfaces, e.g *:11334 instead of localhost:11334
+
+          ;; Check that we can access the web ui
+          (test-equal "http-get"
+            200
+            (begin
+              (let-values (((response text)
+                            (http-get "http://localhost:22668/"
+                                      #:decode-body? #t)))
+                (response-code response))))
+
+          (test-assert "rspamd socket ready"
+            (wait-for-unix-socket
+             "/var/lib/rspamd/rspamd.sock"
+             marionette))
+
+          (test-assert "rspamd pid ready"
+            (marionette-eval
+             '(file-exists? "/var/run/rspamd/rspamd.pid")
+             marionette))
+
+          (test-assert "rspamd log file"
+            (marionette-eval
+             '(file-exists? "/var/log/rspamd/rspamd.log")
+             marionette))
+
+          (test-end))))
+
+  (gexp->derivation "rspamd-test" test))
+
+(define %test-rspamd
+  (system-test
+   (name "rspamd")
+   (description "Send an email to a running rspamd server.")
+   (value (run-rspamd-test))))
