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