Self-host your own digital island
1{ pkgs, config, lib, ... }: 2 3with lib; 4let 5 cfg = config.eilean; 6 domain = config.networking.domain; 7in { 8 options.eilean.mailserver = { 9 enable = mkEnableOption "mailserver"; 10 systemAccountPasswordFile = mkOption { 11 type = types.nullOr types.str; 12 default = null; 13 }; 14 }; 15 16 config = mkIf cfg.mailserver.enable { 17 mailserver = { 18 enable = true; 19 fqdn = "mail.${domain}"; 20 domains = [ "${domain}" ]; 21 22 loginAccounts = { 23 "system@${domain}" = { 24 passwordFile = cfg.mailserver.systemAccountPasswordFile; 25 aliases = [ 26 (mkIf cfg.gitea.enable "git@${domain}") 27 (mkIf cfg.mastodon.enable "mastodon@${domain}") 28 ]; 29 }; 30 }; 31 32 # Use Let's Encrypt certificates. Note that this needs to set up a stripped 33 # down nginx and opens port 80. 34 certificateScheme = "acme-nginx"; 35 36 localDnsResolver = false; 37 }; 38 39 services.nginx.enable = true; 40 services.nginx.virtualHosts."${config.mailserver.fqdn}".extraConfig = '' 41 return 301 $scheme://${domain}$request_uri; 42 ''; 43 44 services.postfix.config = { 45 smtpd_tls_protocols = 46 mkForce "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3"; 47 smtp_tls_protocols = 48 mkForce "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3"; 49 smtpd_tls_mandatory_protocols = 50 mkForce "TLSv1.3, !TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3"; 51 smtp_tls_mandatory_protocols = 52 mkForce "TLSv1.3, !TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3"; 53 }; 54 55 eilean.dns.enable = true; 56 eilean.services.dns.zones.${config.networking.domain}.records = [ 57 { 58 name = "mail"; 59 type = "A"; 60 data = cfg.serverIpv4; 61 } 62 { 63 name = "mail"; 64 type = "AAAA"; 65 data = cfg.serverIpv6; 66 } 67 { 68 name = "@"; 69 type = "MX"; 70 data = "10 mail"; 71 } 72 { 73 name = "@"; 74 type = "TXT"; 75 data = ''"v=spf1 a:mail.${config.networking.domain} -all"''; 76 } 77 { 78 name = "mail._domainkey"; 79 ttl = 10800; 80 type = "TXT"; 81 data = '' 82 "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6YmYYvoFF7VqtGcozpVQa78aaGgZdvc5ZIHqzmkKdCBEyDF2FRbCEK4s2AlC8hhc8O4mSSe3S4AzEhlRgHXbU22GBaUZ3s2WHS8JJwZvWeTjsbXQwjN/U7xpkqXPHLH9IVfOJbHlp4HQmCAXw4NaypgkkxIGK0jaZHm2j6/1izQIDAQAB"''; 83 } 84 { 85 name = "_dmarc"; 86 ttl = 10800; 87 type = "TXT"; 88 data = ''"v=DMARC1; p=reject"''; 89 } 90 ]; 91 }; 92}