Install and Integrate OpenDKIM with Postfix | Sign & Authenticate Your Emails

In the previous tutorial, we Set up a Mail Server with Postfix and Dovecot on Ubuntu/Debian. In this guide, we will take the next important step: Installing and Integrating OpenDKIM with Postfix.

OpenDKIM adds a digital signature to outgoing emails. This allows email providers such as Gmail and Outlook to verify the sender, which:

  • Increases the trustworthiness of your mail server.
  • Reduces the chance of emails being flagged as spam.
  • Improves the professionalism of your organization when sending emails.

Prerequisites

Before starting, make sure that Postfix and Dovecot are properly running on your system. This is required before integrating OpenDKIM.

sudo systemctl status postfix

sudo systemctl status dovecot

Ensure that the Postfix and Dovecot services are currently in the “running” state

Install OpenDKIM

Install OpenDKIM along with the required tools:

sudo apt update

sudo apt install opendkim opendkim-tools -y

Start the service and enable it at system boot:

sudo systemctl start opendkim

sudo systemctl enable opendkim

3. Create Directory & Generate DKIM Key

Create a directory structure to store the DKIM keys:

sudo mkdir -p /etc/opendkim/keys/yourdomain.com

sudo touch /etc/opendkim/{KeyTable,SigningTable,TrustedHosts}

cd /etc/opendkim/keys/yourdomain.com

Generate the DKIM key (you can choose a short, simple selector, e.g., mail):

sudo opendkim-genkey -s mail -d yourdomain.com

sudo chown opendkim:opendkim mail.private

The command will generate two files:

  • mail.private: Private key, used by OpenDKIM to sign outgoing emails (must be kept secure and never shared).
  • mail.txt: contains the TXT record (public key) to be published in DNS.

After generating the DKIM key, set the correct ownership and permissions to keep the private key secure:

sudo chown -R opendkim:opendkim /etc/opendkim/keys

sudo chmod 700 /etc/opendkim/keys /etc/opendkim/keys/yourdomain.com

sudo chmod 600 /etc/opendkim/keys/yourdomain.com/mail.private

Explanation:

  • chown -R opendkim:opendkim /etc/opendkim/keys → ensures that only the opendkim user owns the directory.
  • chmod 700 → restricts access so only the opendkim user can access the key directory.
  • chmod 600 → ensures only the opendkim user can read/write the private key file (it must never be exposed).

Configure OpenDKIM

Edit the main config file

Open and edit the file opendkim.conf

sudo vim /etc/opendkim.conf

Find and edit the following lines:

  • Uncomment LogWhy.
  • Uncomment Mode and SubDomains.
  • Modify the Socket line so Postfix can communicate with OpenDKIM:
Socket  inet:[email protected]

Add the following lines at the end of the file:

KeyTable           /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
TrustedHosts /etc/opendkim/TrustedHosts

After editing, the file should look like the example below:


# This is a basic configuration for signing and verifying. It can easily be
# adapted to suit a basic installation. See opendkim.conf(5) and
# /usr/share/doc/opendkim/examples/opendkim.conf.sample for complete
# documentation of available configuration parameters.

Syslog yes
SyslogSuccess yes
LogWhy no


# Common signing and verification parameters. In Debian, the "From" header is
# oversigned, because it is often the identity key used by reputation systems
# and thus somewhat security sensitive.
Canonicalization relaxed/simple
Mode sv
SubDomains no
OversignHeaders From


# Signing domain, selector, and key (required). For example, perform signing
# for domain "example.com" with selector "2020" (2020._domainkey.example.com),
# using the private key stored in /etc/dkimkeys/example.private. More granular
# setup options can be found in /usr/share/doc/opendkim/README.opendkim.
#Domain example.com
#Selector 2020
#KeyFile /etc/dkimkeys/example.private

# In Debian, opendkim runs as user "opendkim". A umask of 007 is required when
# using a local socket with MTAs that access the socket as a non-privileged
# user (for example, Postfix). You may need to add user "postfix" to group
# "opendkim" in that case.
UserID opendkim
UMask 007


# Socket for the MTA connection (required). If the MTA is inside a chroot jail,
# it must be ensured that the socket is accessible. In Debian, Postfix runs in
# a chroot in /var/spool/postfix, therefore a Unix socket would have to be
# configured as shown on the last line below.
#Socket local:/run/opendkim/opendkim.sock
#Socket inet:8891@localhost
Socket inet:[email protected]
#Socket local:/var/spool/postfix/opendkim/opendkim.sock

PidFile /run/opendkim/opendkim.pid

# Hosts for which to sign rather than verify, default is 127.0.0.1. See the
# OPERATION section of opendkim(8) for more information.
#InternalHosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# The trust anchor enables DNSSEC. In Debian, the trust anchor file is provided
# by the package dns-root-data.
TrustAnchorFile /usr/share/dns/root.key
#Nameservers 127.0.0.1
#ADD NEW
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts

Edit the KeyTable file

This file defines which domain uses which DKIM key. It maps a selector and domain to the path of the corresponding private key.

Open and edit the file:

sudo vim /etc/opendkim/KeyTable

Add the following content:

mail._domainkey.yourdomain.com yourdomain.com:mail:/etc/opendkim/keys/yourdomain.com/mail.private

Edit the SigningTable file

This file maps email addresses or entire domains to the selectors defined in the KeyTable. It tells OpenDKIM which key should be used for which sender.

Open and edit file

sudo vim /etc/opendkim/SigningTable

Add the following content:

*@yourdomain.com mail._domainkey.yourdomain.com

Edit the TrustedHosts file

This file lists the hosts that are allowed to use OpenDKIM for signing. Normally, this includes localhost and your mail server’s domain.

Open and edit file

sudo vim /etc/opendkim/TrustedHosts

Add the following content:

127.0.0.1
localhost
yourdomain.com

Integrate OpenDKIM with Postfix

Edit /etc/postfix/main.cf and add the following lines:

milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

Explanation:

  • milter_default_action = accept: if OpenDKIM fails, emails will still be sent instead of being blocked.
  • milter_protocol = 2: defines the milter protocol for Postfix and OpenDKIM communication.
  • smtpd_milters: specifies the OpenDKIM socket for outgoing emails.
  • non_smtpd_milters: applies the filter to non-SMTP generated emails as well.

Restart services:

sudo systemctl restart opendkim postfix

Check the status:

systemctl status opendkim
systemctl status postfix

Configure DNS for DKIM

  • Open the mail.txt file generated earlier.
  • Copy the TXT record content (public key).
  • Merge the entire key into one single line (remove all quotes ") and add it to your DNS:
Record name: mail._domainkey
Type: TXT
Value: v=DKIM1; k=rsa; p=...

Verify DKIM

After the DNS record is updated, verify it using:

dig TXT mail._domainkey.yourdomain.com

Then send a test email to:

  • A personal Gmail account → use “Show original” to check if DKIM=PASS.
  • A service like mail-tester.com → for a detailed SPF, DKIM, and DMARC report.

If the result shows DKIM=PASS, it means your configuration is correct and the public key in DNS matches the private key on the server.

Conclusion

We have successfully:

  • Installed OpenDKIM.
  • Generated and configured DKIM keys.
  • Integrated OpenDKIM with Postfix.
  • Added the DKIM record to DNS.
  • Verified the configuration.

With DKIM, your emails will gain higher trust, reduce the chance of being marked as spam, and enhance the professionalism of your mail server.

Read more

Video

Leave a Reply

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