1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.opensmtpd;
8 conf = pkgs.writeText "smtpd.conf" cfg.serverConfiguration;
9 args = concatStringsSep " " cfg.extraServerArgs;
10
11 sendmail = pkgs.runCommand "opensmtpd-sendmail" { preferLocalBuild = true; } ''
12 mkdir -p $out/bin
13 ln -s ${cfg.package}/sbin/smtpctl $out/bin/sendmail
14 '';
15
16in {
17
18 ###### interface
19
20 imports = [
21 (mkRenamedOptionModule [ "services" "opensmtpd" "addSendmailToSystemPath" ] [ "services" "opensmtpd" "setSendmail" ])
22 ];
23
24 options = {
25
26 services.opensmtpd = {
27
28 enable = mkOption {
29 type = types.bool;
30 default = false;
31 description = lib.mdDoc "Whether to enable the OpenSMTPD server.";
32 };
33
34 package = mkOption {
35 type = types.package;
36 default = pkgs.opensmtpd;
37 defaultText = literalExpression "pkgs.opensmtpd";
38 description = lib.mdDoc "The OpenSMTPD package to use.";
39 };
40
41 setSendmail = mkOption {
42 type = types.bool;
43 default = true;
44 description = lib.mdDoc "Whether to set the system sendmail to OpenSMTPD's.";
45 };
46
47 extraServerArgs = mkOption {
48 type = types.listOf types.str;
49 default = [];
50 example = [ "-v" "-P mta" ];
51 description = lib.mdDoc ''
52 Extra command line arguments provided when the smtpd process
53 is started.
54 '';
55 };
56
57 serverConfiguration = mkOption {
58 type = types.lines;
59 example = ''
60 listen on lo
61 accept for any deliver to lmtp localhost:24
62 '';
63 description = lib.mdDoc ''
64 The contents of the smtpd.conf configuration file. See the
65 OpenSMTPD documentation for syntax information.
66 '';
67 };
68
69 procPackages = mkOption {
70 type = types.listOf types.package;
71 default = [];
72 description = lib.mdDoc ''
73 Packages to search for filters, tables, queues, and schedulers.
74
75 Add OpenSMTPD-extras here if you want to use the filters, etc. from
76 that package.
77 '';
78 };
79 };
80
81 };
82
83
84 ###### implementation
85
86 config = mkIf cfg.enable rec {
87 users.groups = {
88 smtpd.gid = config.ids.gids.smtpd;
89 smtpq.gid = config.ids.gids.smtpq;
90 };
91
92 users.users = {
93 smtpd = {
94 description = "OpenSMTPD process user";
95 uid = config.ids.uids.smtpd;
96 group = "smtpd";
97 };
98 smtpq = {
99 description = "OpenSMTPD queue user";
100 uid = config.ids.uids.smtpq;
101 group = "smtpq";
102 };
103 };
104
105 security.wrappers.smtpctl = {
106 owner = "root";
107 group = "smtpq";
108 setuid = false;
109 setgid = true;
110 source = "${cfg.package}/bin/smtpctl";
111 };
112
113 services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail
114 (security.wrappers.smtpctl // { program = "sendmail"; });
115
116 systemd.tmpfiles.rules = [
117 "d /var/spool/smtpd 711 root - - -"
118 "d /var/spool/smtpd/offline 770 root smtpq - -"
119 "d /var/spool/smtpd/purge 700 smtpq root - -"
120 ];
121
122 systemd.services.opensmtpd = let
123 procEnv = pkgs.buildEnv {
124 name = "opensmtpd-procs";
125 paths = [ cfg.package ] ++ cfg.procPackages;
126 pathsToLink = [ "/libexec/opensmtpd" ];
127 };
128 in {
129 wantedBy = [ "multi-user.target" ];
130 after = [ "network.target" ];
131 serviceConfig.ExecStart = "${cfg.package}/sbin/smtpd -d -f ${conf} ${args}";
132 environment.OPENSMTPD_PROC_PATH = "${procEnv}/libexec/opensmtpd";
133 };
134 };
135}