grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / mail / mlmmj.nix
blobea0a7ad3144b5c92363c3e05b09c32ced7e7602e
1 { config, lib, pkgs, ... }:
2 let
4   concatMapLines = f: l: lib.concatStringsSep "\n" (map f l);
6   cfg = config.services.mlmmj;
7   stateDir = "/var/lib/mlmmj";
8   spoolDir = "/var/spool/mlmmj";
9   listDir = domain: list: "${spoolDir}/${domain}/${list}";
10   listCtl = domain: list: "${listDir domain list}/control";
11   transport = domain: list: "${domain}--${list}@local.list.mlmmj mlmmj:${domain}/${list}";
12   virtual = domain: list: "${list}@${domain} ${domain}--${list}@local.list.mlmmj";
13   alias = domain: list: "${list}: \"|${pkgs.mlmmj}/bin/mlmmj-receive -L ${listDir domain list}/\"";
14   subjectPrefix = list: "[${list}]";
15   listAddress = domain: list: "${list}@${domain}";
16   customHeaders = domain: list: [
17     "List-Id: ${list}"
18     "Reply-To: ${list}@${domain}"
19     "List-Post: <mailto:${list}@${domain}>"
20     "List-Help: <mailto:${list}+help@${domain}>"
21     "List-Subscribe: <mailto:${list}+subscribe@${domain}>"
22     "List-Unsubscribe: <mailto:${list}+unsubscribe@${domain}>"
23   ];
24   footer = domain: list: "To unsubscribe send a mail to ${list}+unsubscribe@${domain}";
25   createList = d: l:
26     let ctlDir = listCtl d l; in
27     ''
28       for DIR in incoming queue queue/discarded archive text subconf unsubconf \
29                  bounce control moderation subscribers.d digesters.d requeue \
30                  nomailsubs.d
31       do
32              mkdir -p '${listDir d l}'/"$DIR"
33       done
34       ${pkgs.coreutils}/bin/mkdir -p ${ctlDir}
35       echo ${listAddress d l} > '${ctlDir}/listaddress'
36       [ ! -e ${ctlDir}/customheaders ] && \
37           echo "${lib.concatStringsSep "\n" (customHeaders d l)}" > '${ctlDir}/customheaders'
38       [ ! -e ${ctlDir}/footer ] && \
39           echo ${footer d l} > '${ctlDir}/footer'
40       [ ! -e ${ctlDir}/prefix ] && \
41           echo ${subjectPrefix l} > '${ctlDir}/prefix'
42     '';
47   ###### interface
49   options = {
51     services.mlmmj = {
53       enable = lib.mkOption {
54         type = lib.types.bool;
55         default = false;
56         description = "Enable mlmmj";
57       };
59       user = lib.mkOption {
60         type = lib.types.str;
61         default = "mlmmj";
62         description = "mailinglist local user";
63       };
65       group = lib.mkOption {
66         type = lib.types.str;
67         default = "mlmmj";
68         description = "mailinglist local group";
69       };
71       listDomain = lib.mkOption {
72         type = lib.types.str;
73         default = "localhost";
74         description = "Set the mailing list domain";
75       };
77       mailLists = lib.mkOption {
78         type = lib.types.listOf lib.types.str;
79         default = [];
80         description = "The collection of hosted maillists";
81       };
83       maintInterval = lib.mkOption {
84         type = lib.types.str;
85         default = "20min";
86         description = ''
87           Time interval between mlmmj-maintd runs, see
88           {manpage}`systemd.time(7)` for format information.
89         '';
90       };
92     };
94   };
96   ###### implementation
98   config = lib.mkIf cfg.enable {
100     users.users.${cfg.user} = {
101       description = "mlmmj user";
102       home = stateDir;
103       createHome = true;
104       uid = config.ids.uids.mlmmj;
105       group = cfg.group;
106       useDefaultShell = true;
107     };
109     users.groups.${cfg.group} = {
110       gid = config.ids.gids.mlmmj;
111     };
113     services.postfix = {
114       enable = true;
115       recipientDelimiter= "+";
116       masterConfig.mlmmj = {
117         type = "unix";
118         private = true;
119         privileged = true;
120         chroot = false;
121         wakeup = 0;
122         command = "pipe";
123         args = [
124           "flags=ORhu"
125           "user=mlmmj"
126           "argv=${pkgs.mlmmj}/bin/mlmmj-receive"
127           "-F"
128           "-L"
129           "${spoolDir}/$nexthop"
130         ];
131       };
133       extraAliases = concatMapLines (alias cfg.listDomain) cfg.mailLists;
135       extraConfig = "propagate_unmatched_extensions = virtual";
137       virtual = concatMapLines (virtual cfg.listDomain) cfg.mailLists;
138       transport = concatMapLines (transport cfg.listDomain) cfg.mailLists;
139     };
141     environment.systemPackages = [ pkgs.mlmmj ];
143     systemd.tmpfiles.settings."10-mlmmj" = {
144       ${stateDir}.d = { };
145       "${spoolDir}/${cfg.listDomain}".d = { };
146       ${spoolDir}.Z = {
147         inherit (cfg) user group;
148       };
149     };
151     systemd.services.mlmmj-maintd = {
152       description = "mlmmj maintenance daemon";
153       serviceConfig = {
154         User = cfg.user;
155         Group = cfg.group;
156         ExecStart = "${pkgs.mlmmj}/bin/mlmmj-maintd -F -d ${spoolDir}/${cfg.listDomain}";
157       };
158       preStart = ''
159         ${concatMapLines (createList cfg.listDomain) cfg.mailLists}
160         ${pkgs.postfix}/bin/postmap /etc/postfix/virtual
161         ${pkgs.postfix}/bin/postmap /etc/postfix/transport
162       '';
163     };
165     systemd.timers.mlmmj-maintd = {
166       description = "mlmmj maintenance timer";
167       timerConfig.OnUnitActiveSec = cfg.maintInterval;
168       wantedBy = [ "timers.target" ];
169     };
170   };