Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 52 additions & 15 deletions nixos/modules/services/mail/rmilter.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ let
rspamdCfg = config.services.rspamd;
cfg = config.services.rmilter;

inetSockets = map (sock: let s = stringSplit ":" sock; in "inet:${last s}:${head s}") cfg.bindInetSockets;
unixSockets = map (sock: "unix:${sock}") cfg.bindUnixSockets;

allSockets = unixSockets ++ inetSockets;

rmilterConf = ''
pidfile = /run/rmilter/rmilter.pid;
bind_socket = ${cfg.bindSocket};
bind_socket = ${if cfg.socketActivation then "fd:3" else concatStringsSep ", " allSockets};
tempdir = /tmp;

'' + (with cfg.rspamd; if enable then ''
Expand Down Expand Up @@ -68,14 +73,37 @@ in
'';
};

bindSocket = mkOption {
type = types.string;
default = "unix:/run/rmilter/rmilter.sock";
description = "Socket to listed for MTA requests";
bindUnixSockets = mkOption {
type = types.listOf types.str;
default = ["/run/rmilter.sock"];
description = ''
Unix domain sockets to listen for MTA requests.
'';
example = ''
"unix:/run/rmilter/rmilter.sock" or
"inet:11990@127.0.0.1"
'';
[ "/run/rmilter.sock"]
'';
};

bindInetSockets = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Inet addresses to listen (in format accepted by systemd.socket)
'';
example = ''
["127.0.0.1:11990"]
'';
};

socketActivation = mkOption {
type = types.bool;
default = true;
description = ''
Enable systemd socket activation for rmilter.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If socket activation is recommended, why make it optional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It recommended for domain socket setup, because rmilter (actually libmilter from sendmail) can't set proper permissions on socket.

So folks who prefer inet socket have option here.

(disabling socket activation not recommended
when unix socket used, and follow to wrong
permissions on unix domain socket.)
'';
};

rspamd = {
Expand All @@ -86,7 +114,7 @@ in

servers = mkOption {
type = types.listOf types.str;
default = ["r:0.0.0.0:11333"];
default = ["r:/run/rspamd.sock"];
description = ''
Spamd socket definitions.
Is server name is prefixed with r: it is rspamd server.
Expand Down Expand Up @@ -129,7 +157,7 @@ in
type = types.str;
description = "Addon to postfix configuration";
default = ''
smtpd_milters = ${cfg.bindSocket}
smtpd_milters = ${head allSockets}
# or for TCP socket
# # smtpd_milters = inet:localhost:9900
milter_protocol = 6
Expand Down Expand Up @@ -169,21 +197,30 @@ milter_default_action = accept

serviceConfig = {
ExecStart = "${pkgs.rmilter}/bin/rmilter ${optionalString cfg.debug "-d"} -n -c ${rmilterConfigFile}";
ExecReload = "/bin/kill -USR1 $MAINPID";
User = cfg.user;
Group = cfg.group;
PermissionsStartOnly = true;
Restart = "always";
RuntimeDirectory = "rmilter";
RuntimeDirectoryPermissions="0755";
};

preStart = ''
${pkgs.coreutils}/bin/mkdir -p /run/rmilter
${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /run/rmilter
'';
};

systemd.sockets.rmilter = mkIf cfg.socketActivation {
description = "Rmilter service socket";
wantedBy = [ "sockets.target" ];
socketConfig = {
ListenStream = cfg.bindUnixSockets ++ cfg.bindInetSockets;
SocketUser = cfg.user;
SocketGroup = cfg.group;
SocketMode = "0660";
};
};

services.postfix.extraConfig = optionalString cfg.postfix.enable cfg.postfix.configFragment;

users.users.postfix.extraGroups = [ cfg.group ];
};

}
59 changes: 57 additions & 2 deletions nixos/modules/services/mail/rspamd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,35 @@ let

cfg = config.services.rspamd;

mkBindSockets = socks: concatStringsSep "\n" (map (each: " bind_socket = \"${each}\"") socks);

rspamdConf =
''
.include "$CONFDIR/common.conf"

options {
pidfile = "$RUNDIR/rspamd.pid";
.include "$CONFDIR/options.inc"
}

logging {
type = "file";
filename = "$LOGDIR/rspamd.log";
.include "$CONFDIR/logging.inc"
}

worker {
${mkBindSockets cfg.bindSocket}
.include "$CONFDIR/worker-normal.inc"
}

worker {
${mkBindSockets cfg.bindUISocket}
.include "$CONFDIR/worker-controller.inc"
}
'';
rspamdConfFile = pkgs.writeText "rspamd.conf" rspamdConf;

in

{
Expand All @@ -26,6 +55,32 @@ in
description = "Whether to run the rspamd daemon in debug mode.";
};

bindSocket = mkOption {
type = types.listOf types.str;
default = [
"/run/rspamd.sock mode=0666 owner=${cfg.user}"
];
description = ''
List of sockets to listen, in format acceptable by rspamd
'';
example = ''
bindSocket = [
"/run/rspamd.sock mode=0666 owner=rspamd"
"*:11333"
];
'';
};

bindUISocket = mkOption {
type = types.listOf types.str;
default = [
"localhost:11334"
];
description = ''
List of sockets for web interface, in format acceptable by rspamd
'';
};

user = mkOption {
type = types.string;
default = "rspamd";
Expand Down Expand Up @@ -62,7 +117,7 @@ in

users.extraGroups = singleton {
name = cfg.group;
gid = config.ids.gids.spamd;
gid = config.ids.gids.rspamd;
};

systemd.services.rspamd = {
Expand All @@ -72,7 +127,7 @@ in
after = [ "network.target" ];

serviceConfig = {
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -f";
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
RuntimeDirectory = "/var/lib/rspamd";
PermissionsStartOnly = true;
Restart = "always";
Expand Down
3 changes: 2 additions & 1 deletion pkgs/development/libraries/libmemcached/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ stdenv.mkDerivation rec {
sha256 = "1nvxwdkxj2a2g39z0g8byxjwnw4pa5xlvsmdk081q63vmfywh7zb";
});

buildInputs = [ cyrus_sasl libevent ];
buildInputs = [ libevent ];
propagatedBuildInputs = [ cyrus_sasl ];

meta = with stdenv.lib; {
homepage = http://libmemcached.org;
Expand Down
16 changes: 11 additions & 5 deletions pkgs/servers/mail/rmilter/default.nix
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
{ stdenv, fetchFromGitHub, cmake, bison, flex, openssl, pcre, libmilter, opendkim }:
{ stdenv, fetchFromGitHub, cmake, bison, flex, openssl, pcre, libmilter, opendkim,
libmemcached }:

let patchedLibmilter = stdenv.lib.overrideDerivation libmilter (_ : {
patches = libmilter.patches ++ [ ./fd-passing-libmilter.patch ];
});
in

stdenv.mkDerivation rec {
name = "rmilter-${version}";
version = "1.7.3";
version = "1.8.1";

src = fetchFromGitHub {
owner = "vstakhov";
repo = "rmilter";
rev = version;
sha256 = "04xalaxq5xgg5ls0f4ayp8yhzdfq5gqjb8qwfyha3mrx4dqrgh7s";
sha256 = "0cplkc1acgysxn8id9wakd1fx0f76cazscpfqhrxyjbk5fb11ll4";
};

nativeBuildInputs = [ bison cmake flex ];
buildInputs = [ libmilter openssl pcre opendkim ];
buildInputs = [ libmemcached patchedLibmilter openssl pcre opendkim];

meta = with stdenv.lib; {
homepage = "https://github.com/vstakhov/rmilter";
license = licenses.bsd2;
license = licenses.asl20;
description = ''
Daemon to integrate rspamd and milter compatible MTA, for example
postfix or sendmail
Expand Down
80 changes: 80 additions & 0 deletions pkgs/servers/mail/rmilter/fd-passing-libmilter.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
Description: systemd-like socket activation support for libmilter
Author: Mikhail Gusarov <dottedmag@debian.org
diff --git a/libmilter/docs/smfi_setconn.html b/libmilter/docs/smfi_setconn.html
index 70a510e..013f04e 100644
--- a/libmilter/docs/smfi_setconn.html
+++ b/libmilter/docs/smfi_setconn.html
@@ -43,6 +43,7 @@ Set the socket through which this filter should communicate with sendmail.
<LI><CODE>{unix|local}:/path/to/file</CODE> -- A named pipe.
<LI><CODE>inet:port@{hostname|ip-address}</CODE> -- An IPV4 socket.
<LI><CODE>inet6:port@{hostname|ip-address}</CODE> -- An IPV6 socket.
+ <LI><CODE>fd:number</CODE> -- Pre-opened file descriptor.
</UL>
</TD></TR>
</TABLE>
diff --git a/libmilter/listener.c b/libmilter/listener.c
index 48c552f..2249a1f 100644
--- a/libmilter/listener.c
+++ b/libmilter/listener.c
@@ -197,6 +197,11 @@ mi_milteropen(conn, backlog, rmsocket, name)
L_socksize = sizeof addr.sin6;
}
#endif /* NETINET6 */
+ else if (strcasecmp(p, "fd") == 0)
+ {
+ addr.sa.sa_family = AF_UNSPEC;
+ L_socksize = sizeof (_SOCK_ADDR);
+ }
else
{
smi_log(SMI_LOG_ERR, "%s: unknown socket type %s",
@@ -443,7 +448,21 @@ mi_milteropen(conn, backlog, rmsocket, name)
}
#endif /* NETINET || NETINET6 */

- sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+ if (addr.sa.sa_family == AF_UNSPEC)
+ {
+ char *end;
+ sock = strtol(colon, &end, 10);
+ if (*end != '\0' || sock < 0)
+ {
+ smi_log(SMI_LOG_ERR, "%s: expected positive integer as fd, got %s", name, colon);
+ return INVALID_SOCKET;
+ }
+ }
+ else
+ {
+ sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+ }
+
if (!ValidSocket(sock))
{
smi_log(SMI_LOG_ERR,
@@ -466,6 +485,7 @@ mi_milteropen(conn, backlog, rmsocket, name)
#if NETUNIX
addr.sa.sa_family != AF_UNIX &&
#endif /* NETUNIX */
+ addr.sa.sa_family != AF_UNSPEC &&
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sockopt,
sizeof(sockopt)) == -1)
{
@@ -511,7 +531,8 @@ mi_milteropen(conn, backlog, rmsocket, name)
}
#endif /* NETUNIX */

- if (bind(sock, &addr.sa, L_socksize) < 0)
+ if (addr.sa.sa_family != AF_UNSPEC &&
+ bind(sock, &addr.sa, L_socksize) < 0)
{
smi_log(SMI_LOG_ERR,
"%s: Unable to bind to port %s: %s",
@@ -817,7 +838,7 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
# ifdef BSD4_4_SOCKADDR
cliaddr.sa.sa_len == 0 ||
# endif /* BSD4_4_SOCKADDR */
- cliaddr.sa.sa_family != L_family))
+ (L_family != AF_UNSPEC && cliaddr.sa.sa_family != L_family)))
{
(void) closesocket(connfd);
connfd = INVALID_SOCKET;
8 changes: 4 additions & 4 deletions pkgs/servers/mail/rspamd/default.nix
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{ stdenv, fetchFromGitHub, cmake, perl
, file, glib, gmime, libevent, luajit, openssl, pcre, pkgconfig, sqlite }:

let libmagic = file; # libmagic provided buy file package ATM
let libmagic = file; # libmagic provided by file package ATM
in

stdenv.mkDerivation rec {
name = "rspamd-${version}";
version = "1.2.0";
version = "1.2.5";

src = fetchFromGitHub {
owner = "vstakhov";
repo = "rspamd";
rev = version;
sha256 = "00d9c9b8w6j0ls1w08bfghn4635as779b45vhhlv1f5wfzhxz6a1";
sha256 = "0slpixcfd74qkm7445lmcry4s1yamayphzzyr7cxjlr9xfxlblqn";
};

nativeBuildInputs = [ cmake pkgconfig perl ];
Expand All @@ -32,7 +32,7 @@ stdenv.mkDerivation rec {

meta = with stdenv.lib; {
homepage = "https://github.com/vstakhov/rspamd";
license = licenses.bsd2;
license = licenses.asl20;
description = "advanced spam filtering system";
maintainers = with maintainers; [ avnik fpletz ];
};
Expand Down