DKIM setup with Postfix and Rspamd on Debian Linux

DomainKeys Identified Mail is a standard that allows an MTA to add a signature to outgoing mails. The receiving MTA can validate the signature using a key published in the sender's DNS records. This page outlines how to configure Postfix and Rspamd on Debian bullseye. This article is an update to an older post on DKIM with Postfix and OpenDKIM, replacing OpenDKIM with a combination of Rspamd and the python3-dkim tools. Like the older article, the setup described here uses a UNIX socket for the Postfix-to-Rspamd communication rather than a TCP port. This is marginally more secure as it removes one potential remote attack surface compared to a setup using a TCP port.

Generate the keys

Install the python3-dkim package, then generate a key for each of your domains. I suggest to include the selector in the file name, this helps when rotating keys. I use a form like YYYYMMDD for the selector which uses the current date. This makes it easy to add a new key in the DNS record and still use the old key in Postfix while the change slowly trickles through the various layers of DNS caches.

dknewkey example.com.YYYYMMDD
dknewkey example.org.YYYYMMDD
…

This creates two files for each domain, selector.domain.key and selector.domain.dns.

Create the directory /var/lib/rspamd/dkim if needed on the server and copy the .key files to this directory. Keep these files secret, as they contain the private key used to sign mails.

The .dns file is a DNS TXT record which needs to be copied to the DNS configuration for the domain. Below is an example of the domain.YYYYMMDD.dns file. Copy the content of the file to the DNS TXT record with name YYYYMMDD._domainkey.

YYYYMMDD._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2hL+x…";

Allow a few hours for the various DNS servers to refresh their cache before configuring Postfix.

Rspamd configuration

Create the /var/spool/postfix/rspamd directory, owned by postfix and group _rspamd.

Then edit the file /etc/rspamd/local.d/worker-proxy.inc with the following content:

# this worker will be used as postfix milter
milter = yes;

bind_socket = "/var/spool/postfix/rspamd/milter.sock mode=0666 owner=nobody";

# the following specifies self-scan mode, for when rspamd is on the same
# machine as postfix
timeout = 120s;
upstream "local" {
  default = yes;
  self_scan = yes;
}

Finally edit /etc/rspamd/local.d/dkim_signing.conf and add:

path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector = "20211016";
### Enable DKIM signing for alias sender addresses
allow_username_mismatch = true;

Restart Rspamd to activate the changes.

Postfix configuration

Edit /etc/postfix/main.cf and add the following line that tells Postfix to handle milter errors gracefully.

milter_default_action = accept

If the DKIM milter is the only in use, then add also the following lines:

smtpd_milters = unix:/rspamd/milter.sock
non_smtpd_milters = unix:/rspamd/milter.sock

Also set the milter_mail_macros and milter_protocol options:

milter_protocol = 6
milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}

Finally, restart Postfix and you're done.

service postfix restart