{ config, lib, pkgs, ... }: with lib; let cfg = config.fudo.services.mail-server; hostname = config.instance.hostname; domain-name = config.instance.local-domain; domain = config.fudo.domains.${domain-name}; mailserver-host = domain.primary-mailserver; mailserver-domain-name = config.fudo.hosts.${mailserver-host}.domain; mailserver-domain = config.fudo.domains.${mailserver-domain-name}; mailserver-host-fqdn = "${mailserver-host}.${mailserver-domain-name}"; isMailServer = hostname == mailserver-host; isLocalMailserver = domain-name == mailserver-domain-name; metricsEnabled = mailserver-domain.prometheus-hosts != [ ]; host-certs = config.fudo.acme.host-domains.${hostname}; in { options.fudo.services.mail-server = with types; { debug = mkEnableOption "Enable debug options for mailserver."; state-directory = mkOption { type = str; description = "Directory at which to store mailserver state."; }; }; config = { services.nginx = mkIf (isMailServer && metricsEnabled) { enable = true; recommendedOptimisation = true; recommendedProxySettings = true; virtualHosts."mail-stats.${mailserver-domain-name}" = let trusted-networks = config.instance.local-networks; trustedNetworkString = optionalString (length trusted-networks > 0) (concatStringsSep "\n" (map (network: "allow ${network};") trusted-networks)) + '' deny all;''; in { enableACME = true; forceSSL = true; locations = let monitor-cfg = config.fudo.mail-server.monitoring; in { "/metrics/dovecot" = { proxyPass = "http://127.0.0.1:${ toString monitor-cfg.dovecot-listen-port }/metrics"; extraConfig = trustedNetworkString; }; "/metrics/postfix" = { proxyPass = "http://127.0.0.1:${ toString monitor-cfg.postfix-listen-port }/metrics"; extraConfig = trustedNetworkString; }; "/metrics/rspamd" = { proxyPass = "http://127.0.0.1:${ toString monitor-cfg.rspamd-listen-port }/metrics"; extraConfig = trustedNetworkString; }; }; }; }; fudo = { acme.host-domains = mkIf isMailServer { ${hostname} = { "imap.${mailserver-domain-name}" = { admin-email = "admin@${mailserver-domain-name}"; local-copies.dovecot = { user = config.services.dovecot2.user; dependent-services = [ "dovecot2.service" ]; }; }; "smtp.${mailserver-domain-name}" = { admin-email = "admin@${mailserver-domain-name}"; local-copies.postfix = { user = config.services.postfix.user; dependent-services = [ "postfix.service" ]; }; }; }; }; zones = mkIf isLocalMailserver { ${mailserver-domain.zone} = let server-ipv4 = pkgs.lib.network.host-ipv4 config mailserver-host; server-ipv6 = pkgs.lib.network.host-ipv6 config mailserver-host; srv-record = host: port: [{ host = "${host}.${mailserver-domain-name}"; port = port; }]; in { hosts = genAttrs [ "imap" "smtp" ] (alias: { ipv4-address = server-ipv4; ipv6-address = server-ipv6; description = "Primary ${toUpper alias} server for ${mailserver-domain-name}."; }); mx = [ "smtp.${mailserver-domain-name}" ]; aliases = mkIf metricsEnabled { mail-stats = "${mailserver-host-fqdn}."; }; srv-records.tcp = { pop3 = srv-record "imap" 110; pop3s = srv-record "imap" 995; imap = srv-record "imap" 143; imaps = srv-record "imap" 993; smtp = srv-record "smtp" 25; submission = srv-record "smtp" 587; }; metric-records = mkIf metricsEnabled (genAttrs [ "dovecot" "postfix" "rspamd" ] (_: srv-record "mail-stats" 443)); }; }; metrics.prometheus.service-discovery-dns = mkIf metricsEnabled (genAttrs [ "dovecot" "postfix" "rspamd" ] (mtype: [ "${mtype}._metrics._tcp.${mailserver-domain-name}" ])); mail-server = mkIf isLocalMailserver { enable = isMailServer; domain = mailserver-domain-name; mail-hostname = "smtp.${mailserver-domain-name}"; monitoring.enable = metricsEnabled; debug = cfg.debug; clamav.enable = true; dkim.signing = true; dovecot = let cert-copy = host-certs."imap.${mailserver-domain-name}".local-copies.dovecot; in { ssl-certificate = cert-copy.full-certificate; ssl-private-key = cert-copy.private-key; }; postfix = let cert-copy = host-certs."smtp.${mailserver-domain-name}".local-copies.postfix; in { ssl-certificate = cert-copy.full-certificate; ssl-private-key = cert-copy.private-key; }; local-domains = [ mailserver-host-fqdn "smtp.${mailserver-domain-name}" ]; mail-directory = "${cfg.state-directory}/mail"; state-directory = "${cfg.state-directory}/state"; trusted-networks = config.instance.local-networks; alias-users = genAttrs [ "root" "postmaster" "hostmaster" "webmaster" "system" "admin" "dmarc-report" ] (alias: config.instance.local-admins); }; }; }; }