Back to tutorials
Tutorial

DMARC setup tutorial: Configure SPF, DKIM, and DMARC for a VPS mail server (2026)

DMARC setup tutorial for 2026: publish SPF/DKIM/DMARC, enable reports, and stop spoofing for VPS email safely.

By Anurag Singh
Updated on Jul 31, 2026
Category: Tutorial
Share article
DMARC setup tutorial: Configure SPF, DKIM, and DMARC for a VPS mail server (2026)

Email spoofing usually isn’t a “server got owned” problem. It’s a policy problem. Your domain has no DMARC record (or it has a messy one). That makes it easy for anyone to send mail that looks like it came from you.

This DMARC setup tutorial walks through a safe rollout for a VPS mail setup. You’ll publish SPF and DKIM first. Then you’ll add DMARC with reporting. Finally, you’ll enforce DMARC in stages without cutting off legitimate mail.

These steps work whether you send mail from a VPS (Postfix/Exim), a control panel like cPanel, or a hosted SMTP relay. The DNS work is the same.

If you build mail stacks for clients, get this process right once. Then reuse the checklist on every new domain.

What you’ll set up (and why the order matters)

DMARC sits on top of SPF and DKIM. If SPF or DKIM don’t align with the visible From: domain, DMARC fails. That can happen even when messages “deliver fine” today.

  • SPF tells receivers which servers are allowed to send for your domain (MAIL FROM / Return-Path).
  • DKIM cryptographically signs messages so receivers can verify they weren’t altered.
  • DMARC tells receivers what to do when SPF/DKIM don’t align with your From domain, and where to send reports.

Rollout order in this tutorial:

  1. Inventory your senders (so you don’t accidentally block your own mail).
  2. Publish/validate SPF.
  3. Enable DKIM signing (or verify it’s already enabled).
  4. Publish DMARC in monitor mode (p=none) and collect reports.
  5. Move to quarantine/reject in steps, with tight alignment and a fallback plan.

Prerequisites: access, tools, and a quick sender inventory

You’ll need DNS edit access for the domain (registrar or DNS provider). You’ll also need a way to view full headers on a test message.

If mail runs on a VPS, shell access makes validation and troubleshooting much easier.

If you want the admin side to stay predictable, start with a HostMyCode VPS sized for mail workload (CPU for spam filtering, disk for logs and queues).

If you’d rather avoid maintaining Exim/Postfix configs long-term, managed VPS hosting can keep patching and deliverability maintenance from turning into a weekly project.

Step 1: list every place that sends mail as your domain

Before you touch DNS, list every sender that uses your domain in the From address:

  • Your VPS mail server (Postfix or Exim/cPanel)
  • Website app mail (WordPress, forms, WooCommerce)
  • Transactional providers (SMTP relay, helpdesk, CRM)
  • Marketing providers (newsletters)
  • Any third-party sending on behalf of subdomains (e.g., billing.example.com)

If you’re not sure what’s in play, search your inbox for messages from your domain. Note “mailed-by” and “signed-by”. In Gmail, open a message → “Show original”.

Step 2: install basic DNS query tools (VPS)

On Ubuntu/Debian:

sudo apt update
sudo apt install -y dnsutils

On AlmaLinux/Rocky/RHEL:

sudo dnf install -y bind-utils

We’ll use dig to confirm records after you publish them.

Publish SPF correctly (without the usual foot-guns)

SPF is a single TXT record at the root (and optionally on subdomains). Most SPF breakage comes from three issues:

  • multiple SPF TXT records
  • blowing past the 10-DNS-lookup limit
  • forgetting a legitimate sender

Step 3: check whether SPF already exists

dig +short TXT example.com

Look for a string starting with v=spf1.

If you find more than one SPF record, many receivers treat SPF as a “permerror” and effectively fail it.

Step 4: build an SPF record for your real senders

Common building blocks:

  • ip4:203.0.113.10 and ip6:... for your VPS public IPs
  • a and mx only if they truly represent senders
  • include:provider.example for SaaS senders (use their documented include)
  • -all once you’re confident; start with ~all if you’re still discovering senders

Example SPF (single VPS IP + a relay include), conservative first pass:

example.com.  300  IN  TXT  "v=spf1 ip4:203.0.113.10 include:_spf.your-relay.example ~all"

After you’ve checked logs and DMARC reports, tighten to -all:

"v=spf1 ip4:203.0.113.10 include:_spf.your-relay.example -all"

Step 5: validate SPF lookups and propagation

dig +short TXT example.com | tr -d '"'

Operational checklist for SPF:

  • Exactly one SPF record per hostname.
  • Stay under 10 DNS lookups (each include, a, mx, ptr, exists can add lookups).
  • Keep TTL low during rollout (e.g., 300 seconds), then raise later (e.g., 3600–14400).

If you also send from a subdomain (like mail.example.com or news.example.com), publish SPF there too.

DMARC alignment is about the From domain, not necessarily the envelope sender. Decide up front how you want subdomains handled.

Enable DKIM signing (cPanel/WHM and Postfix/OpenDKIM paths)

SPF alone doesn’t carry modern deliverability. DKIM adds an authentication signal that often survives forwarding.

SPF frequently won’t.

Step 6A: cPanel/WHM — confirm DKIM is enabled and published

In WHM:

  1. EmailEmail Authentication
  2. Make sure DKIM shows as enabled for the domain
  3. Confirm the suggested DKIM TXT record exists in DNS

If you want the control-panel workflow end-to-end (mail + DNS), use: cPanel mail server setup guide.

Step 6B: Postfix on a VPS — set up OpenDKIM (quick, practical version)

If you run Postfix directly, OpenDKIM is the common choice.

On Ubuntu 24.04/26.04-era builds in 2026, the package names and paths below are stable.

Install packages:

sudo apt update
sudo apt install -y opendkim opendkim-tools postfix

Create a key directory (one domain example):

sudo mkdir -p /etc/opendkim/keys/example.com
sudo chown -R opendkim:opendkim /etc/opendkim/keys
sudo chmod 700 /etc/opendkim/keys/example.com

Generate a 2048-bit key (safe default for 2026):

sudo -u opendkim opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s s1 -v
sudo mv /etc/opendkim/keys/example.com/s1.private /etc/opendkim/keys/example.com/s1.key

Create (or update) these mapping files:

sudo tee /etc/opendkim/KeyTable >/dev/null <<'EOF'
s1._domainkey.example.com example.com:s1:/etc/opendkim/keys/example.com/s1.key
EOF

sudo tee /etc/opendkim/SigningTable >/dev/null <<'EOF'
*@example.com s1._domainkey.example.com
EOF

sudo tee /etc/opendkim/TrustedHosts >/dev/null <<'EOF'
127.0.0.1
localhost
::1
# Add your server IP if needed
EOF

Edit /etc/opendkim.conf (key lines):

Syslog                  yes
UMask                   002
Canonicalization        relaxed/simple
Mode                    sv
SubDomains              no
AutoRestart             yes
AutoRestartRate         10/1h
Socket                  inet:12301@localhost
KeyTable                /etc/opendkim/KeyTable
SigningTable            refile:/etc/opendkim/SigningTable
ExternalIgnoreList      /etc/opendkim/TrustedHosts
InternalHosts           /etc/opendkim/TrustedHosts

Connect Postfix to OpenDKIM by editing /etc/postfix/main.cf:

milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

Restart services:

sudo systemctl restart opendkim
sudo systemctl restart postfix
sudo systemctl enable opendkim

Step 7: publish the DKIM DNS record

Print the TXT record value from the generated s1.txt file:

sudo cat /etc/opendkim/keys/example.com/s1.txt

You’ll publish it as a TXT record at:

  • s1._domainkey.example.com → TXT → v=DKIM1; k=rsa; p=...

Verify it:

dig +short TXT s1._domainkey.example.com

DKIM operational notes:

  • Use simple selectors (s1, s2). You’ll rotate later without downtime.
  • Don’t reuse DKIM private keys across unrelated domains.
  • If you’re planning rotations, keep this handy: DKIM key rotation tutorial.

DMARC setup tutorial: publish a monitor-only policy first

With SPF and DKIM in place, you can publish DMARC.

Start with p=none. This lets you see who’s sending as your domain before you tell receivers to quarantine or reject.

Step 8: create DMARC record with reporting

DMARC is a TXT record at _dmarc.example.com. Start with:

_dmarc.example.com. 300 IN TXT "v=DMARC1; p=none; adkim=s; aspf=s; pct=100; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensics@example.com; fo=1"

Field choices explained (briefly, but practically):

  • p=none: monitor only.
  • adkim=s, aspf=s: strict alignment. This blocks more spoofing. It also exposes sloppy sender setups. If you rely on lots of third-party senders, start relaxed (r) and tighten later.
  • rua: aggregate reports (XML). Use a dedicated mailbox.
  • ruf: forensic reports (not all receivers send these; privacy policies vary). Optional.
  • fo=1: request failure reports when either SPF or DKIM fails (where supported).

Mailbox warning: DMARC aggregate reports add up fast.

If you manage multiple domains, use per-domain addresses or plus-addressing so you can filter cleanly.

Step 9: verify DMARC in DNS

dig +short TXT _dmarc.example.com

You want exactly one DMARC record. Multiple DMARC records can trigger a “permerror”.

Step 10: send a test message and check authentication results

Send an email from your domain to a Gmail or Outlook mailbox. Then inspect headers.

You’re looking for something like:

Authentication-Results: ...
  spf=pass ...
  dkim=pass ...
  dmarc=pass ...

If DMARC fails, the culprit is usually alignment. It’s usually not “DNS is broken”.

Common causes:

  • From domain is example.com but DKIM signs as mail.example.net (misalignment).
  • SPF passes for the server’s HELO domain but not for the envelope sender domain.
  • A third-party service sends with your From domain, but you didn’t add their SPF include and/or DKIM setup.

Move from monitor to enforcement (without breaking customer mail)

Leave monitor mode running long enough to get a real picture.

Busy domains usually show clear patterns within 24–72 hours. Quiet domains may need closer to a week.

Step 11: fix the “unknown senders” before enforcing

As reports arrive, focus on legitimate sources that fail SPF/DKIM.

For each sender, pick one path:

  • Add it to SPF (carefully, avoiding lookup explosion)
  • Configure it to DKIM-sign with your domain (preferred)
  • Move that sender to a subdomain and set separate DMARC there

If you run cPanel mail, keep reputation issues from piling up. Set PTR/rDNS and match it to your mail hostname.

That’s not DMARC, but it affects inbox placement and hard rejections.

Use: rDNS setup guide.

Step 12: switch to quarantine gradually

Update DMARC to quarantine a small percentage first:

"v=DMARC1; p=quarantine; pct=25; adkim=s; aspf=s; rua=mailto:dmarc-reports@example.com"

Then move to pct=50, then pct=100 over several days.

If you see unexpected failures, roll back to p=none while you fix SPF/DKIM alignment.

Step 13: move to reject once you’re stable

Final enforcement (typical end state):

"v=DMARC1; p=reject; pct=100; adkim=s; aspf=s; rua=mailto:dmarc-reports@example.com"

Practical tip for resellers: strict alignment can turn into support tickets. This happens when clients send through random SMTP plugins.

Standardize outbound mail (server mail or a relay). Document the standard. Then enforce it.

Common troubleshooting: DMARC fails even though SPF and DKIM “pass”

This is common. A raw “pass” doesn’t guarantee DMARC passes.

DMARC requires alignment with the From domain.

Check 1: DKIM d= domain matches your From domain

In headers, find:

DKIM-Signature: ... d=example.com; s=s1; ...

If d= isn’t your From domain (or an aligned domain under relaxed rules), DMARC fails even if DKIM technically passes.

Check 2: SPF passes for the envelope sender domain

SPF is evaluated against the Return-Path / MAIL FROM domain, not the visible From.

DMARC then checks whether that SPF domain aligns with the From domain (based on aspf).

Check 3: forwarding and mailing lists

Forwarding often breaks SPF because the forwarder’s IP isn’t in your SPF record.

DKIM usually survives if the forwarder doesn’t modify the message.

Mailing lists frequently rewrite headers or the body. That can break DKIM.

If your users rely on mailing lists, start with relaxed alignment (adkim=r; aspf=r). Watch reports before switching to strict.

Check 4: DNS split-brain or wrong nameservers

Confirm you’re editing the same DNS zone the domain actually delegates to.

A lot of “DMARC doesn’t work” cases come down to updating records in the wrong provider dashboard.

If you run your own DNS on a hosting server, double-check delegation and glue records. Pair this with: cPanel nameserver setup guide.

Hardening checklist for a mail VPS (small changes, big impact)

DMARC helps receivers trust your mail. Your server still needs basic hygiene. Without it, you’ll run into rate limits, filtering, and blacklists.

  • Open only required ports (25, 465/587 if you offer submission, 143/993 for IMAP if hosted). Audit before tightening: firewall audit tutorial.
  • TLS certificates for SMTP/IMAP: keep them valid and auto-renewing. Use: SSL certificate deployment tutorial.
  • Correct hostname + rDNS: match PTR to your mail hostname and make sure forward DNS matches back.
  • Log visibility: don’t troubleshoot deliverability blind. Set up basic monitoring and alerts.

If you’re rolling out SPF/DKIM/DMARC for one domain or fifty, stability matters more than clever config. Run it on a HostMyCode VPS, or hand off patching and mail stack upkeep to managed VPS hosting so you can spend your time on deliverability and client ops—not queue triage and TLS renewals.

FAQ: DMARC rollout questions you’ll hit in real hosting work

Should I start DMARC with p=none or go straight to reject?

Start with p=none unless you’re 100% sure all legitimate mail is SPF/DKIM-aligned. Monitor reports, then enforce in steps.

Do I need DKIM if SPF already passes?

Yes. SPF breaks on forwarding and doesn’t protect message integrity. DKIM gives a second independent signal, and DMARC can pass via DKIM even when SPF fails.

What’s a safe DMARC policy for a small business domain?

A common path is p=none for monitoring, then p=quarantine with pct=25, then pct=100, then p=reject once reports are clean.

Can I use different DMARC policies for subdomains?

Yes. Either publish DMARC at the subdomain’s _dmarc.sub.example.com, or use sp= in the organizational DMARC record to set a default for subdomains.

My DMARC reports show lots of unknown sources. What should I do first?

Confirm they’re actually sending mail with your From domain (not just failing attempts), then fix alignment: add the sender to SPF and/or configure DKIM signing for your domain. Don’t jump to reject until the legitimate sources are clean.

Summary: a repeatable DMARC rollout you can support

DMARC isn’t a single TXT record you toss into DNS and forget. Treat it like a controlled change.

Inventory senders, validate SPF, enable DKIM, publish DMARC in monitor mode, then enforce using real report data.

If you want this to stay calm across domains and client accounts, run mail on infrastructure you can depend on. HostMyCode gives you a clean base with HostMyCode VPS options and operational help through managed VPS hosting when you’d rather not babysit mail queues and certificate renewals.