.. SPDX-License-Identifier: GPL-3.0-or-later .. SPDX-FileCopyrightText: 2026 Martin Weinelt .. _dkim: DKIM Signing ============ DKIM (DomainKeys Identified Mail) is an email authentication mechanism that allows a mailserver to digitally sign outgoing emails for a domain. Receiving mail servers can verify this signature using a public key published in DNS to confirm the message was authorized by the domain and was not modified during transit. How DKIM works in practice ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. ``bob@bar.example`` sends an email to ``alice@foo.example``. The sending mail server for ``bar.example`` selects one or multiple DKIM keys using a **selector** (e.g., ``mail``) and creates one or multiple cryptographic signature for selected headers and the message body, adding a ``DKIM-Signature`` header that references the selector. 2. The message arrives at ``foo.example``. The receiving mail server reads the ``DKIM-Signature`` headers, looks up the public keys for ``bar.example`` for each of the specified selectors (e.g., ``mail._domainkey.bar.example``), and verifies that at least one signature matches the message content. 3. With a valid signature, the receiver knows the message was authorized by ``bar.example`` and that the signed headers and body were not modified in transit. If the content or signed headers were changed, the DKIM verification fails. The use of selectors allows ``bar.example`` to rotate or migrate keys without disrupting verification for previously sent messages. Enabling DKIM Signing ~~~~~~~~~~~~~~~~~~~~~ Because DKIM signing is crucial for reliable mail delivery it is enabled by default and without further configuration a DKIM keypair will be generated for each :option:`mailserver.domains` (including :option:`mailserver.srs.domain`, if set) based on :option:`mailserver.dkim.defaults `. .. code:: nix { mailserver = { domains = [ "example.com" ]; dkim.enable = true; # enabled by default }; } .. note:: If you set up NixOS Mailserver before the `25.11 release`_ your DKIM keys were generated with 1024 bit RSA and we recommend replacing them with 2048 bit RSA key material per `RFC8301 3.2`_. .. _25.11 release: release-notes.html#nixos-25-11 .. _RFC8301 3.2: https://www.rfc-editor.org/rfc/rfc8301#section-3.2 .. _dkim-key-rotation: DKIM Key Rotation ~~~~~~~~~~~~~~~~~ DKIM key rotation replaces a domain's signing keys to maintain strong email authentication and support algorithm upgrades. Rotation is essential for migrating away from weaker or deprecated algorithms. Selectors allow multiple keys to coexist during the transition: a new key can be deployed under a different selector while the old key remains valid for a limited period to verify messages still in transit. Once all messages signed with the old key have been delivered, the key can be safely retired, ensuring a reliable migration without breaking verification. 1. Make the automatically generated key explicit ************************************************ First we need to make sure we keep the current DKIM key configured. If you were relying on automatically generated keys before, you now need to start explicitly defining that key, because explicit selector configuration takes precedence. .. code:: nix { mailserver = { domains = [ "example.com" ]; dkim.domains = { "example.com".selectors = { "${config.mailserver.dkim.defaults.selector}" = { }; }; }; }; } 2. Create the new DKIM keypair ****************************** Next we need to create a new DKIM key with a unique selector, you can for example choose the current date. Without any settings passed a new key will be generated from the current :option:`mailserver.dkim.defaults `, which should be sufficient. .. code:: nix { mailserver = { domains = [ "example.com" ]; dkim = { enable = true; domains."example.com".selectors = { "${config.mailserver.dkim.defaults.selector}" = { }; "rsa-2026-03" = { keyType = "rsa"; keyLength = 2048; }; }; }; }; } .. warning:: While DKIM does support Ed25519 keys (`RFC8463`_), many validators still lack proper support and may treat Ed25519 key material as invalid. As a result, mail signed only with Ed25519 DKIM keys may fail verification at some receivers. .. _RFC8463: https://datatracker.ietf.org/doc/html/rfc8463 Once this configuration is applied the new keypair will be generated below :option:`mailserver.dkim.keyDirectory`, which defaults to ``/var/dkim``. The mailserver then begins signing outgoing mail with this key, so that it is now signing with two DKIM keys simultaneously. To allow receiving servers to verify the new DKIM signature its public key needs to be published into DNS. Look up the public key from ``/var/dkim/example.com.rsa-2026-03.txt`` and create the following DNS record by substituting selector and public key. .. csv-table:: :header: "Name", "TTL", "Type", "Value" :widths: 30, 10, 10, 50 rsa-2026-03._domainkey.example.com., 86400, TXT, v=DKIM1; k=rsa; p= .. note:: If you created an Ed25519 key, make sure to set the correct key type: ``k=ed25519`` Now wait for a few minutes and then check DNS propagation to show the value specified. .. code-block:: console $ nix-shell -p dig --command "dig @ns1.example.org TXT rsa-2026-03._domainkey.example.com" You can use https://www.mail-tester.com to test the new DKIM signature passes validation. They allow you to view the message source where you can check that the correct number of ``DKIM-Signature`` keys are present in the mail header. 3. Stop signing with the old DKIM keypair ***************************************** Once validation passes we need to stop signing with the old DKIM keypair, so mail in transit eventually stops depending on the key material we want to rotate out. Removing the selector will not remove the key material from disk, but it will stop using it to sign outgoing mail. .. code:: nix { mailserver = { domains = [ "example.com" ]; dkim = { enable = true; domains."example.com".selectors = { "rsa-2026-03" = { keyType = "rsa"; keyLength = 2048; }; }; } } } Apply the configuration. 4. Remove the old DKIM selector from DNS **************************************** .. warning:: Do not remove the DNS records for the old selector immediately. Keeping them in place is essential to ensure that messages still in transit can be verified and delivered successfully. Mail delivery is not always instantaneous. In the worst case, multiple retries over several days may be required. According to `RFC5321 4.5.4.1`_ delivery should be retried for at least 4-5 days. This means messages signed only with the old DKIM key could still be in transit and rely on the old selector to verify their signatures. To ensure reliable delivery, we recommend waiting **at least five days** before removing the old DKIM selector from DNS. .. _RFC5321 4.5.4.1: https://www.rfc-editor.org/rfc/rfc5321#section-4.5.4.1