Merge branch 'dkim-path' into 'master'

feat: add support for DKIM private key files

See merge request simple-nixos-mailserver/nixos-mailserver!344
This commit is contained in:
Jeremy Fleischman 2025-03-26 04:15:19 +00:00
commit 230e1eb1fc
3 changed files with 43 additions and 8 deletions

View File

@ -794,6 +794,21 @@ in
'';
};
dkimPrivateKeyFiles = mkOption {
type = types.nullOr (types.attrsOf types.path);
default = null;
example = {
"mail.example.com" = "/run/secrets/dkim/mail.example.com.mail.key";
};
description = ''
Paths to opendkim private keys generated with `opendkim-genkey`,
indexed by domain name.
If `null`, then the keys are auto generated.
If set, then there must be an entry for every domain in
{option}`config.mailserver.domains`.
'';
};
dkimKeyDirectory = mkOption {
type = types.path;
default = "/var/dkim";
@ -803,8 +818,8 @@ in
};
dkimKeyBits = mkOption {
type = types.int;
default = 1024;
type = types.nullOr types.int;
default = if cfg.dkimPrivateKeyFiles == null then 1024 else null;
description = ''
How many bits in generated DKIM keys. RFC6376 advises minimum 1024-bit keys.

View File

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }:
{ config, lib, ... }:
{
assertions = lib.optionals config.mailserver.ldap.enable [
{
@ -18,5 +18,15 @@
assertion = config.mailserver.acmeCertificateName == config.mailserver.fqdn;
message = "When the certificate scheme is not 'acme' (mailserver.certificateScheme != \"acme\"), it is not possible to define mailserver.acmeCertificateName";
}
] ++ lib.optionals (config.mailserver.enable && config.mailserver.dkimPrivateKeyFiles != null) [
{
assertion = config.mailserver.dkimKeyBits == null;
message = "When you bring your own DKIM private keys (mailserver.dkimPrivateKeyFiles != null), you must not specify key generation options (mailserver.dkimKeyBits)";
}
] ++ lib.optionals (config.mailserver.enable && config.mailserver.dkimPrivateKeyFiles == null) [
{
assertion = config.mailserver.dkimKeyBits != null;
message = "When generating DKIM private keys (mailserver.dkimPrivateKeyFiles = null), you must specify key generation options (mailserver.dkimKeyBits)";
}
];
}

View File

@ -23,14 +23,24 @@ let
dkimUser = config.services.opendkim.user;
dkimGroup = config.services.opendkim.group;
createDomainDkimCert = dom:
createOrLinkDkimCerts = dom:
let
dkim_key = "${cfg.dkimKeyDirectory}/${dom}.${cfg.dkimSelector}.key";
dkim_txt = "${cfg.dkimKeyDirectory}/${dom}.${cfg.dkimSelector}.txt";
dkimPrivateKeyFile = cfg.dkimPrivateKeyFiles.${dom};
in
if cfg.dkimPrivateKeyFiles != null then
''
if [ ! -f "${dkim_key}" ]
then
if [ ! -e "${dkimPrivateKeyFile}" ]; then
echo "DKIM keyfile does not exist: ${dkimPrivateKeyFile}"
exit 1
fi
ln -sf "${dkimPrivateKeyFile}" "${dkim_key}"
''
else
''
if [ ! -e "${dkim_key}" ]; then
${pkgs.opendkim}/bin/opendkim-genkey -s "${cfg.dkimSelector}" \
-d "${dom}" \
--bits="${toString cfg.dkimKeyBits}" \
@ -41,7 +51,7 @@ let
echo "Generated key for domain ${dom} selector ${cfg.dkimSelector}"
fi
'';
createAllCerts = lib.concatStringsSep "\n" (map createDomainDkimCert cfg.domains);
createOrLinkAllCerts = lib.concatStringsSep "\n" (map createOrLinkDkimCerts cfg.domains);
keyTable = pkgs.writeText "opendkim-KeyTable"
(lib.concatStringsSep "\n" (lib.flip map cfg.domains
@ -76,7 +86,7 @@ in
postfix.extraGroups = [ "${dkimGroup}" ];
};
systemd.services.opendkim = {
preStart = lib.mkForce createAllCerts;
preStart = lib.mkForce createOrLinkAllCerts;
serviceConfig = {
ExecStart = lib.mkForce "${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}";
PermissionsStartOnly = lib.mkForce false;