mail-server/dkim.nix

125 lines
3.6 KiB
Nix
Raw Normal View History

2023-09-17 09:57:55 -07:00
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.fudo.mail.dkim;
ensureDomainDkimCert = keyDir: domain:
let
dkimKey = "${keyDir}/${domain}.mail.key";
dkimTxt = "${keyDir}/${domain}.mail.txt";
in ''
if [ ! -f "${dkimKey}" ] || [ ! -f ${dkimTxt} ]; then
2023-09-28 13:00:01 -07:00
OUT=$(${pkgs.coreutils}/bin/mktemp -d -t dkim-XXXXXXXXXX)
2023-09-17 09:57:55 -07:00
opendkim-genkey \
2023-09-28 13:00:01 -07:00
--selector=mail \
--domain=${domain} \
2023-09-17 09:57:55 -07:00
--bits="${toString cfg.key-bits}" \
2023-09-28 13:00:01 -07:00
--directory=$OUT
mv $OUT/mail.private ${dkimKey}
mv $OUT/mail.txt ${dkimTxt}
2023-09-17 09:57:55 -07:00
fi
'';
2023-09-24 11:00:56 -07:00
ensureAllDkimCerts = keyDir: domains:
concatStringsSep "\n" (map (ensureDomainDkimCert keyDir) domains);
2023-09-17 09:57:55 -07:00
makeKeyTable = keyDir: domains:
pkgs.writeText "opendkim-key-table" (concatStringsSep "\n"
2023-09-24 11:21:16 -07:00
(map (dom: "${dom}:mail:${keyDir}/${dom}.mail.key") domains));
2023-09-17 09:57:55 -07:00
makeSigningTable = domains:
pkgs.writeText "opendkim-signing-table"
(concatStringsSep "\n" (map (dom: "${dom} ${dom}") domains));
in {
options.fudo.mail.dkim = with types; {
enable = mkEnableOption "Enable DKIM signature verification.";
debug = mkEnableOption "Enable debug logs.";
domains = mkOption {
type = listOf str;
description =
"List of domains to be considered local, and signed instead of verified.";
};
2023-09-24 10:52:57 -07:00
selector = mkOption {
type = str;
description = "Name to use for mail-signing keys.";
default = "mail";
};
2023-09-24 12:07:48 -07:00
key-bits = mkOption {
type = int;
description = ''
How many bits in generated DKIM keys. RFC6376 advises minimum 1024-bit keys.
If you have already deployed a key with a different number of bits than specified
here, then you should use a different selector (dkimSelector). In order to get
this package to generate a key with the new number of bits, you will either have to
change the selector or delete the old key file.
'';
default = 2048;
};
2023-09-17 09:57:55 -07:00
port = mkOption {
type = port;
description = "Port at which to listen for incoming signing requests.";
default = 5324;
};
state-directory = mkOption {
type = str;
description = "Directory at which to store DKIM state (i.e. keys).";
};
};
config = mkIf cfg.enable {
2023-09-28 12:31:03 -07:00
networking.firewall = {
enable = true;
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];
};
2023-09-17 09:57:55 -07:00
services.opendkim = {
enable = true;
selector = cfg.selector;
domains = let domainString = concatStringsSep "," cfg.domains;
2023-09-24 11:27:27 -07:00
in "csl:${domainString}";
2023-09-17 09:57:55 -07:00
configFile = let
debugString = ''
Syslog yes
SyslogSuccess yes
LogWhy yes
'';
2023-09-24 11:00:56 -07:00
keyTable = makeKeyTable cfg.state-directory cfg.domains;
signingTable = makeSigningTable cfg.domains;
2023-09-17 09:57:55 -07:00
in pkgs.writeText "opendkim.conf" ''
Canonicalization relaxed/simple
Socket inet:${toString cfg.port}
KeyTable file: ${keyTable}
SigningTable file:${signingTable}
${optionalString cfg.debug debugString}
'';
};
systemd = {
tmpfiles.rules = let
user = config.services.opendkim.user;
group = config.services.opendkim.group;
in [ "d ${cfg.state-directory} 0700 ${user} ${group} - -" ];
services.opendkim = {
2023-09-27 13:01:06 -07:00
path = with pkgs; [ opendkim ];
2023-09-24 11:00:56 -07:00
serviceConfig = {
ExecStartPre = [
(pkgs.writeShellScript "ensure-dkim-certs.sh"
(ensureAllDkimCerts cfg.state-directory cfg.domains))
];
2023-09-24 11:00:56 -07:00
ReadWritePaths = [ cfg.state-directory ];
};
2023-09-17 09:57:55 -07:00
};
};
};
}