From 9e772d166cb5b9654899e3d70d3006a494fb09b0 Mon Sep 17 00:00:00 2001
From: Symphorien Gibol <symphorien+git@xlumurb.eu>
Date: Fri, 3 Apr 2020 12:00:00 +0000
Subject: [PATCH] rspamd: configure redis backend

The sqlite backed is deprecated, and the redis backend is the default
since rspamd 2.0.

Not having redis started results in such errors:
rspamd_redis_init: cannot init redis backend for BAYES_SPAM

To migrate the sqlite database, run

rspamadm statconvert --spam-db /var/lib/rspamd/bayes.spam.sqlite --ham-db /var/lib/rspamd/bayes.ham.sqlite -h 127.0.0.1:6379 --symbol-ham BAYES_HAM --symbol-spam BAYES_SPAM

The current module implements the recommended configuration that this
utility prints out.
---
 default.nix            | 40 ++++++++++++++++++++++++++++++++++++++++
 mail-server/rspamd.nix | 17 +++++++++++++++--
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/default.nix b/default.nix
index e6aaf8c..86cbe19 100644
--- a/default.nix
+++ b/default.nix
@@ -480,6 +480,46 @@ in
       '';
     };
 
+    redis = {
+      address = mkOption {
+        type = types.str;
+        # read the default from nixos' redis module
+        default = let
+          cf = config.services.redis.bind;
+          cfdefault = if cf == null then "127.0.0.1" else cf;
+          ips = lib.strings.splitString " " cfdefault;
+          ip = lib.lists.head (ips ++ [ "127.0.0.1" ]);
+          isIpv6 = ip: lib.lists.elem ":" (lib.stringToCharacters ip);
+        in
+        if (ip == "0.0.0.0" || ip == "::")
+        then "127.0.0.1"
+        else if isIpv6 ip then "[${ip}]" else ip;
+        description = ''
+          Address that rspamd should use to contact redis. The default value
+          is read from <literal>config.services.redis.bind</literal>.
+        '';
+      };
+
+      port = mkOption {
+        type = types.port;
+        default = config.services.redis.port;
+        description = ''
+          Port that rspamd should use to contact redis. The default value is
+          read from <literal>config.services.redis.port<literal>.
+        '';
+      };
+
+      password = mkOption {
+        type = types.nullOr types.str;
+        default = config.services.redis.requirePass;
+        description = ''
+          Password that rspamd should use to contact redis, or null if not
+          required. The default value is read from
+          <literal>config.services.redis.requirePass<literal>.
+        '';
+      };
+    };
+
     rewriteMessageId = mkOption {
       type = types.bool;
       default = false;
diff --git a/mail-server/rspamd.nix b/mail-server/rspamd.nix
index b46b7de..f5a2d20 100644
--- a/mail-server/rspamd.nix
+++ b/mail-server/rspamd.nix
@@ -32,6 +32,16 @@ in
           "milter_headers.conf" = { text = ''
               extended_spam_headers = yes;
           ''; };
+          "redis.conf" = { text = ''
+              servers = "${cfg.redis.address}:${toString cfg.redis.port}";
+          '' + (lib.optionalString (cfg.redis.password != null) ''
+              password = "${cfg.redis.password}";
+          ''); };
+          "classifier-bayes.conf" = { text = ''
+              cache {
+                backend = "redis";
+              }
+          ''; };
           "antivirus.conf" = lib.mkIf cfg.virusScanning { text = ''
               clamav {
                 action = "reject";
@@ -80,9 +90,12 @@ in
       };
 
     };
+
+    services.redis.enable = true;
+
     systemd.services.rspamd = {
-      requires = (lib.optional cfg.virusScanning "clamav-daemon.service");
-      after = (lib.optional cfg.virusScanning "clamav-daemon.service");
+      requires = [ "redis.service" ] ++ (lib.optional cfg.virusScanning "clamav-daemon.service");
+      after = [ "redis.service" ] ++ (lib.optional cfg.virusScanning "clamav-daemon.service");
     };
 
     systemd.services.postfix = {