nixpkgs/nixos/modules/services/mail/postgrey.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

252 lines
7.0 KiB
Nix
Raw Normal View History

{
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 {
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";
2017-01-02 14:19:00 +00:00
};
port = mkOption {
type = natural';
default = 10030;
description = "Tcp port to bind to";
2017-01-02 14:19:00 +00:00
};
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";
description = "Path of the unix socket";
2017-01-02 14:19:00 +00:00
};
2017-01-02 14:09:50 +00:00
2017-01-02 14:19:00 +00:00
mode = mkOption {
type = str;
2017-01-02 14:19:00 +00:00
default = "0777";
description = "Mode of the unix socket";
2017-01-02 14:19:00 +00:00
};
2017-01-02 14:09:50 +00:00
};
};
in
{
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;
}
)
)
];
options = {
2016-09-14 00:18:18 +00:00
services.postgrey = with types; {
enable = mkOption {
2016-09-14 00:18:18 +00:00
type = bool;
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";
};
greylistText = mkOption {
type = str;
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 {
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 {
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 {
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";
};
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))";
};
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.postgrey ];
users = {
users = {
postgrey = {
description = "Postgrey Daemon";
uid = config.ids.uids.postgrey;
group = "postgrey";
};
};
groups = {
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
"--unix=${cfg.socket.path} --socketmode=${cfg.socket.mode}"
else
2017-01-02 14:27:00 +00:00
''--inet=${
optionalString (cfg.socket.addr != null) (cfg.socket.addr + ":")
}${toString cfg.socket.port}'';
in
{
description = "Postfix Greylisting Service";
wantedBy = [ "multi-user.target" ];
before = [ "postfix.service" ];
2017-01-02 14:42:51 +00:00
preStart = ''
mkdir -p /var/postgrey
chown postgrey:postgrey /var/postgrey
chmod 0770 /var/postgrey
'';
serviceConfig = {
Type = "simple";
ExecStart = ''
2017-01-02 14:42:51 +00:00
${pkgs.postgrey}/bin/postgrey \
${bind-flag} \
--group=postgrey --user=postgrey \
--dbdir=/var/postgrey \
2017-01-02 14:42:51 +00:00
--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)
} \
2017-01-02 14:42:51 +00:00
--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";
RestartSec = 5;
TimeoutSec = 10;
};
};
};
}