Self-host your own digital island
1# nixos-mailserver: a simple mail server
2# Copyright (C) 2016-2018 Robin Raymond
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>
16
17{ config, pkgs, lib, ... }:
18
19let
20 cfg = config.mailserver;
21
22 postfixCfg = config.services.postfix;
23 rspamdCfg = config.services.rspamd;
24 rspamdSocket = "rspamd.service";
25in
26{
27 config = with cfg; lib.mkIf enable {
28 services.rspamd = {
29 enable = true;
30 inherit debug;
31 locals = {
32 "milter_headers.conf" = { text = ''
33 extended_spam_headers = yes;
34 ''; };
35 "redis.conf" = { text = ''
36 servers = "${cfg.redis.address}:${toString cfg.redis.port}";
37 '' + (lib.optionalString (cfg.redis.password != null) ''
38 password = "${cfg.redis.password}";
39 ''); };
40 "classifier-bayes.conf" = { text = ''
41 cache {
42 backend = "redis";
43 }
44 ''; };
45 "antivirus.conf" = lib.mkIf cfg.virusScanning { text = ''
46 clamav {
47 action = "reject";
48 symbol = "CLAM_VIRUS";
49 type = "clamav";
50 log_clean = true;
51 servers = "/run/clamav/clamd.ctl";
52 scan_mime_parts = false; # scan mail as a whole unit, not parts. seems to be needed to work at all
53 }
54 ''; };
55 "dkim_signing.conf" = { text = ''
56 # Disable outbound email signing, we use opendkim for this
57 enabled = false;
58 ''; };
59 };
60
61 overrides = {
62 "milter_headers.conf" = {
63 text = ''
64 extended_spam_headers = true;
65 '';
66 };
67 };
68
69 workers.rspamd_proxy = {
70 type = "rspamd_proxy";
71 bindSockets = [{
72 socket = "/run/rspamd/rspamd-milter.sock";
73 mode = "0664";
74 }];
75 count = 1; # Do not spawn too many processes of this type
76 extraConfig = ''
77 milter = yes; # Enable milter mode
78 timeout = 120s; # Needed for Milter usually
79
80 upstream "local" {
81 default = yes; # Self-scan upstreams are always default
82 self_scan = yes; # Enable self-scan
83 }
84 '';
85 };
86 workers.controller = {
87 type = "controller";
88 count = 1;
89 bindSockets = [{
90 socket = "/run/rspamd/worker-controller.sock";
91 mode = "0666";
92 }];
93 includes = [];
94 extraConfig = ''
95 static_dir = "''${WWWDIR}"; # Serve the web UI static assets
96 '';
97 };
98
99 };
100
101 services.redis.servers.rspamd = {
102 enable = lib.mkDefault true;
103 port = lib.mkDefault 6380;
104 };
105
106 systemd.services.rspamd = {
107 requires = [ "redis-rspamd.service" ] ++ (lib.optional cfg.virusScanning "clamav-daemon.service");
108 after = [ "redis-rspamd.service" ] ++ (lib.optional cfg.virusScanning "clamav-daemon.service");
109 };
110
111 systemd.services.postfix = {
112 after = [ rspamdSocket ];
113 requires = [ rspamdSocket ];
114 };
115
116 users.extraUsers.${postfixCfg.user}.extraGroups = [ rspamdCfg.group ];
117 };
118}
119