Tutorial

How To Install and Configure DKIM with Postfix on Debian Wheezy

Published on February 28, 2014
author

Popute Sebastian Armin

How To Install and Configure DKIM with Postfix on Debian Wheezy

Introduction

The frustration of getting falsely flagged as a spammer is not strange to most of the mail server admins. By excluding the possibility of a compromised server, a false flag is usually caused by one of the following:

  • the server is an open mail relay
  • the sender’s or server’s IP address is blacklisted
  • the server does not have a Fully Qualified Domain Name (FQDN) and a PTR record
  • the Sender Policy Framework (SPF) DNS record is missing or it is misconfigured
  • the DomainKeys Identified Mail (DKIM) implementation is missing or it’s not properly set up

These are some of the basic properties that are being checked by the majority of proprietary and open source spam filters (including SpamAssassin). Passing these tests is extremely important for a well configured mail server.

This tutorial will focus on installing and configuring OpenDKIM]: an open source implementation of the DKIM sender authentication system.

It is assumed that the reader knows how to access the server over SSH, Postfix and Dovecot is already installed and configured (tutorial), the host name and the FQDN are set up (tutorial, tutorial) and the SPF record is in place (tutorial).

About DKIM

DKIM is an Internet Standard that enables a person or organisation to associate a domain name with an email message. This, in effect, serves as a method of claiming responsibility for a message. At its core, DKIM is powered by asymmetric cryptography. The sender’s Mail Transfer Agent (MTA) signs every outgoing message with a private key. The recipient retrieves the public key from the sender’s DNS records and verifies if the message body and some of the header fields were not altered since the message signing took place.

Install OpenDKIM

Before starting the installation, a system update is recommended:

sudo apt-get update
sudo apt-get dist-upgrade

Install OpenDKIM and it’s dependencies:

sudo apt-get install opendkim opendkim-tools

Additional packages will be listed as dependencies, type yes and press Enter to continue.

Configure OpenDKIM

A couple of files must be created and edited in order to configure OpenDKIM.

Nano will be used as an editor because it’s installed by default on DigitalOcean droplets and it’s simple to operate:

  • navigate with the arrow keys
  • exit without saving changes: press CTRL + X and then N
  • exit and save changes: press CTRL + X and then Y, and finally press Enter

Important: replace every instance of example.com with your own domain in all commands and configuration files. Don’t forget to save your files after editing.

Let’s start with the main configuration file:

sudo nano /etc/opendkim.conf

Append the following lines to the end of the conf file (each parameter is explained below). Optionally, you can choose a custom port number for the Socket. Make sure that it’s not used by a different application.

AutoRestart             Yes
AutoRestartRate         10/1h
UMask                   002
Syslog                  yes
SyslogSuccess           Yes
LogWhy                  Yes

Canonicalization        relaxed/simple

ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts           refile:/etc/opendkim/TrustedHosts
KeyTable                refile:/etc/opendkim/KeyTable
SigningTable            refile:/etc/opendkim/SigningTable

Mode                    sv
PidFile                 /var/run/opendkim/opendkim.pid
SignatureAlgorithm      rsa-sha256

UserID                  opendkim:opendkim

Socket                  inet:12301@localhost
  • AutoRestart: auto restart the filter on failures

  • AutoRestartRate: specifies the filter’s maximum restart rate, if restarts begin to happen faster than this rate, the filter will terminate; 10/1h - 10 restarts/hour are allowed at most

  • UMask: gives all access permissions to the user group defined by UserID and allows other users to read and execute files, in this case it will allow the creation and modification of a Pid file.

  • Syslog, SyslogSuccess, *LogWhy: these parameters enable detailed logging via calls to syslog

  • Canonicalization: defines the canonicalization methods used at message signing, the simple method allows almost no modification while the relaxed one tolerates minor changes such as whitespace replacement; relaxed/simple - the message header will be processed with the relaxed algorithm and the body with the simple one

  • ExternalIgnoreList: specifies the external hosts that can send mail through the server as one of the signing domains without credentials

  • InternalHosts: defines a list of internal hosts whose mail should not be verified but signed instead

  • KeyTable: maps key names to signing keys

  • SigningTable: lists the signatures to apply to a message based on the address found in the From: header field

  • Mode: declares operating modes; in this case the milter acts as a signer (s) and a verifier (v)

  • PidFile: the path to the Pid file which contains the process identification number

  • SignatureAlgorithm: selects the signing algorithm to use when creating signatures

  • UserID: the opendkim process runs under this user and group

  • Socket: the milter will listen on the socket specified here, Posfix will send messages to opendkim for signing and verification through this socket; 12301@localhost defines a TCP socket that listens on localhost, port 12301

This simple configuration is meant to allow message signing for one or more domains, to learn about other options please go here.

Connect the milter to Postfix:

sudo nano /etc/default/opendkim

Add the following line, edit the port number only if a custom one is used:

SOCKET="inet:12301@localhost"

Configure postfix to use this milter:

sudo nano /etc/postfix/main.cf

Make sure that these two lines are present in the Postfix config file and are not commented out:

milter_protocol = 2
milter_default_action = accept

It is likely that a filter (SpamAssasin, Clamav etc.) is already used by Postfix; if the following parameters are present, just append the opendkim milter to them (milters are separated by a comma), the port number should be the same as in opendkim.conf:

smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301
non_smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301

If the parameters are missing, define them as follows:

smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

Create a directory structure that will hold the trusted hosts, key tables, signing tables and crypto keys:

sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys

Specify trusted hosts:

sudo nano /etc/opendkim/TrustedHosts

We will use this file to define both ExternalIgnoreList and InternalHosts, messages originating from these hosts, domains and IP addresses will be trusted and signed.

Because our main configuration file declares TrustedHosts as a regular expression file (refile), we can use wildcard patters, *.example.com means that messages coming from example.com’s subdomains will be trusted too, not just the ones sent from the root domain.

Customize and add the following lines to the newly created file. Multiple domains can be specified, do not edit the first three lines:

127.0.0.1
localhost
192.168.0.1/24

*.example.com

#*.example.net
#*.example.org

Create a key table:

sudo nano /etc/opendkim/KeyTable

A key table contains each selector/domain pair and the path to their private key. Any alphanumeric string can be used as a selector, in this example mail is used and it’s not necessary to change it.

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

#mail._domainkey.example.net example.net:mail:/etc/opendkim/keys/example.net/mail.private
#mail._domainkey.example.org example.org:mail:/etc/opendkim/keys/example.org/mail.private

Create a signing table:

sudo nano /etc/opendkim/SigningTable

This file is used for declaring the domains/email addresses and their selectors.

*@example.com mail._domainkey.example.com

#*@example.net mail._domainkey.example.net
#*@example.org mail._domainkey.example.org

Generate the public and private keys

Change to the keys directory:

cd /etc/opendkim/keys

Create a separate folder for the domain to hold the keys:

sudo mkdir example.com
cd example.com

Generate the keys:

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

-s specifies the selector and -d the domain, this command will create two files, mail.private is our private key and mail.txt contains the public key.

Change the owner of the private key to opendkim:

sudo chown opendkim:opendkim mail.private

Add the public key to the domain’s DNS records

Open mail.txt:

sudo nano -$ mail.txt

The public key is defined under the p parameter. Do not use the example key below, it’s only an illustration and will not work on your server.

mail._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5N3lnvvrYgPCRSoqn+awTpE+iGYcKBPpo8HHbcFfCIIV10Hwo4PhCoGZSaKVHOjDm4yefKXhQjM7iKzEPuBatE7O47hAx1CJpNuIdLxhILSbEmbMxJrJAG0HZVn8z6EAoOHZNaPHmK2h4UUrjOG8zA5BHfzJf7tGwI+K619fFUwIDAQAB" ; ----- DKIM key mail for example.com

Copy that key and add a TXT record to your domain’s DNS entries:

Name: mail._domainkey.example.com.

Text: "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5N3lnvvrYgPCRSoqn+awTpE+iGYcKBPpo8HHbcFfCIIV10Hwo4PhCoGZSaKVHOjDm4yefKXhQjM7iKzEPuBatE7O47hAx1CJpNuIdLxhILSbEmbMxJrJAG0HZVn8z6EAoOHZNaPHmK2h4UUrjOG8zA5BHfzJf7tGwI+K619fFUwIDAQAB"

Please note that the DNS changes may take a couple of hours to propagate.

Restart Postfix and OpenDKIM:

sudo service postfix restart
sudo service opendkim restart

Congratulations! You have successfully configured DKIM for your mail server!

The configuration can be tested by sending an empty email to check-auth@verifier.port25.com and a reply will be received. If everything works correctly you should see DKIM check: pass under Summary of Results.

==========================================================
Summary of Results
==========================================================
SPF check:          pass
DomainKeys check:   neutral
DKIM check:         pass
Sender-ID check:    pass
SpamAssassin check: ham

Alternatively, you can send a message to a Gmail address that you control, view the received email’s headers in your Gmail inbox, dkim=pass should be present in the Authentication-Results header field.

Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of contact@example.com designates --- as permitted sender) smtp.mail=contact@example.com;
       dkim=pass header.i=@example.com;

<div class=“author”>Submitted by: P. Sebastian</a></div>

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Category:
Tutorial

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I went over this again and again and still get: DKIM check: neutral Can you update the pictures with new links? This might help. Thank you.

alexdo
Site Moderator
Site Moderator badge
January 8, 2025

Heya, @sianios

Keep in mind that DNS changes might take up to 48 hours in order to update. This is mainly due to DNS cache and general propagation DNS time.

Regards

Hi. how to pass “DomainKeys check” ?

Please refer to my recent response to “Jon” (in this same thread), regarding DomainKeys authentication deprecation.

-xxar

alexdo
Site Moderator
Site Moderator badge
January 30, 2025

DomainKeys (DK) is an old and obsolete email authentication method that was replaced by DKIM (DomainKeys Identified Mail).

If your DKIM check passes, you can ignore the “DomainKeys check” result in tools like check-auth@verifier.port25.com or mail-tester.com.

Regards

Hey, I followed your article to a tee, but am still having some problems. Also, I am performing these steps on Ubuntu 14.04.

Everything seems perfect, but I got the two following errors from opendkim that I can’t figure out the fix for:

opendkim[8078]: AC355401B9: SSL error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long opendkim[8078]: AC355401B9: dkim_eom(): resource unavailable: d2i_PrivateKey_bio() failed

My searches suggest that the problem may be with the cert itself so I re-did that step slowly (including the updated TXT record), but I still get the errors. I also thought maybe it was a simple permissions issue with opendkim reading the cert itself, but after chown -R opendkim:opendkim /etc/opendkim it still didn’t work.

Thank you for getting me this far, if you have further insight, please help.

alexdo
Site Moderator
Site Moderator badge
January 8, 2025

SSL error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long

This error suggests that OpenDKIM is trying to read a file that is either corrupted, not in the correct format, or not what it expects (e.g., a private key instead of a certificate or vice versa).

resource unavailable: d2i_PrivateKey_bio() failed

This error indicates that OpenDKIM is unable to load the private key, likely because the file is invalid or unreadable.

The private key must be in PEM format. You can verify this by checking the file:

cat /etc/opendkim/keys/yourdomain.private

It should start with:

-----BEGIN PRIVATE KEY-----

or:

-----BEGIN RSA PRIVATE KEY-----

If the file doesn’t look right, regenerate the key using:

opendkim-genkey -s selector -d yourdomain.com

Replace selector with your DKIM selector and yourdomain.com with your domain.

Regards

I solved the problem that I was having. The formatting of the tutorial was the problem. In the section where you create the KeyTable the formatting makes it appear that this stanza is on two lines instead of one:

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

By joining those lines together with a space between them, everything finally worked as expected.

It was quite satisfying to see the dkim=pass!

Thanks for the howto!

alexdo
Site Moderator
Site Moderator badge
January 11, 2025

Heya,

I’m glad that you’ve sorted this! Adding the public DKIM record can sometimes be tricky and different providers might have an alternative way of joing long CNAME and TXT records.

Regards

Hi, I receive error:

sudo apt-get install opendkim opendkim-tools Reading package lists… Done Building dependency tree Reading state information… Done E: Unable to locate package opendkim E: Unable to locate package opendkim-tools

can you consult? thank you.

alexdo
Site Moderator
Site Moderator badge
January 8, 2025

You can ensure that the universe repository is enabled, as opendkim resides there. To check and enable:

sudo add-apt-repository universe sudo apt update

After updating and verifying your repositories, install the packages:

sudo apt install opendkim opendkim-tools

Hope that this helps!

ournet.biz, I remember that error of “Unable to locate package opendkim” happens because you have not ran the “apt-get update” before starting with the install option. Try and see…

alexdo
Site Moderator
Site Moderator badge
January 8, 2025

You can ensure that the universe repository is enabled, as opendkim resides there. To check and enable:

sudo add-apt-repository universe sudo apt update

After updating and verifying your repositories, install the packages:

sudo apt install opendkim opendkim-tools

Hope that this helps!

Hello, im getting this:

========================================================== Summary of Results

SPF check: pass DomainKeys check: neutral DKIM check: pass DKIM check: pass Sender-ID check: pass SpamAssassin check: ham

But my email is still being flagged as spam on gmail, what is wrong?

how did you solve this? got the same now

I have the same too!

alexdo
Site Moderator
Site Moderator badge
January 8, 2025

Even if your email passes SPF, DKIM, and SpamAssassin checks, Gmail has a sophisticated spam detection system that evaluates multiple factors beyond these checks.

You can use sites like https://www.mail-tester.com/ to check the overall score of your outgoing emails. The site will return result with recommended actions which you can implement to increase the score of your emails.

Also you can set up a Gmail Postmaster account (https://postmaster.google.com/) to monitor your domain’s reputation and receive feedback on deliverability issues.

Hope that this helps!

Some webhosters don’t allow to add capital letters in the IN TEXT field, they automatically change every letter to lowercase, so it will be difficult to enter the base64-encoded Key, it will look like:

mail._domainkey in txt "v=dkim1; k=rsa; p=migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqc5n3lnvvrygpcrsoqn+awtpe+igyckbppo8hhbcffciiv10hwo4phcogzsakvhojdm4yefkxhqjm7ikzepubate7o47hax1cjpnuidlxhilsbembmxjrjag0hzvn8z6eaoohznaphmk2h4uurjog8za5bhfzjf7tgwi+k619ffuwidaqab" ; ----- dkim key mail for example.com

Which will not be the correct key. You have to contact your webhoster then to change the interface.

You can check if you Key is valid with: http://dkimcore.org/tools/keycheck.html

alexdo
Site Moderator
Site Moderator badge
January 11, 2025

Heya,

Use the DKIM Core Key Checker to test your key before submission:

  • Enter your domain and selector (e.g., mail._domainkey.example.com).
  • Paste the DKIM record.
  • Confirm it’s valid before proceeding.

Also If your hosting platform supports splitting TXT records, divide the DKIM key into smaller chunks (less common but worth trying). For example:

mail._domainkey IN TXT "v=DKIM1; k=rsa; p=migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqc5n3lnvvrygpcrsoqn+" 
"awtpe+igyckbppo8hhbcffciiv10hwo4phcogzsakvhojdm4yefkxhqjm7ikzepu"
"bate7o47hax1cjpnuidlxhilsbembmxjrjag0hzvn8z6eaoohznaphmk2h4uurjog"
"8za5bhfzjf7tgwi+k619ffuwidaqab"

This method preserves the case while adhering to the host’s limitations. Ensure the platform supports this.

Regards

If my mail server is sub.domain.com, is it still safe to replace all example.com with sub.domain.com in the tutorial?

My DKIM is still showing neutral.

same here! i have a domain.com hosted on bluehost and subdomain.domain.com poting A to the serveer. how should i installl in this case?

alexdo
Site Moderator
Site Moderator badge
January 30, 2025

Yes, if your mail server is sub.domain.com, you should replace example.com with sub.domain.com in most cases. However, there are some important exceptions where you still need to use domain.com instead of sub.domain.com.

  • DO NOT use sub.domain.com here.
  • The DKIM record should be at the root domain (domain.com), not your mail server subdomain.
mail._domainkey.domain.com  TXT  "v=DKIM1; k=rsa; p=MIGfMA0G..."
  • Your SPF and DMARC policies should be for domain.com, not sub.domain.com.
  • SPF Record (✅ Correct)
domain.com  TXT  "v=spf1 mx ~all"
  • DMARC Record
_dmarc.domain.com  TXT  "v=DMARC1; p=reject; rua=mailto:postma

Regards

Do you have more info on config to pass **DomainKeys **test?

DomainKeys != DKIM.

DomainKeys authentication is deprecated: DKIM is the successor to DomainKeys.

Trying to “pass” the DomainKeys component of the check recommended in this guide (provided by check-auth@verifier.port25.com), is absolutely unnecessary.

If you see “DKIM check: pass” in the authentication report, then you’re good.

-xxar

alexdo
Site Moderator
Site Moderator badge
January 30, 2025

You’re absolutely right! DomainKeys (DK) is an old, deprecated authentication method, and DKIM has fully replaced it.

There’s no need to worry about passing the DomainKeys check when verifying email authentication.

Regards

alexdo
Site Moderator
Site Moderator badge
January 30, 2025

While DKIM has largely replaced DomainKeys, some older systems (or specific mail servers) may still check for it.

  1. Create a directory for the key:
sudo mkdir -p /etc/opendkim/keys/example.com cd /etc/opendkim/keys/example.com
  1. Generate a private and public key for DomainKeys (not DKIM!):
opendkim-genkey -b 1024 -s domainkeys -d example.com -D /etc/opendkim/keys/example.com
  • This will create:
  • domainkeys.privatePrivate key (kept on the mail server)
  • domainkeys.txtPublic key (added to DNS)
  1. Open the domainkeys.txt file:
cat /etc/opendkim/keys/example.com/domainkeys.txt

You’ll see something like:

domainkeys._domainkey.example.com. IN TXT "k=rsa; p=MIGfMA0G...QAB"
  1. Go to your DNS provider (DigitalOcean, Cloudflare, etc.) and create a TXT record:
  • Name: domainkeys._domainkey
  • Type: TXT
  • Value: k=rsa; p=MIGfMA0G...QAB (from the file)

Regards

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.