Merge pull request #21586 from pngwjpgh/postgrey

Postgrey
This commit is contained in:
Joachim F 2017-01-05 07:24:47 +01:00 committed by GitHub
commit 02053c31c1
2 changed files with 141 additions and 15 deletions

View File

@ -153,6 +153,17 @@ with lib;
# alsa # alsa
(mkRenamedOptionModule [ "sound" "enableMediaKeys" ] [ "sound" "mediaKeys" "enable" ]) (mkRenamedOptionModule [ "sound" "enableMediaKeys" ] [ "sound" "mediaKeys" "enable" ])
# postgrey
(mkMergedOptionModule [ [ "services" "postgrey" "inetAddr" ] [ "services" "postgrey" "inetPort" ] ] [ "services" "postgrey" "socket" ] (config: let
value = p: getAttrFromPath p config;
inetAddr = [ "services" "postgrey" "inetAddr" ];
inetPort = [ "services" "postgrey" "inetPort" ];
in
if value inetAddr == null
then { path = "/var/run/postgrey.sock"; }
else { addr = value inetAddr; port = value inetPort; }
))
# Options that are obsolete and have no replacement. # Options that are obsolete and have no replacement.
(mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "") (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "")
(mkRemovedOptionModule [ "programs" "bash" "enable" ] "") (mkRemovedOptionModule [ "programs" "bash" "enable" ] "")

View File

@ -4,6 +4,43 @@ with lib; let
cfg = config.services.postgrey; cfg = config.services.postgrey;
natural = with types; addCheck int (x: x >= 0);
natural' = with types; addCheck int (x: x > 0);
socket = with types; addCheck (either (submodule unixSocket) (submodule inetSocket)) (x: x ? "path" || x ? "port");
inetSocket = with types; {
options = {
addr = mkOption {
type = nullOr string;
default = null;
example = "127.0.0.1";
description = "The address to bind to. Localhost if null";
};
port = mkOption {
type = natural';
default = 10030;
description = "Tcp port to bind to";
};
};
};
unixSocket = with types; {
options = {
path = mkOption {
type = path;
default = "/var/run/postgrey.sock";
description = "Path of the unix socket";
};
mode = mkOption {
type = string;
default = "0777";
description = "Mode of the unix socket";
};
};
};
in { in {
options = { options = {
@ -13,21 +50,83 @@ in {
default = false; default = false;
description = "Whether to run the Postgrey daemon"; description = "Whether to run the Postgrey daemon";
}; };
inetAddr = mkOption { socket = mkOption {
type = nullOr string; type = socket;
default = null; default = {
example = "127.0.0.1"; path = "/var/run/postgrey.sock";
description = "The inet address to bind to. If none given, bind to /var/run/postgrey.sock"; mode = "0777";
}; };
inetPort = mkOption { example = {
type = int; addr = "127.0.0.1";
default = 10030; port = 10030;
description = "The tcp port to bind to"; };
description = "Socket to bind to";
}; };
greylistText = mkOption { greylistText = mkOption {
type = string; type = string;
default = "Greylisted for %%s seconds"; default = "Greylisted for %%s seconds";
description = "Response status text for greylisted messages"; description = "Response status text for greylisted messages; use %%s for seconds left until greylisting is over and %%r for mail domain of recipient";
};
greylistAction = mkOption {
type = string;
default = "DEFER_IF_PERMIT";
description = "Response status for greylisted messages (see access(5))";
};
greylistHeader = mkOption {
type = string;
default = "X-Greylist: delayed %%t seconds by postgrey-%%v at %%h; %%d";
description = "Prepend header to greylisted mails; use %%t for seconds delayed due to greylisting, %%v for the version of postgrey, %%d for the date, and %%h for the host";
};
delay = mkOption {
type = natural;
default = 300;
description = "Greylist for N seconds";
};
maxAge = mkOption {
type = natural;
default = 35;
description = "Delete entries from whitelist if they haven't been seen for N days";
};
retryWindow = mkOption {
type = either string natural;
default = 2;
example = "12h";
description = "Allow N days for the first retry. Use string with appended 'h' to specify time in hours";
};
lookupBySubnet = mkOption {
type = bool;
default = true;
description = "Strip the last N bits from IP addresses, determined by IPv4CIDR and IPv6CIDR";
};
IPv4CIDR = mkOption {
type = natural;
default = 24;
description = "Strip N bits from IPv4 addresses if lookupBySubnet is true";
};
IPv6CIDR = mkOption {
type = natural;
default = 64;
description = "Strip N bits from IPv6 addresses if lookupBySubnet is true";
};
privacy = mkOption {
type = bool;
default = true;
description = "Store data using one-way hash functions (SHA1)";
};
autoWhitelist = mkOption {
type = nullOr natural';
default = 5;
description = "Whitelist clients after successful delivery of N messages";
};
whitelistClients = mkOption {
type = listOf path;
default = [];
description = "Client address whitelist files (see postgrey(8))";
};
whitelistRecipients = mkOption {
type = listOf path;
default = [];
description = "Recipient address whitelist files (see postgrey(8))";
}; };
}; };
}; };
@ -52,10 +151,10 @@ in {
}; };
systemd.services.postgrey = let systemd.services.postgrey = let
bind-flag = if isNull cfg.inetAddr then bind-flag = if cfg.socket ? "path" then
"--unix=/var/run/postgrey.sock" ''--unix=${cfg.socket.path} --socketmode=${cfg.socket.mode}''
else else
"--inet=${cfg.inetAddr}:${cfg.inetPort}"; ''--inet=${optionalString (cfg.socket.addr != null) (cfg.socket.addr + ":")}${toString cfg.socket.port}'';
in { in {
description = "Postfix Greylisting Service"; description = "Postfix Greylisting Service";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
@ -67,7 +166,23 @@ in {
''; '';
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "simple";
ExecStart = ''${pkgs.postgrey}/bin/postgrey ${bind-flag} --pidfile=/var/run/postgrey.pid --group=postgrey --user=postgrey --dbdir=/var/postgrey --greylist-text="${cfg.greylistText}"''; ExecStart = ''${pkgs.postgrey}/bin/postgrey \
${bind-flag} \
--group=postgrey --user=postgrey \
--dbdir=/var/postgrey \
--delay=${toString cfg.delay} \
--max-age=${toString cfg.maxAge} \
--retry-window=${toString cfg.retryWindow} \
${if cfg.lookupBySubnet then "--lookup-by-subnet" else "--lookup-by-host"} \
--ipv4cidr=${toString cfg.IPv4CIDR} --ipv6cidr=${toString cfg.IPv6CIDR} \
${optionalString cfg.privacy "--privacy"} \
--auto-whitelist-clients=${toString (if cfg.autoWhitelist == null then 0 else cfg.autoWhitelist)} \
--greylist-action=${cfg.greylistAction} \
--greylist-text="${cfg.greylistText}" \
--x-greylist-header="${cfg.greylistHeader}" \
${concatMapStringsSep " " (x: "--whitelist-clients=" + x) cfg.whitelistClients} \
${concatMapStringsSep " " (x: "--whitelist-recipients=" + x) cfg.whitelistRecipients}
'';
Restart = "always"; Restart = "always";
RestartSec = 5; RestartSec = 5;
TimeoutSec = 10; TimeoutSec = 10;