This repository has no description
0

Configure Feed

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

superconfig / 2configs / mailserver.nix
6.7 kB 211 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 sieveScript = '' 47 require ["fileinto", "mailbox"]; 48 49 # GitHub — sort by repo from List-Id header 50 if header :matches "List-Id" "*.github.com" { 51 if header :contains "List-Id" "nixpkgs" { fileinto :create "GitHub.nixpkgs"; } 52 elsif header :contains "List-Id" "disko" { fileinto :create "GitHub.disko"; } 53 elsif header :contains "List-Id" "clan-core" { fileinto :create "GitHub.clan-core"; } 54 elsif header :contains "List-Id" "data-mesher" { fileinto :create "GitHub.data-mesher"; } 55 elsif header :contains "List-Id" "foundation" { fileinto :create "GitHub.foundation"; } 56 elsif header :contains "List-Id" "nix." { fileinto :create "GitHub.nix"; } 57 elsif header :contains "List-Id" "nixos-wiki" { fileinto :create "GitHub.nixos-wiki"; } 58 elsif header :contains "List-Id" "nixos-homepage" { fileinto :create "GitHub.nixos-homepage"; } 59 else { fileinto :create "GitHub.other"; } 60 stop; 61 } 62 63 # Gitea (clan) 64 if anyof ( 65 header :matches "X-Gitea-*" "*", 66 address :domain "From" "clan.lol" 67 ) { 68 fileinto :create "GitHub.clan"; 69 stop; 70 } 71 72 # Mailing lists — sort by List-Id 73 if exists "List-Id" { 74 if header :contains "List-Id" "vorstand.c-base" { fileinto :create "Lists.c-base-vorstand"; } 75 elsif header :contains "List-Id" "c-base" { fileinto :create "Lists.c-base"; } 76 elsif header :contains "List-Id" "afra" { fileinto :create "Lists.afra"; } 77 elsif header :contains "List-Id" "soundlab" { fileinto :create "Lists.soundlab"; } 78 elsif header :contains "List-Id" "nixos" { fileinto :create "Lists.nixos"; } 79 elsif header :contains "List-Id" "shack" { fileinto :create "Lists.shack"; } 80 elsif header :contains "List-Id" "dezentrale" { fileinto :create "Lists.dezentrale"; } 81 elsif header :contains "List-Id" "dn42" { fileinto :create "Lists.dn42"; } 82 elsif header :contains "List-Id" "tinc" { fileinto :create "Lists.tinc"; } 83 elsif header :contains "List-Id" "wireguard" { fileinto :create "Lists.wireguard"; } 84 elsif header :contains "List-Id" "retiolum" { fileinto :create "Lists.retiolum"; } 85 else { fileinto :create "Lists.other"; } 86 stop; 87 } 88 89 # Billing/receipts 90 if anyof ( 91 address :domain "From" "paypal.de", 92 address :domain "From" "paypal.com", 93 address :domain "From" "steuerberaten.de", 94 address :domain "From" "patreon.com", 95 address :domain "From" "dhl.de", 96 address :domain "From" "eloop.app", 97 header :contains "Subject" "Rechnung", 98 header :contains "Subject" "Invoice", 99 header :contains "Subject" "receipt" 100 ) { 101 fileinto :create "Billing"; 102 stop; 103 } 104 105 # Newsletters (has unsubscribe but no List-Id) 106 if allof ( 107 header :contains "List-Unsubscribe" "http", 108 not exists "List-Id" 109 ) { 110 fileinto :create "Newsletters"; 111 stop; 112 } 113 114 # Everything else -> INBOX 115 keep; 116 ''; 117 }; 118 "bot@lassul.us" = { 119 hashedPasswordFile = 120 config.clan.core.vars.generators.mailserver-bot.files."bot-mail-password-hash".path; 121 }; 122 }; 123 124 # TLS via existing ACME cert 125 x509.useACMEHost = "mail.lassul.us"; 126 127 # DKIM — auto-managed by module 128 dkimSigning = true; 129 dkimSelector = "mail"; 130 131 # Full-text search for IMAP clients 132 fullTextSearch = { 133 enable = true; 134 memoryLimit = 500; 135 }; 136 137 stateVersion = 3; 138 }; 139 140 # Password generation for mail accounts 141 clan.core.vars.generators.mailserver-lass = { 142 files."lass-mail-password" = { }; 143 files."lass-mail-password-hash" = { }; 144 runtimeInputs = with pkgs; [ 145 coreutils 146 mkpasswd 147 pwgen 148 ]; 149 script = '' 150 pwgen -s 32 1 > "$out/lass-mail-password" 151 mkpasswd -sm bcrypt < "$out/lass-mail-password" > "$out/lass-mail-password-hash" 152 ''; 153 }; 154 155 clan.core.vars.generators.mailserver-bot = { 156 files."bot-mail-password" = { }; 157 files."bot-mail-password-hash" = { }; 158 runtimeInputs = with pkgs; [ 159 coreutils 160 mkpasswd 161 pwgen 162 ]; 163 script = '' 164 pwgen -s 32 1 > "$out/bot-mail-password" 165 mkpasswd -sm bcrypt < "$out/bot-mail-password" > "$out/bot-mail-password-hash" 166 ''; 167 }; 168 169 # Retiolum relay: allow krebs hosts to relay through postfix 170 services.postfix.settings.main.mynetworks = lib.mkForce ( 171 [ 172 "127.0.0.0/8" 173 "[::1]/128" 174 ] 175 ++ mynetworks 176 ); 177 178 # ACME cert — reuse existing setup 179 security.acme.certs."mail.lassul.us" = { 180 group = "lasscert"; 181 webroot = "/var/lib/acme/acme-challenge"; 182 }; 183 users.groups.lasscert.members = [ 184 "dovecot2" 185 "postfix" 186 "nginx" 187 ]; 188 189 # Firewall rules (krebs.iptables pattern, INPUT policy is DROP) 190 krebs.iptables.tables.filter.INPUT.rules = [ 191 { 192 predicate = "-p tcp --dport smtp"; 193 target = "ACCEPT"; 194 } 195 { 196 predicate = "-p tcp --dport submissions"; 197 target = "ACCEPT"; 198 } 199 { 200 predicate = "-p tcp --dport submission"; 201 target = "ACCEPT"; 202 } 203 { 204 predicate = "-p tcp --dport imaps"; 205 target = "ACCEPT"; 206 } 207 ]; 208 209 # msmtp for local submission via SSH 210 environment.systemPackages = [ pkgs.msmtp ]; 211}