This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / 2configs / mailserver.nix
8.1 kB 276 lines
1{ 2 self, 3 config, 4 lib, 5 pkgs, 6 ... 7}: 8let 9 relayHosts = map (host: host.nets.retiolum.ip6.addr) [ 10 config.krebs.hosts.aergia 11 config.krebs.hosts.ignavia 12 config.krebs.hosts.coaxmetal 13 config.krebs.hosts.green 14 config.krebs.hosts.mors 15 ]; 16 17 mynetworks = map (ip: "[${ip}]") relayHosts; 18in 19{ 20 imports = [ 21 self.inputs.nixos-mailserver.nixosModules.default 22 ]; 23 24 mailserver = { 25 enable = true; 26 fqdn = "mail.lassul.us"; 27 domains = [ "lassul.us" ]; 28 29 loginAccounts = { 30 "lass@lassul.us" = { 31 hashedPasswordFile = 32 config.clan.core.vars.generators.mailserver-lass.files."lass-mail-password-hash".path; 33 aliases = [ 34 "postmaster@lassul.us" 35 "root@lassul.us" 36 "abuse@lassul.us" 37 "hostmaster@lassul.us" 38 "webmaster@lassul.us" 39 "security@lassul.us" 40 "noc@lassul.us" 41 "mailer-daemon@lassul.us" 42 "nobody@lassul.us" 43 "lassulus@lassul.us" 44 ]; 45 catchAll = [ "lassul.us" ]; 46 }; 47 "bot@lassul.us" = { 48 hashedPasswordFile = 49 config.clan.core.vars.generators.mailserver-bot.files."bot-mail-password-hash".path; 50 }; 51 }; 52 53 # TLS via existing ACME cert 54 x509.useACMEHost = "mail.lassul.us"; 55 56 # DKIM — auto-managed by module 57 dkimSigning = true; 58 dkimSelector = "mail"; 59 60 # ManageSieve: lets mail clients manage sieve rules dynamically (port 4190) 61 enableManageSieve = true; 62 63 # Full-text search for IMAP clients 64 fullTextSearch = { 65 enable = true; 66 memoryLimit = 500; 67 }; 68 69 stateVersion = 3; 70 }; 71 72 # nixos-mailserver mkForces virtualMail without homeMode; match its priority 73 users.users.virtualMail = lib.mkOverride 50 { homeMode = "2770"; }; 74 75 # POSIX ACL default ensures new files inherit lass access (needed for muchsync hardlinks) 76 systemd.services.dovecot.serviceConfig.ExecStartPost = [ 77 "+${pkgs.acl}/bin/setfacl -R -m u:lass:rwX /var/vmail/lassul.us/lass/mail" 78 "+${pkgs.acl}/bin/setfacl -R -d -m u:lass:rwX /var/vmail/lassul.us/lass/mail" 79 ]; 80 81 # Password generation for mail accounts 82 clan.core.vars.generators.mailserver-lass = { 83 files."lass-mail-password" = { }; 84 files."lass-mail-password-hash" = { }; 85 runtimeInputs = with pkgs; [ 86 coreutils 87 mkpasswd 88 pwgen 89 ]; 90 script = '' 91 pwgen -s 32 1 > "$out/lass-mail-password" 92 mkpasswd -sm bcrypt < "$out/lass-mail-password" > "$out/lass-mail-password-hash" 93 ''; 94 }; 95 96 clan.core.vars.generators.mailserver-bot = { 97 files."bot-mail-password" = { }; 98 files."bot-mail-password-hash" = { }; 99 files."mail.env" = { }; 100 runtimeInputs = with pkgs; [ 101 coreutils 102 mkpasswd 103 pwgen 104 ]; 105 script = '' 106 pwgen -s 32 1 > "$out/bot-mail-password" 107 mkpasswd -sm bcrypt < "$out/bot-mail-password" > "$out/bot-mail-password-hash" 108 cat > "$out/mail.env" << EOF 109 IMAP_USER=bot@lassul.us 110 IMAP_PASSWORD=$(cat "$out/bot-mail-password") 111 IMAP_HOST=localhost 112 EOF 113 ''; 114 }; 115 116 # Retiolum relay: allow krebs hosts to relay through postfix 117 services.postfix.settings.main.mynetworks = lib.mkForce ( 118 [ 119 "127.0.0.0/8" 120 "[::1]/128" 121 ] 122 ++ mynetworks 123 ); 124 125 # ACME cert — reuse existing setup 126 security.acme.certs."mail.lassul.us" = { 127 group = "lasscert"; 128 webroot = "/var/lib/acme/acme-challenge"; 129 }; 130 users.groups.lasscert.members = [ 131 "dovecot2" 132 "postfix" 133 "nginx" 134 ]; 135 136 # Firewall: SMTP(25), submission(587), submissions(465), IMAPS(993), ManageSieve(4190) 137 networking.firewall.allowedTCPPorts = [ 138 25 139 587 140 465 141 993 142 4190 143 ]; 144 145 # muchsync: lass user needs access to vmail for notmuch/muchsync 146 users.groups.virtualMail.members = [ "lass" ]; 147 systemd.tmpfiles.rules = [ 148 "L+ /home/lass/Maildir - - - - /var/vmail/lassul.us/lass/mail" 149 "z /var/vmail/lassul.us 2770 virtualMail virtualMail -" 150 "z /var/vmail/lassul.us/lass 2770 virtualMail virtualMail -" 151 "d /var/vmail/lassul.us/lass/mail 2770 virtualMail virtualMail -" 152 ]; 153 154 # Thunderbird autoconfig 155 services.nginx.virtualHosts."autoconfig.lassul.us" = { 156 forceSSL = true; 157 enableACME = true; 158 locations."= /mail/config-v1.1.xml".extraConfig = '' 159 default_type application/xml; 160 return 200 '<?xml version="1.0" encoding="UTF-8"?> 161 <clientConfig version="1.1"> 162 <emailProvider id="lassul.us"> 163 <domain>lassul.us</domain> 164 <displayName>lassul.us Mail</displayName> 165 <displayShortName>lassul.us</displayShortName> 166 <incomingServer type="imap"> 167 <hostname>mail.lassul.us</hostname> 168 <port>993</port> 169 <socketType>SSL</socketType> 170 <authentication>password-cleartext</authentication> 171 <username>%EMAILADDRESS%</username> 172 </incomingServer> 173 <outgoingServer type="smtp"> 174 <hostname>mail.lassul.us</hostname> 175 <port>465</port> 176 <socketType>SSL</socketType> 177 <authentication>password-cleartext</authentication> 178 <username>%EMAILADDRESS%</username> 179 </outgoingServer> 180 </emailProvider> 181 </clientConfig>'; 182 ''; 183 }; 184 185 # Dovecot virtual mailbox + ACL-restricted shared namespace for bot 186 services.dovecot2.mailPlugins.globally.enable = [ 187 "virtual" 188 "acl" 189 ]; 190 # Provision virtual mailbox config to a writable directory (nix store is read-only, 191 # and the ACL plugin needs to write dovecot-acl-list next to the virtual config) 192 systemd.tmpfiles.settings."dovecot-virtual" = { 193 "/var/vmail/virtual-config".d = { 194 user = "virtualMail"; 195 group = "virtualMail"; 196 mode = "0750"; 197 }; 198 "/var/vmail/virtual-config/Unread".d = { 199 user = "virtualMail"; 200 group = "virtualMail"; 201 mode = "0750"; 202 }; 203 "/var/vmail/virtual-config/Unread/dovecot-virtual".f = { 204 user = "virtualMail"; 205 group = "virtualMail"; 206 mode = "0640"; 207 argument = "*\n-notmuch\n-fts-flatcurve\n unseen\n"; 208 }; 209 }; 210 211 services.dovecot2.extraConfig = '' 212 plugin { 213 acl = vfile 214 acl_shared_dict = file:/var/vmail/shared-mailboxes.db 215 } 216 217 namespace shared { 218 type = shared 219 separator = . 220 prefix = shared.%%n. 221 location = maildir:/var/vmail/lassul.us/%%n/mail:LAYOUT=Maildir++ 222 subscriptions = no 223 list = children 224 } 225 226 namespace virtual { 227 prefix = virtual. 228 separator = . 229 location = virtual:/var/vmail/virtual-config:INDEX=/var/vmail/virtual-indexes/%u 230 subscriptions = no 231 mailbox Unread { 232 auto = subscribe 233 } 234 } 235 ''; 236 237 # Write dovecot-acl files to grant bot read-only + flag access to lass's mail 238 systemd.services.dovecot-acl-sync = { 239 description = "Sync dovecot ACL files for bot shared access"; 240 after = [ "dovecot.service" ]; 241 serviceConfig = { 242 Type = "oneshot"; 243 User = "virtualMail"; 244 Group = "virtualMail"; 245 }; 246 # l=lookup, r=read, w=write-flags, s=write-seen (no insert/delete/expunge) 247 script = '' 248 acl_line="user=bot@lassul.us lrws" 249 # Only write ACL in mailbox root dirs, skip cur/new/tmp/notmuch subdirs 250 find /var/vmail/lassul.us/lass/mail -type d \ 251 -not -name cur -not -name new -not -name tmp \ 252 -not -path '*/.notmuch/*' -not -name .notmuch \ 253 -not -path '*/fts-flatcurve/*' -not -name fts-flatcurve \ 254 | while IFS= read -r dir; do 255 acl_file="$dir/dovecot-acl" 256 if [ ! -f "$acl_file" ] || [ "$(cat "$acl_file")" != "$acl_line" ]; then 257 echo "$acl_line" > "$acl_file" 258 fi 259 done 260 ''; 261 }; 262 systemd.timers.dovecot-acl-sync = { 263 wantedBy = [ "timers.target" ]; 264 timerConfig = { 265 OnBootSec = "1min"; 266 OnUnitActiveSec = "1h"; 267 }; 268 }; 269 270 # notmuch + muchsync + msmtp for CLI mail access 271 environment.systemPackages = [ 272 self.packages.${pkgs.system}.notmuch 273 pkgs.muchsync 274 pkgs.msmtp 275 ]; 276}