191 lines
5.8 KiB
Nix
191 lines
5.8 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-fqdn = "${mailserver-host}.${mailserver-domain-name}";
|
|
|
|
hasMailServer = mailserver-host != null;
|
|
|
|
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 = mkIf hasMailServer {
|
|
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 = {
|
|
${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: [{ inherit host port; }];
|
|
|
|
in {
|
|
aliases = mkIf metricsEnabled { mail-stats = "${mailserver-fqdn}."; };
|
|
|
|
# srv-records.tcp = {
|
|
# pop3 = srv-record mailserver-fqdn 110;
|
|
# pop3s = srv-record mailserver-fqdn 995;
|
|
|
|
# imap = srv-record mailserver-fqdn 143;
|
|
# imaps = srv-record mailserver-fqdn 993;
|
|
|
|
# smtp = srv-record mailserver-fqdn 25;
|
|
# submission = srv-record mailserver-fqdn 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-fqdn "smtp.${mailserver-domain-name}" ];
|
|
|
|
mail-directory = "${cfg.state-directory}/mail";
|
|
state-directory = "${cfg.state-directory}/state";
|
|
|
|
trusted-networks = let
|
|
wrapIpv6 = net:
|
|
let elems = builtins.split "/" net;
|
|
in "[${elemAt elems 0}]/${elemAt elems 2}";
|
|
|
|
in map (network:
|
|
if (builtins.match ".*::.*" network) != null then
|
|
wrapIpv6 network
|
|
else
|
|
network) config.instance.local-networks;
|
|
|
|
user-aliases = genAttrs (attrNames config.fudo.users)
|
|
(username: config.fudo.users."${username}".email-aliases);
|
|
|
|
alias-users = genAttrs [
|
|
"root"
|
|
"postmaster"
|
|
"hostmaster"
|
|
"webmaster"
|
|
"system"
|
|
"admin"
|
|
"dmarc-report"
|
|
] (alias: config.instance.local-admins);
|
|
};
|
|
};
|
|
};
|
|
}
|