nixos-config/config/service/mail-server.nix

181 lines
5.5 KiB
Nix

{ 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)) + "\n\ndeny 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.services" ];
};
};
"smtp.${mailserver-domain-name}" = {
admin-email = "admin@${mailserver-domain-name}";
local-copies.postfix = {
user = config.services.postfix.user;
dependent-services = [ "postfix.services" ];
};
};
};
};
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);
};
};
};
}