DKIM signature in Postfix on Debian


DKIM works by interfacing a proxy in postfix to add priv/pub signature to out-going emails using a private key and opendkim.

Matching public key will be exported in the DNS server so receiving SMTP can verify in the signature in the metadata matches the public key.

It helps for non being consider as a spamer.

A friend asked me to setup this on his two servers with two different domains so we’ll be setting up the whole thing here with separate keys pair for each domain/each server and we’ll allow both servers to sign emails for these domains.

Install required packages

apt install opendkim opendkim-tools rename dnsutils

Create pub/priv keys sets

According to /usr/share/doc/opendkim/README.Debian.gz there is a tool named opendkim-genkey that can help generating the key pairs. This tool is in opendkim-tools package.

As we want to allow different servers to sign messages with different key but for the same domain, we’ll use the origin server short hostname as selector. It means the signature will be somehow prefixed with this selector, indicating the receiver SMTP which DNS entry should be queried for getting associated public key. By doing so, we’ll be able to export different public key for each server.

opendkim-genkey -b 1024 -d -s `hostname -s` --directory=/etc/dkimkeys/
rename "s/`hostname -s`/`hostname -s`" /etc/dkimkeys/`hostname -s`.{txt,private}

opendkim-genkey -b 1024 -d -s `hostname -s` --directory=/etc/dkimkeys/
rename "s/`hostname -s`/`hostname -s`" /etc/dkimkeys/`hostname -s`.{txt,private}

chown opendkim:opendkim /etc/dkimkeys/`hostname -s`_*
chmod 0600 /etc/dkimkeys/`hostname -s`_*

Now you should see the private keys as well as public key as a bind9 snippet in /etc/dkimkeys:

drwx------   2 opendkim opendkim 4.0K May 29 22:40 .
 drwxr-xr-x 109 root     root     8.0K May 29 22:11 ..
 -rw-r-----   1 root     opendkim  887 May 29 22:39
 -rw-r-----   1 root     opendkim  329 May 29 22:39
 -rw-r-----   1 root     opendkim  887 May 29 22:40
 -rw-r-----   1 root     opendkim  339 May 29 22:40
 -rw-r--r--   1 root     root      664 Nov  7  2015 README.PrivateKeys

Register public key in DNS zones

Now you need to add the public signature in your DNS zone. In this example, the primary bind server for both and is running on the server itself so we can just do:

cat /etc/dkimkeys/`hostname -s` >> /etc/bind/zones/
cat /etc/dkimkeys/`hostname -s` >> /etc/bind/zones/

This is very unlikely that method is suitable for you, but you get the idea right ?

Don’t forget to bump DNS zone serial number and reload bind

sed -i "s/20\(1\|2\)[0-9][0-9]\{2\}[0-9]\{2\}[0-9]\{2\}/`date "+%Y%m%d01"`/" /etc/bind/zones/
sed -i "s/20\(1\|2\)[0-9][0-9]\{2\}[0-9]\{2\}[0-9]\{2\}/`date "+%Y%m%d01"`/" /etc/bind/zones/
systemctl reload bind9

We can now check with dig that our DNS server now expose the public key:

dig -t TXT `hostname -s` @

Should return something like:


;; ANSWER SECTION: 600 IN TXT	"v=DKIM1; h=sha256; k=rsa; " "p=aaa1111bbbb3333cccc"

Configure OpenDKIM

Now we need to create a KeyTable file to match domain, selector and private key file. We also need a SigningTable to actually ask for signature to be added to outgoing emails.

In /etc/opendkim.conf add the following entries at bottom of files:

LogWhy                yes
KeyTable              refile:/etc/dkimkeys/KeyTable
SigningTable          refile:/etc/dkimkeys/SigningTable

Then we we’ll create /etc/dkimkeys/KeyTable file:

echo -e "`hostname -s`:/etc/dkimkeys/`hostname -s`" >> /etc/dkimkeys/KeyTable
echo -e "`hostname -s`:/etc/dkimkeys/`hostname -s`" >> /etc/dkimkeys/KeyTable

The file now looks like:

Now we create /etc/dkimkeys/SigningTable file:

echo "*" >> /etc/dkimkeys/SigningTable
echo "*" >> /etc/dkimkeys/SigningTable

The file should content:


OpenDKIM is now configured, restart it

systemctl restart opendkim

Integrate with Postfix

On Debian systems Postfix is chrooted so there are a few additionnal steps to get it working correctly:

In /etc/opendkim.conf change the socket path to Postifx chroot:

Socket                  local:/var/spool/postfix/var/run/opendkim/opendkim.sock

Create proper folder in Postfix chroot and give proper permissions

mkdir -p /var/spool/postfix/var/run/opendkim
chown opendkim:opendkim /var/spool/postfix/var/run/opendkim

Add Postfix to opendkim group so it can write to the socket:

adduser postfix opendkim

Enable filtering in postfix (postconf commands will edit /etc/postfix/

Missing trailling / is not a typo !

postconf -e milter_protocol=6
postconf -e milter_default_action=accept
postconf -e smtpd_milters=unix:var/run/opendkim/opendkim.sock
postconf -e non_smtpd_milters=unix:var/run/opendkim/opendkim.sock

Restart both services:

systemctl restart opendkim
systemctl restart postfix


You can send an email from the server itself using following commands:

echo "This is a test" | mail -s "Test DKIM" -a "From:"
echo "This is a test" | mail -s "Test DKIM" -a "From:"

My server runs Postfix with Amavis so I can check the header of the email I just received and I can confirm valid DKIM signature has been seen:

X-Spam-Status: No, [...] DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VERIFIED=-0.5 [...]

Leave a Reply

Your email address will not be published. Required fields are marked *