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
andSubDomains
. - 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
- Install and Integrate OpenDKIM with Postfix | Sign & Authenticate Your Emails
- What is OpenDKIM? A Simple Guide from Basics to How It Works
- How to Install and Configure Fail2ban on Ubuntu/Debian
- Install n8n Server on Linux VPS (Ubuntu/Debian) | Docker + FreeSSL + Nginx
- How to Set Up WordPress Website on Ubuntu/Debian | Secure with Free SSL (Let’s Encrypt)