···
1
-
{ config, lib, pkgs, ... }:
1
+
{ config, options, pkgs, lib, ... }:
cfg = config.services.rspamd;
8
+
opts = options.services.rspamd;
9
-
mkBindSockets = socks: concatStringsSep "\n" (map (each: " bind_socket = \"${each}\"") socks);
10
+
bindSocketOpts = {options, config, ... }: {
14
+
example = "localhost:11333";
16
+
Socket for this worker to listen on in a format acceptable by rspamd.
22
+
description = "Mode to set on unix socket";
26
+
default = "${cfg.user}";
27
+
description = "Owner to set on unix socket";
31
+
default = "${cfg.group}";
32
+
description = "Group to set on unix socket";
34
+
rawEntry = mkOption {
39
+
config.rawEntry = let
40
+
maybeOption = option:
41
+
optionalString options.${option}.isDefined " ${option}=${config.${option}}";
43
+
if (!(hasPrefix "/" config.socket)) then "${config.socket}"
44
+
else "${config.socket}${maybeOption "mode"}${maybeOption "owner"}${maybeOption "group"}";
47
+
workerOpts = { name, ... }: {
50
+
type = types.nullOr types.bool;
52
+
description = "Whether to run the rspamd worker.";
55
+
type = types.nullOr types.str;
57
+
description = "Name of the worker";
60
+
type = types.nullOr (types.enum [
61
+
"normal" "controller" "fuzzy_storage" "proxy" "lua"
63
+
description = "The type of this worker";
65
+
bindSockets = mkOption {
66
+
type = types.listOf (types.either types.str (types.submodule bindSocketOpts));
69
+
List of sockets to listen, in format acceptable by rspamd
72
+
socket = "/run/rspamd.sock";
76
+
apply = value: map (each: if (isString each)
77
+
then if (isUnixSocket each)
78
+
then {socket = each; owner = cfg.user; group = cfg.group; mode = "0644"; rawEntry = "${each}";}
79
+
else {socket = each; rawEntry = "${each}";}
83
+
type = types.nullOr types.int;
86
+
Number of worker instances to run
89
+
includes = mkOption {
90
+
type = types.listOf types.str;
93
+
List of files to include in configuration
96
+
extraConfig = mkOption {
99
+
description = "Additional entries to put verbatim into worker section of rspamd config file.";
102
+
config = mkIf (name == "normal" || name == "controller" || name == "fuzzy") {
103
+
type = mkDefault name;
104
+
includes = mkDefault [ "$CONFDIR/worker-${name}.inc" ];
105
+
bindSockets = mkDefault (if name == "normal"
107
+
socket = "/run/rspamd/rspamd.sock";
112
+
else if name == "controller"
113
+
then [ "localhost:11334" ]
118
+
indexOf = default: start: list: e:
121
+
else if (head list) == e then start
122
+
else (indexOf default (start + (length (listenStreams (head list).socket))) (tail list) e);
124
+
systemdSocket = indexOf (abort "Socket not found") 0 allSockets;
126
+
isUnixSocket = socket: hasPrefix "/" (if (isString socket) then socket else socket.socket);
127
+
isPort = hasPrefix "*:";
128
+
isIPv4Socket = hasPrefix "*v4:";
129
+
isIPv6Socket = hasPrefix "*v6:";
130
+
isLocalHost = hasPrefix "localhost:";
131
+
listenStreams = socket:
132
+
if (isLocalHost socket) then
133
+
let port = (removePrefix "localhost:" socket);
134
+
in [ "127.0.0.1:${port}" ] ++ (if config.networking.enableIPv6 then ["[::1]:${port}"] else [])
135
+
else if (isIPv6Socket socket) then [removePrefix "*v6:" socket]
136
+
else if (isPort socket) then [removePrefix "*:" socket]
137
+
else if (isIPv4Socket socket) then
138
+
throw "error: IPv4 only socket not supported in rspamd with socket activation"
139
+
else if (length (splitString " " socket)) != 1 then
140
+
throw "error: string options not supported in rspamd with socket activation"
143
+
mkBindSockets = enabled: socks: concatStringsSep "\n " (flatten (map (each:
144
+
if cfg.socketActivation && enabled != false then
145
+
let systemd = (systemdSocket each);
146
+
in (imap (idx: e: "bind_socket = \"systemd:${toString (systemd + idx - 1)}\";") (listenStreams each.socket))
147
+
else "bind_socket = \"${each.rawEntry}\";") socks));
11
-
rspamdConfFile = pkgs.writeText "rspamd.conf"
149
+
rspamdConfFile = pkgs.writeText "rspamd.conf"
.include "$CONFDIR/common.conf"
···
.include "$CONFDIR/logging.inc"
26
-
${mkBindSockets cfg.bindSocket}
27
-
.include "$CONFDIR/worker-normal.inc"
31
-
${mkBindSockets cfg.bindUISocket}
32
-
.include "$CONFDIR/worker-controller.inc"
163
+
${concatStringsSep "\n" (mapAttrsToList (name: value: ''
164
+
worker ${optionalString (value.name != "normal" && value.name != "controller") "${value.name}"} {
165
+
type = "${value.type}";
166
+
${optionalString (value.enable != null)
167
+
"enabled = ${if value.enable != false then "yes" else "no"};"}
168
+
${mkBindSockets value.enable value.bindSockets}
169
+
${optionalString (value.count != null) "count = ${toString value.count};"}
170
+
${concatStringsSep "\n " (map (each: ".include \"${each}\"") value.includes)}
171
+
${value.extraConfig}
178
+
allMappedSockets = flatten (mapAttrsToList (name: value:
179
+
if value.enable != false
180
+
then imap (idx: each: {
184
+
}) value.bindSockets
185
+
else []) cfg.workers);
186
+
allSockets = map (e: e.value) allMappedSockets;
188
+
allSocketNames = map (each: "rspamd-${each.name}-${toString each.index}.socket") allMappedSockets;
···
enable = mkEnableOption "Whether to run the rspamd daemon.";
description = "Whether to run the rspamd daemon in debug mode.";
55
-
bindSocket = mkOption {
56
-
type = types.listOf types.str;
58
-
"/run/rspamd/rspamd.sock mode=0660 owner=${cfg.user} group=${cfg.group}"
61
-
"/run/rspamd/rspamd.sock mode=0660 owner=${cfg.user} group=${cfg.group}"
208
+
socketActivation = mkOption {
64
-
List of sockets to listen, in format acceptable by rspamd
68
-
"/run/rspamd.sock mode=0666 owner=rspamd"
211
+
Enable systemd socket activation for rspamd.
74
-
bindUISocket = mkOption {
75
-
type = types.listOf types.str;
215
+
workers = mkOption {
216
+
type = with types; attrsOf (submodule workerOpts);
80
-
List of sockets for web interface, in format acceptable by rspamd
218
+
Attribute set of workers to start.
224
+
example = literalExample ''
227
+
includes = [ "$CONFDIR/worker-normal.inc" ];
229
+
socket = "/run/rspamd/rspamd.sock";
231
+
owner = "${cfg.user}";
232
+
group = "${cfg.group}";
236
+
includes = [ "$CONFDIR/worker-controller.inc" ];
237
+
bindSockets = [ "[::1]:11334" ];
···
config = mkIf cfg.enable {
275
+
services.rspamd.socketActivation = mkDefault (!opts.bindSocket.isDefined && !opts.bindUISocket.isDefined);
278
+
assertion = !cfg.socketActivation || !(opts.bindSocket.isDefined || opts.bindUISocket.isDefined);
279
+
message = "Can't use socketActivation for rspamd when using renamed bind socket options";
# Allow users to run 'rspamc' and 'rspamadm'.
environment.systemPackages = [ pkgs.rspamd ];
···
gid = config.ids.gids.rspamd;
297
+
environment.etc."rspamd.conf".source = rspamdConfFile;
systemd.services.rspamd = {
description = "Rspamd Service";
134
-
wantedBy = [ "multi-user.target" ];
135
-
after = [ "network.target" ];
302
+
wantedBy = mkIf (!cfg.socketActivation) [ "multi-user.target" ];
303
+
after = [ "network.target" ] ++
304
+
(if cfg.socketActivation then allSocketNames else []);
305
+
requires = mkIf cfg.socketActivation allSocketNames;
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
RuntimeDirectory = "rspamd";
312
+
Sockets = mkIf cfg.socketActivation (concatStringsSep " " allSocketNames);
···
${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /var/lib/rspamd
320
+
systemd.sockets = mkIf cfg.socketActivation
321
+
(listToAttrs (map (each: {
322
+
name = "rspamd-${each.name}-${toString each.index}";
324
+
description = "Rspamd socket ${toString each.index} for worker ${each.name}";
325
+
wantedBy = [ "sockets.target" ];
326
+
listenStreams = (listenStreams each.value.socket);
328
+
BindIPv6Only = mkIf (isIPv6Socket each.value.socket) "ipv6-only";
329
+
Service = "rspamd.service";
330
+
SocketUser = mkIf (isUnixSocket each.value.socket) each.value.owner;
331
+
SocketGroup = mkIf (isUnixSocket each.value.socket) each.value.group;
332
+
SocketMode = mkIf (isUnixSocket each.value.socket) each.value.mode;
335
+
}) allMappedSockets));
338
+
(mkRenamedOptionModule [ "services" "rspamd" "bindSocket" ] [ "services" "rspamd" "workers" "normal" "bindSockets" ])
339
+
(mkRenamedOptionModule [ "services" "rspamd" "bindUISocket" ] [ "services" "rspamd" "workers" "controller" "bindSockets" ])