2015-11-17 17:30:10 +00:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
with lib; let
|
|
|
|
|
|
|
|
cfg = config.services.postgrey;
|
|
|
|
|
2017-01-02 14:09:50 +00:00
|
|
|
natural = with types; addCheck int (x: x >= 0);
|
|
|
|
natural' = with types; addCheck int (x: x > 0);
|
|
|
|
|
2019-08-13 21:52:01 +00:00
|
|
|
socket = with types; addCheck (either (submodule unixSocket) (submodule inetSocket)) (x: x ? path || x ? port);
|
2017-01-02 14:09:50 +00:00
|
|
|
|
|
|
|
inetSocket = with types; {
|
2017-01-02 14:19:00 +00:00
|
|
|
options = {
|
|
|
|
addr = mkOption {
|
2019-08-08 20:48:27 +00:00
|
|
|
type = nullOr str;
|
2017-01-02 14:19:00 +00:00
|
|
|
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";
|
|
|
|
};
|
2017-01-02 14:09:50 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
unixSocket = with types; {
|
2017-01-02 14:19:00 +00:00
|
|
|
options = {
|
|
|
|
path = mkOption {
|
|
|
|
type = path;
|
2018-12-19 21:37:15 +00:00
|
|
|
default = "/run/postgrey.sock";
|
2017-01-02 14:19:00 +00:00
|
|
|
description = "Path of the unix socket";
|
|
|
|
};
|
2017-01-02 14:09:50 +00:00
|
|
|
|
2017-01-02 14:19:00 +00:00
|
|
|
mode = mkOption {
|
2019-08-08 20:48:27 +00:00
|
|
|
type = str;
|
2017-01-02 14:19:00 +00:00
|
|
|
default = "0777";
|
|
|
|
description = "Mode of the unix socket";
|
|
|
|
};
|
2017-01-02 14:09:50 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-11-17 17:30:10 +00:00
|
|
|
in {
|
2019-12-10 01:51:19 +00:00
|
|
|
imports = [
|
|
|
|
(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 = "/run/postgrey.sock"; }
|
|
|
|
else { addr = value inetAddr; port = value inetPort; }
|
|
|
|
))
|
|
|
|
];
|
2015-11-17 17:30:10 +00:00
|
|
|
|
|
|
|
options = {
|
2016-09-14 00:18:18 +00:00
|
|
|
services.postgrey = with types; {
|
2015-11-17 17:30:10 +00:00
|
|
|
enable = mkOption {
|
2016-09-14 00:18:18 +00:00
|
|
|
type = bool;
|
2015-11-17 17:30:10 +00:00
|
|
|
default = false;
|
|
|
|
description = "Whether to run the Postgrey daemon";
|
|
|
|
};
|
2017-01-02 14:09:50 +00:00
|
|
|
socket = mkOption {
|
|
|
|
type = socket;
|
2017-01-02 14:32:50 +00:00
|
|
|
default = {
|
2018-12-19 21:37:15 +00:00
|
|
|
path = "/run/postgrey.sock";
|
2017-01-02 14:32:50 +00:00
|
|
|
mode = "0777";
|
|
|
|
};
|
2017-01-02 14:09:50 +00:00
|
|
|
example = {
|
|
|
|
addr = "127.0.0.1";
|
|
|
|
port = 10030;
|
|
|
|
};
|
|
|
|
description = "Socket to bind to";
|
2015-11-17 17:30:10 +00:00
|
|
|
};
|
|
|
|
greylistText = mkOption {
|
2019-08-08 20:48:27 +00:00
|
|
|
type = str;
|
2015-11-17 17:30:10 +00:00
|
|
|
default = "Greylisted for %%s seconds";
|
2017-01-02 14:09:50 +00:00
|
|
|
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 {
|
2019-08-08 20:48:27 +00:00
|
|
|
type = str;
|
2017-01-02 14:09:50 +00:00
|
|
|
default = "DEFER_IF_PERMIT";
|
|
|
|
description = "Response status for greylisted messages (see access(5))";
|
|
|
|
};
|
|
|
|
greylistHeader = mkOption {
|
2019-08-08 20:48:27 +00:00
|
|
|
type = str;
|
2017-01-02 14:09:50 +00:00
|
|
|
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 {
|
2019-08-08 20:48:27 +00:00
|
|
|
type = either str natural;
|
2017-01-02 14:09:50 +00:00
|
|
|
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;
|
2017-01-02 14:12:39 +00:00
|
|
|
description = "Strip N bits from IPv4 addresses if lookupBySubnet is true";
|
2017-01-02 14:09:50 +00:00
|
|
|
};
|
|
|
|
IPv6CIDR = mkOption {
|
|
|
|
type = natural;
|
|
|
|
default = 64;
|
2017-01-02 14:12:39 +00:00
|
|
|
description = "Strip N bits from IPv6 addresses if lookupBySubnet is true";
|
2017-01-02 14:09:50 +00:00
|
|
|
};
|
|
|
|
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";
|
2015-11-17 17:30:10 +00:00
|
|
|
};
|
2017-01-02 14:40:54 +00:00
|
|
|
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))";
|
|
|
|
};
|
2015-11-17 17:30:10 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
|
|
|
|
environment.systemPackages = [ pkgs.postgrey ];
|
|
|
|
|
|
|
|
users = {
|
2018-06-29 23:58:35 +00:00
|
|
|
users = {
|
2015-11-17 17:30:10 +00:00
|
|
|
postgrey = {
|
|
|
|
description = "Postgrey Daemon";
|
|
|
|
uid = config.ids.uids.postgrey;
|
|
|
|
group = "postgrey";
|
|
|
|
};
|
|
|
|
};
|
2018-06-29 23:58:35 +00:00
|
|
|
groups = {
|
2015-11-17 17:30:10 +00:00
|
|
|
postgrey = {
|
|
|
|
gid = config.ids.gids.postgrey;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
systemd.services.postgrey = let
|
2019-08-13 21:52:01 +00:00
|
|
|
bind-flag = if cfg.socket ? path then
|
2017-01-02 14:09:50 +00:00
|
|
|
''--unix=${cfg.socket.path} --socketmode=${cfg.socket.mode}''
|
2015-11-17 17:30:10 +00:00
|
|
|
else
|
2017-01-02 14:27:00 +00:00
|
|
|
''--inet=${optionalString (cfg.socket.addr != null) (cfg.socket.addr + ":")}${toString cfg.socket.port}'';
|
2015-11-17 17:30:10 +00:00
|
|
|
in {
|
|
|
|
description = "Postfix Greylisting Service";
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
before = [ "postfix.service" ];
|
|
|
|
preStart = ''
|
|
|
|
mkdir -p /var/postgrey
|
|
|
|
chown postgrey:postgrey /var/postgrey
|
|
|
|
chmod 0770 /var/postgrey
|
|
|
|
'';
|
|
|
|
serviceConfig = {
|
|
|
|
Type = "simple";
|
2017-01-02 14:42:51 +00:00
|
|
|
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}
|
|
|
|
'';
|
2015-11-17 17:30:10 +00:00
|
|
|
Restart = "always";
|
|
|
|
RestartSec = 5;
|
|
|
|
TimeoutSec = 10;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|