Set Up DKIM, SPF, DMARC on VPS to Stop Email Spoofing
DKIM, SPF, and DMARC are three email authentication standards that prevent your domain from being impersonated by attackers. If your VPS runs a mail server like Postfix, you must configure all three to stop spoofing, increase email deliverability, and ensure your messages land in the inbox instead of spam folders. Together, they create a robust authentication framework that receivers trust.
Install OpenDKIM
# Install OpenDKIM
sudo apt update
sudo apt install opendkim opendkim-tools libopendkim-perl -y
# Enable the service
sudo systemctl enable --now opendkim
# Check status
sudo systemctl status opendkim
Generate DKIM Key Pair
# Create keys directory
sudo mkdir -p /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys
sudo chmod 700 /etc/opendkim/keys
# Navigate to the directory
cd /etc/opendkim/keys
# Generate key pair for your domain (replace example.com)
sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys -s default -v
# Fix permissions
sudo chown opendkim:opendkim /etc/opendkim/keys/default.private
sudo chown opendkim:opendkim /etc/opendkim/keys/default.txt
Configure OpenDKIM
# Edit the main config file
sudo nano /etc/opendkim.conf
Add or modify these lines (adjust values to match your setup):
Domain example.com
KeyFile /etc/opendkim/keys/default.private
Selector default
Socket inet:8891@localhost
CanonicalHeadersOnly yes
Mode sv
SubDomains yes
Exit with Ctrl+X, then press Y to save.
Add DKIM DNS Record
View the public key that was generated:
sudo cat /etc/opendkim/keys/default.txt
The output looks like:
default._domainkey.example.com. IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkq..."
Log into your DNS control panel and add a TXT record for subdomain default._domainkey (or default._domainkey.example.com if your panel requires FQDN). Paste the value starting with v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkq.... Some panels only need the p= portion; check your provider's instructions.
Add SPF DNS Record
Add an SPF record to your domain root (not a subdomain) as a TXT record:
v=spf1 ip4:YOUR_VPS_IP -all
Replace YOUR_VPS_IP with your VPS IP address, e.g., v=spf1 ip4:203.0.113.5 -all.
If your VPS uses a mail relay or multiple servers:
v=spf1 ip4:203.0.113.5 ip4:203.0.113.10 mx -all
Add DMARC DNS Record
Create a DMARC record on your domain (subdomain _dmarc) as a TXT record:
v=DMARC1; p=quarantine; rua=mailto:[email protected]
The fields mean:
v=DMARC1— versionp=quarantine— policy (quarantine = move to spam if fails; none = report only; reject = block)rua=mailto:[email protected]— send aggregate reports to this email
For initial testing, use p=none first. After verifying that no legitimate emails fail, upgrade to p=quarantine or p=reject.
# Full version
v=DMARC1; p=quarantine; rua=mailto:[email protected]; ruf=mailto:[email protected]; fo=1
Verify That DKIM, SPF, DMARC Are Working Correctly
# Check DKIM public key
dig default._domainkey.example.com TXT
# Check SPF record
dig example.com TXT
# Check DMARC record
dig _dmarc.example.com TXT
# Test DKIM key loading
sudo opendkim-testkey -d example.com -s default
# View OpenDKIM logs
sudo journalctl -u opendkim -f
Send a test email to Gmail or Yahoo, then open it and select "Show original." Look for an Authentication-Results header that shows the results of DKIM, SPF, and DMARC checks:
Authentication-Results: gmail.com;
dkim=pass [email protected] header.s=default header.b=...;
spf=pass (google.com: domain of [email protected] designates 203.0.113.5 as permitted sender) [email protected];
dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=example.com
Common Issues & Troubleshooting
Error: "DKIM signature did not pass"
Your DNS record is incorrect, or the key pair doesn't match the configured keys.
# Test key loading and DNS match
sudo opendkim-testkey -d example.com -s default -vv
# If key mismatch, regenerate
cd /etc/opendkim/keys
sudo rm default.private default.txt
sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys -s default
sudo chown opendkim:opendkim default.private
# Copy the new public key from default.txt to DNS and wait for propagation
Error: "SPF: Too many DNS lookups"
Your SPF record includes too many mechanisms (limit is 10 DNS lookups).
# Check the SPF chain
dig example.com TXT +trace
# Simplify your SPF record, e.g.:
v=spf1 ip4:203.0.113.5 -all
# Instead of:
v=spf1 ip4:203.0.113.5 include:thirdparty.com include:another.com -all
Error: "DMARC alignment failure"
DKIM or SPF failed, or the domain in the From: header doesn't match the signing domain.
# Verify your From: header matches the DKIM-signed domain
# Verify SPF permits this server
dig example.com TXT
Error: "OpenDKIM failed to load key"
File permissions are wrong, or the config path is incorrect.
# Check permissions
ls -la /etc/opendkim/keys/default.private
# Should be opendkim:opendkim with mode 600
sudo chown opendkim:opendkim /etc/opendkim/keys/default.private
sudo chmod 600 /etc/opendkim/keys/default.private
# Restart OpenDKIM
sudo systemctl restart opendkim
Error: "SPF record return permerror"
Your SPF syntax contains errors or invalid CIDR notation.
# Verify SPF syntax with an online tool like mxtoolbox.com/spf.aspx
# Ensure correct format:
v=spf1 ip4:203.0.113.5/32 -all
# For IP ranges:
v=spf1 ip4:203.0.113.0/24 -all
Frequently Asked Questions
Do I have to set up all three: DKIM, SPF, and DMARC?
You don't need all three, but they are complementary. SPF provides basic spoofing prevention; DKIM cryptographically signs emails; DMARC tells receivers what to do if DKIM or SPF fails. Together, they provide the strongest authentication. Major email providers like Gmail and Yahoo require or strongly prefer all three.
How often do I need to rotate DKIM keys?
There's no hard requirement. DKIM keys can remain valid indefinitely. However, security best practice is to rotate keys every 1–2 years. You can add a new key to DNS alongside the old one, then retire the old key after a transition period.
Where do DMARC reports go?
DMARC aggregate reports (rua=) are sent daily to the email address you specify. Forensic reports (ruf=) are sent when an email fails DMARC alignment. These reports tell you how many emails pass or fail DKIM and SPF, and whether your domain is being impersonated. You can parse them to monitor email authentication health.