at 23.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 = lib.mdDoc "Enable mlmmj"; 60 }; 61 62 user = mkOption { 63 type = types.str; 64 default = "mlmmj"; 65 description = lib.mdDoc "mailinglist local user"; 66 }; 67 68 group = mkOption { 69 type = types.str; 70 default = "mlmmj"; 71 description = lib.mdDoc "mailinglist local group"; 72 }; 73 74 listDomain = mkOption { 75 type = types.str; 76 default = "localhost"; 77 description = lib.mdDoc "Set the mailing list domain"; 78 }; 79 80 mailLists = mkOption { 81 type = types.listOf types.str; 82 default = []; 83 description = lib.mdDoc "The collection of hosted maillists"; 84 }; 85 86 maintInterval = mkOption { 87 type = types.str; 88 default = "20min"; 89 description = lib.mdDoc '' 90 Time interval between mlmmj-maintd runs, see 91 {manpage}`systemd.time(7)` for format information. 92 ''; 93 }; 94 95 }; 96 97 }; 98 99 ###### implementation 100 101 config = mkIf cfg.enable { 102 103 users.users.${cfg.user} = { 104 description = "mlmmj user"; 105 home = stateDir; 106 createHome = true; 107 uid = config.ids.uids.mlmmj; 108 group = cfg.group; 109 useDefaultShell = true; 110 }; 111 112 users.groups.${cfg.group} = { 113 gid = config.ids.gids.mlmmj; 114 }; 115 116 services.postfix = { 117 enable = true; 118 recipientDelimiter= "+"; 119 masterConfig.mlmmj = { 120 type = "unix"; 121 private = true; 122 privileged = true; 123 chroot = false; 124 wakeup = 0; 125 command = "pipe"; 126 args = [ 127 "flags=ORhu" 128 "user=mlmmj" 129 "argv=${pkgs.mlmmj}/bin/mlmmj-receive" 130 "-F" 131 "-L" 132 "${spoolDir}/$nexthop" 133 ]; 134 }; 135 136 extraAliases = concatMapLines (alias cfg.listDomain) cfg.mailLists; 137 138 extraConfig = "propagate_unmatched_extensions = virtual"; 139 140 virtual = concatMapLines (virtual cfg.listDomain) cfg.mailLists; 141 transport = concatMapLines (transport cfg.listDomain) cfg.mailLists; 142 }; 143 144 environment.systemPackages = [ pkgs.mlmmj ]; 145 146 system.activationScripts.mlmmj = '' 147 ${pkgs.coreutils}/bin/mkdir -p ${stateDir} ${spoolDir}/${cfg.listDomain} 148 ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${spoolDir} 149 ${concatMapLines (createList cfg.listDomain) cfg.mailLists} 150 ${pkgs.postfix}/bin/postmap /etc/postfix/virtual 151 ${pkgs.postfix}/bin/postmap /etc/postfix/transport 152 ''; 153 154 systemd.services.mlmmj-maintd = { 155 description = "mlmmj maintenance daemon"; 156 serviceConfig = { 157 User = cfg.user; 158 Group = cfg.group; 159 ExecStart = "${pkgs.mlmmj}/bin/mlmmj-maintd -F -d ${spoolDir}/${cfg.listDomain}"; 160 }; 161 }; 162 163 systemd.timers.mlmmj-maintd = { 164 description = "mlmmj maintenance timer"; 165 timerConfig.OnUnitActiveSec = cfg.maintInterval; 166 wantedBy = [ "timers.target" ]; 167 }; 168 }; 169 170}