How to Configure Postfix with DKIM to Sign Emails from Any Domain on Ubuntu


2 views

When running an email service that handles multiple client domains, the standard DKIM setup fails because:

  1. Gmail and other providers validate DKIM signatures against the From: domain
  2. Traditional configs only sign for your primary domain's DNS records
  3. Postfix's default DKIM implementation doesn't handle dynamic selector generation

We need three key components working together:

Postfix → OpenDKIM → Dynamic DNS Records

1. Modify OpenDKIM Configuration

Edit /etc/opendkim.conf:

# KeyTable and SigningTable need to be files (not regex)
KeyTable           /etc/opendkim/keytable
SigningTable       /etc/opendkim/signingtable

# Enable loose signing mode
RequireSafeKeys    no
ExternalIgnoreList refile:/etc/opendkim/trustedhosts
InternalHosts      refile:/etc/opendkim/trustedhosts

2. Create Dynamic Key Management Files

/etc/opendkim/keytable:

# Format: domain selector:path/to/key
* default:/etc/opendkim/keys/default.private
client1.com client1:/etc/opendkim/keys/client1.private
client2.net client2:/etc/opendkim/keys/client2.private

/etc/opendkim/signingtable:

# Wildcard catch-all first
* default
# Then specific domains
@client1.com client1
@client2.net client2

3. Generate DKIM Keys for Each Domain

For each client domain:

opendkim-genkey -b 2048 -s client1 -d client1.com
mv client1.private /etc/opendkim/keys/
chown opendkim:opendkim /etc/opendkim/keys/client1.*

4. Configure Postfix Integration

Edit /etc/postfix/main.cf:

# DKIM milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

For a newsletter service, you'll need a script to handle new clients:

#!/bin/bash
# add_dkim_client.sh
DOMAIN=$1
SELECTOR="s${RANDOM}"

opendkim-genkey -b 2048 -s $SELECTOR -d $DOMAIN
mv $SELECTOR.private /etc/opendkim/keys/$SELECTOR.private
chown opendkim:opendkim /etc/opendkim/keys/$SELECTOR.private

echo "$DOMAIN $SELECTOR:/etc/opendkim/keys/$SELECTOR.private" >> /etc/opendkim/keytable
echo "@$DOMAIN $SELECTOR" >> /etc/opendkim/signingtable

systemctl restart opendkim postfix

echo "DKIM record for DNS (TXT):"
cat $SELECTOR.txt

Use these commands to test your setup:

# Verify OpenDKIM is running
sudo systemctl status opendkim

# Test email signing
echo "Test message" | mail -s "DKIM Test" -a "From: test@clientdomain.com" recipient@example.com

# Verify DKIM signature (on receiving server)
apt install opendkim-tools
opendkim-testkey -d clientdomain.com -s client1 -k /etc/opendkim/keys/client1.private
  • DNS Propagation: New TXT records may take 24-48 hours
  • Key Permissions: Ensure opendkim user can read private keys
  • Selector Mismatch: The signing table must match the key table exactly
  • SPF Alignment: Combine with proper SPF records for DMARC compliance

For high-volume services:

  1. Implement a Redis cache for key lookups
  2. Use a database-backed signing table instead of flat files
  3. Monitor signing failures with opendkim-stats
  4. Rotate keys quarterly using your automation script

Remember to update your DNS records whenever adding new client domains or rotating keys. Each client will need to add the generated DKIM TXT record to their domain's DNS.


When setting up DKIM for a multi-tenant email service, we need the server to properly sign messages regardless of the sender's domain in the From header. The default configuration typically only signs emails matching the server's primary domain.

First, edit the main DKIM configuration file:


# /etc/dkim-filter.conf
Domain *
KeyFile /etc/dkimkeys/%d/mail.private
Selector mail
Socket inet:8891@localhost

Then modify the Postfix configuration:


# /etc/postfix/main.cf
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

For each client domain, you'll need to create a TXT record:


mail._domainkey.clientdomain.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."

Here's a bash script to generate keys for new domains:


#!/bin/bash
DOMAIN=$1
mkdir -p /etc/dkimkeys/$DOMAIN
cd /etc/dkimkeys/$DOMAIN
openssl genrsa -out mail.private 1024
openssl rsa -in mail.private -out mail.public -pubout -outform PEM

To test your configuration:


telnet localhost 25
EHLO example.com
MAIL FROM:<test@clientdomain.com>
RCPT TO:<check-auth@verifier.port25.com>
DATA
Subject: DKIM Test
From: Test User <test@clientdomain.com>
To: Tester <check-auth@verifier.port25.com>
This is a test message
.

If verification fails:

  1. Check DNS propagation with dig TXT mail._domainkey.clientdomain.com
  2. Verify the private key matches the public key in DNS
  3. Ensure proper permissions on key files (600)
  4. Check mail logs: tail -f /var/log/mail.log