How to Set Up DKIM for Your Domain (Step-by-Step)
DomainKeys Identified Mail is the most resilient signal in the email authentication stack. It uses asymmetric cryptography to prove that a message was signed by someone in possession of your domain's private key and that nothing in the body has changed since then. Below is the deployment we use ourselves, condensed into a working playbook.
What DKIM does in one paragraph
Defined in RFC 6376, DKIM attaches a cryptographic signature to every outbound message. The signature is computed across a chosen set of headers and the body using a private key that lives only on the sending server. The matching public key is published as a DNS record. When a receiving server picks up the message, it fetches the public key, runs the verification, and concludes one of two things:
- Pass — the signer held the private key and the body has not been altered since signing.
- Fail — the signature is invalid. Either the body was modified, the headers were rewritten, or the published key is wrong.
Unlike SPF, the DKIM signature travels with the message. It survives ordinary forwarding, which makes it the more reliable of the two authentication methods in the real world.
Step 1: generate the key pair
You need an RSA key. 2048 bits is the modern default; 1024-bit keys are still legal, but Google now warns about them in Postmaster Tools. Any Linux box with OpenSSL will do:
# Generate a 2048-bit private key
openssl genrsa -out dkim_private.pem 2048
# Extract the public key in DNS-friendly base64
openssl rsa -in dkim_private.pem -pubout -outform DER 2>/dev/null \
| openssl base64 -A
The second command prints a long base64 string. Copy it — you will paste it into the DNS record in a moment.
Step 2: pick a selector name
A selector is a short label that distinguishes one DKIM key from another for the same domain. Common conventions are default, mail, k1, or a date stamp like 2026q2. Date or revision-style selectors make rotation painless — you can publish a new key under a new name and switch over without affecting in-flight mail signed under the old one.
For this walkthrough we will use k1.
Step 3: publish the public key in DNS
The public key lives at {selector}._domainkey.{domain}. For our example that is k1._domainkey.example.com. Create a TXT record at that name with this value:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
Where the long string after p= is the base64 you just generated. Most modern DNS providers (Cloudflare, Route 53, OVH) automatically split the value across the 255-character TXT-segment boundary. If yours does not, break it manually into multiple quoted strings.
The tags inside the record
v=DKIM1— the version. Always exactly this.k=rsa— the algorithm.ed25519exists in the spec but receiver support is still patchy in 2026.p=...— the base64-encoded public key.t=y— (optional) testing flag. Receivers should not punish a verification failure. Useful while rolling out, but remove it before production.s=email— (optional) restrict the key to email signing only.
Step 4: teach your MTA to sign
Now point your outbound MTA at the private key file and tell it which selector to advertise. The configuration depends on the software you run.
Postfix with OpenDKIM
# /etc/opendkim.conf
Domain example.com
Selector k1
KeyFile /etc/opendkim/keys/k1.private
Socket inet:8891@localhost
Canonicalization relaxed/simple
SignatureAlgorithm rsa-sha256
# /etc/postfix/main.cf
milter_default_action = accept
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Exim
Exim signs natively in the SMTP transport:
remote_smtp:
driver = smtp
dkim_domain = example.com
dkim_selector = k1
dkim_private_key = /etc/exim/dkim/k1.private
dkim_canon = relaxed
dkim_strict = false
Hosted services (Google, Microsoft, SendGrid, Mailchimp)
If you send through a SaaS provider you typically do not generate the key yourself. The provider gives you a CNAME to publish, and the public key lives at the destination of that CNAME on their side. The upside is automatic rotation managed for you. The downside is you trust the vendor to actually rotate.
Step 5: verify on the receiving end
Send a message to a Gmail address and open it. From the three-dot menu pick "Show original." You should see something close to:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
d=example.com; s=k1; t=1714500000;
bh=eY4cR2qz7y0...; b=Vd9pCJrOtN...
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=k1
If dkim=pass appears, you are done. The common failure modes:
dkim=neutral (no key)— DNS is not propagated yet, or the selector path is wrong. Wait a few minutes and re-check.dkim=fail (body hash did not verify)— something is rewriting the body after signing. Mailing-list footer appenders and antivirus banners are the classic culprits.dkim=fail (signature did not verify)— the public key in DNS does not correspond to the private key the MTA is using. Re-export and re-publish.
Tools that earn their keep
- MXToolbox DKIM Lookup — pulls the published key and confirms it parses.
- mail-tester.com — gives you a one-time inbox to send to and returns a deliverability scorecard, including the DKIM result.
opendkim-testkey— ships with the OpenDKIM package and confirms the published key matches the local private key. Runopendkim-testkey -d example.com -s k1 -vvv.
Rotating keys
Best practice is a key rotation at least every six months — quarterly if your traffic volume is high enough to be interesting to attackers. Selector-based design makes rotation effectively free of risk: publish the new key under a new selector, configure the MTA to switch, wait a few days for queued mail to drain, then remove the old key. We cover the operational mechanics in our complete authentication stack guide.
Things that still go wrong in production
Even a clean configuration can fail in the wild. The cases we see most often:
- Mailing lists that strip the DKIM header or rewrite headers after signing — ARC was created to mitigate this, but coverage is uneven.
- Antivirus appliances that append a "scanned by..." footer after the message has been signed.
- Keys below 1024 bits, which Google and Microsoft now treat as no signature at all.
- Public keys published with literal newlines inside the value because the DNS provider stored them verbatim.
With those caveats accounted for, DKIM is the strongest authentication signal you can publish. Combine it with SPF and bind them with DMARC for a complete posture.