1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.dspam;
8
9 dspam = pkgs.dspam;
10
11 defaultSock = "/run/dspam/dspam.sock";
12
13 cfgfile = pkgs.writeText "dspam.conf" ''
14 Home /var/lib/dspam
15 StorageDriver ${dspam}/lib/dspam/lib${cfg.storageDriver}_drv.so
16
17 Trust root
18 Trust ${cfg.user}
19 SystemLog on
20 UserLog on
21
22 ${optionalString (cfg.domainSocket != null) ''
23 ServerDomainSocketPath "${cfg.domainSocket}"
24 ClientHost "${cfg.domainSocket}"
25 ''}
26
27 ${cfg.extraConfig}
28 '';
29
30in {
31
32 ###### interface
33
34 options = {
35
36 services.dspam = {
37
38 enable = mkOption {
39 type = types.bool;
40 default = false;
41 description = lib.mdDoc "Whether to enable the dspam spam filter.";
42 };
43
44 user = mkOption {
45 type = types.str;
46 default = "dspam";
47 description = lib.mdDoc "User for the dspam daemon.";
48 };
49
50 group = mkOption {
51 type = types.str;
52 default = "dspam";
53 description = lib.mdDoc "Group for the dspam daemon.";
54 };
55
56 storageDriver = mkOption {
57 type = types.str;
58 default = "hash";
59 description = lib.mdDoc "Storage driver backend to use for dspam.";
60 };
61
62 domainSocket = mkOption {
63 type = types.nullOr types.path;
64 default = defaultSock;
65 description = lib.mdDoc "Path to local domain socket which is used for communication with the daemon. Set to null to disable UNIX socket.";
66 };
67
68 extraConfig = mkOption {
69 type = types.lines;
70 default = "";
71 description = lib.mdDoc "Additional dspam configuration.";
72 };
73
74 maintenanceInterval = mkOption {
75 type = types.nullOr types.str;
76 default = null;
77 description = lib.mdDoc "If set, maintenance script will be run at specified (in systemd.timer format) interval";
78 };
79
80 };
81
82 };
83
84
85 ###### implementation
86
87 config = mkIf cfg.enable (mkMerge [
88 {
89 users.users = optionalAttrs (cfg.user == "dspam") {
90 dspam = {
91 group = cfg.group;
92 uid = config.ids.uids.dspam;
93 };
94 };
95
96 users.groups = optionalAttrs (cfg.group == "dspam") {
97 dspam.gid = config.ids.gids.dspam;
98 };
99
100 environment.systemPackages = [ dspam ];
101
102 environment.etc."dspam/dspam.conf".source = cfgfile;
103
104 systemd.services.dspam = {
105 description = "dspam spam filtering daemon";
106 wantedBy = [ "multi-user.target" ];
107 after = [ "postgresql.service" ];
108 restartTriggers = [ cfgfile ];
109
110 serviceConfig = {
111 ExecStart = "${dspam}/bin/dspam --daemon --nofork";
112 User = cfg.user;
113 Group = cfg.group;
114 RuntimeDirectory = optional (cfg.domainSocket == defaultSock) "dspam";
115 RuntimeDirectoryMode = optional (cfg.domainSocket == defaultSock) "0750";
116 StateDirectory = "dspam";
117 StateDirectoryMode = "0750";
118 LogsDirectory = "dspam";
119 LogsDirectoryMode = "0750";
120 # DSPAM segfaults on just about every error
121 Restart = "on-abort";
122 RestartSec = "1s";
123 };
124 };
125 }
126
127 (mkIf (cfg.maintenanceInterval != null) {
128 systemd.timers.dspam-maintenance = {
129 description = "Timer for dspam maintenance script";
130 wantedBy = [ "timers.target" ];
131 timerConfig = {
132 OnCalendar = cfg.maintenanceInterval;
133 Unit = "dspam-maintenance.service";
134 };
135 };
136
137 systemd.services.dspam-maintenance = {
138 description = "dspam maintenance script";
139 restartTriggers = [ cfgfile ];
140
141 serviceConfig = {
142 ExecStart = "${dspam}/bin/dspam_maintenance --verbose";
143 Type = "oneshot";
144 User = cfg.user;
145 Group = cfg.group;
146 };
147 };
148 })
149 ]);
150}