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