ocamlPackages.hxd: 0.3.2 -> 0.3.3 (#364231)
[NixPkgs.git] / nixos / modules / services / mail / postgrey.nix
blob7ce9d40a912af5654988a625c90171d002399660
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
8 with lib;
9 let
11   cfg = config.services.postgrey;
13   natural = with types; addCheck int (x: x >= 0);
14   natural' = with types; addCheck int (x: x > 0);
16   socket =
17     with types;
18     addCheck (either (submodule unixSocket) (submodule inetSocket)) (x: x ? path || x ? port);
20   inetSocket = with types; {
21     options = {
22       addr = mkOption {
23         type = nullOr str;
24         default = null;
25         example = "127.0.0.1";
26         description = "The address to bind to. Localhost if null";
27       };
28       port = mkOption {
29         type = natural';
30         default = 10030;
31         description = "Tcp port to bind to";
32       };
33     };
34   };
36   unixSocket = with types; {
37     options = {
38       path = mkOption {
39         type = path;
40         default = "/run/postgrey.sock";
41         description = "Path of the unix socket";
42       };
44       mode = mkOption {
45         type = str;
46         default = "0777";
47         description = "Mode of the unix socket";
48       };
49     };
50   };
54   imports = [
55     (mkMergedOptionModule
56       [
57         [
58           "services"
59           "postgrey"
60           "inetAddr"
61         ]
62         [
63           "services"
64           "postgrey"
65           "inetPort"
66         ]
67       ]
68       [ "services" "postgrey" "socket" ]
69       (
70         config:
71         let
72           value = p: getAttrFromPath p config;
73           inetAddr = [
74             "services"
75             "postgrey"
76             "inetAddr"
77           ];
78           inetPort = [
79             "services"
80             "postgrey"
81             "inetPort"
82           ];
83         in
84         if value inetAddr == null then
85           { path = "/run/postgrey.sock"; }
86         else
87           {
88             addr = value inetAddr;
89             port = value inetPort;
90           }
91       )
92     )
93   ];
95   options = {
96     services.postgrey = with types; {
97       enable = mkOption {
98         type = bool;
99         default = false;
100         description = "Whether to run the Postgrey daemon";
101       };
102       socket = mkOption {
103         type = socket;
104         default = {
105           path = "/run/postgrey.sock";
106           mode = "0777";
107         };
108         example = {
109           addr = "127.0.0.1";
110           port = 10030;
111         };
112         description = "Socket to bind to";
113       };
114       greylistText = mkOption {
115         type = str;
116         default = "Greylisted for %%s seconds";
117         description = "Response status text for greylisted messages; use %%s for seconds left until greylisting is over and %%r for mail domain of recipient";
118       };
119       greylistAction = mkOption {
120         type = str;
121         default = "DEFER_IF_PERMIT";
122         description = "Response status for greylisted messages (see access(5))";
123       };
124       greylistHeader = mkOption {
125         type = str;
126         default = "X-Greylist: delayed %%t seconds by postgrey-%%v at %%h; %%d";
127         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";
128       };
129       delay = mkOption {
130         type = natural;
131         default = 300;
132         description = "Greylist for N seconds";
133       };
134       maxAge = mkOption {
135         type = natural;
136         default = 35;
137         description = "Delete entries from whitelist if they haven't been seen for N days";
138       };
139       retryWindow = mkOption {
140         type = either str natural;
141         default = 2;
142         example = "12h";
143         description = "Allow N days for the first retry. Use string with appended 'h' to specify time in hours";
144       };
145       lookupBySubnet = mkOption {
146         type = bool;
147         default = true;
148         description = "Strip the last N bits from IP addresses, determined by IPv4CIDR and IPv6CIDR";
149       };
150       IPv4CIDR = mkOption {
151         type = natural;
152         default = 24;
153         description = "Strip N bits from IPv4 addresses if lookupBySubnet is true";
154       };
155       IPv6CIDR = mkOption {
156         type = natural;
157         default = 64;
158         description = "Strip N bits from IPv6 addresses if lookupBySubnet is true";
159       };
160       privacy = mkOption {
161         type = bool;
162         default = true;
163         description = "Store data using one-way hash functions (SHA1)";
164       };
165       autoWhitelist = mkOption {
166         type = nullOr natural';
167         default = 5;
168         description = "Whitelist clients after successful delivery of N messages";
169       };
170       whitelistClients = mkOption {
171         type = listOf path;
172         default = [ ];
173         description = "Client address whitelist files (see postgrey(8))";
174       };
175       whitelistRecipients = mkOption {
176         type = listOf path;
177         default = [ ];
178         description = "Recipient address whitelist files (see postgrey(8))";
179       };
180     };
181   };
183   config = mkIf cfg.enable {
185     environment.systemPackages = [ pkgs.postgrey ];
187     users = {
188       users = {
189         postgrey = {
190           description = "Postgrey Daemon";
191           uid = config.ids.uids.postgrey;
192           group = "postgrey";
193         };
194       };
195       groups = {
196         postgrey = {
197           gid = config.ids.gids.postgrey;
198         };
199       };
200     };
202     systemd.services.postgrey =
203       let
204         bind-flag =
205           if cfg.socket ? path then
206             "--unix=${cfg.socket.path} --socketmode=${cfg.socket.mode}"
207           else
208             ''--inet=${
209               optionalString (cfg.socket.addr != null) (cfg.socket.addr + ":")
210             }${toString cfg.socket.port}'';
211       in
212       {
213         description = "Postfix Greylisting Service";
214         wantedBy = [ "multi-user.target" ];
215         before = [ "postfix.service" ];
216         preStart = ''
217           mkdir -p /var/postgrey
218           chown postgrey:postgrey /var/postgrey
219           chmod 0770 /var/postgrey
220         '';
221         serviceConfig = {
222           Type = "simple";
223           ExecStart = ''
224             ${pkgs.postgrey}/bin/postgrey \
225                       ${bind-flag} \
226                       --group=postgrey --user=postgrey \
227                       --dbdir=/var/postgrey \
228                       --delay=${toString cfg.delay} \
229                       --max-age=${toString cfg.maxAge} \
230                       --retry-window=${toString cfg.retryWindow} \
231                       ${if cfg.lookupBySubnet then "--lookup-by-subnet" else "--lookup-by-host"} \
232                       --ipv4cidr=${toString cfg.IPv4CIDR} --ipv6cidr=${toString cfg.IPv6CIDR} \
233                       ${optionalString cfg.privacy "--privacy"} \
234                       --auto-whitelist-clients=${
235                         toString (if cfg.autoWhitelist == null then 0 else cfg.autoWhitelist)
236                       } \
237                       --greylist-action=${cfg.greylistAction} \
238                       --greylist-text="${cfg.greylistText}" \
239                       --x-greylist-header="${cfg.greylistHeader}" \
240                       ${concatMapStringsSep " " (x: "--whitelist-clients=" + x) cfg.whitelistClients} \
241                       ${concatMapStringsSep " " (x: "--whitelist-recipients=" + x) cfg.whitelistRecipients}
242           '';
243           Restart = "always";
244           RestartSec = 5;
245           TimeoutSec = 10;
246         };
247       };
249   };