Back to blog

Networking

Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records

Full Postfix configuration walkthrough covering virtual domains, TLS encryption, OpenDKIM signing, SPF and DMARC DNS records, and spam filtering.

  • Linux
  • Postfix
  • SMTP
  • DKIM
  • SPF
  • DMARC
  • Networking

Reader map

Key points in Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records

Syntax first, runtime behavior second, migration cleanup last.

Read
16 min
Waypoints
8
Track
Networking
  1. 01
    Start here

    Postfix as an internet-facing SMTP server;

  2. 02
    Waypoint

    a safe non-open-relay baseline;

  3. 03
    Waypoint

    virtual alias domains backed by local files;

  4. 04
    Waypoint

    TLS for inbound SMTP and encrypted submission;

  5. 05
    Waypoint

    OpenDKIM signing through a Postfix milter;

  6. 06
    Waypoint

    SPF and DMARC records in DNS;

  7. 07
    Waypoint

    Rspamd as a spam filter through the milter interface;

  8. 08
    Migration check

    commands to test delivery, authentication, DNS, and logs.

SEO Metadata

SEO Title Options

  1. Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF
  2. Setting Up Postfix Mail Server on Linux: Practical 2026
  3. Networking Playbook: Setting Up Postfix Mail Server on

Meta Description Options

  1. Learn Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records with a practical Networking framework, expert mistakes, implementation steps.
  2. Full Postfix configuration walkthrough covering virtual domains, TLS encryption, OpenDKIM signing, SPF and DMARC DNS records, and spam filtering.

URL Slug

setting-up-postfix-mail-server-linux-smtp-dkim-spf-records

Focus Keyword

Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records

Additional LSI Keywords

  • Networking
  • Linux
  • Postfix
  • SMTP
  • DKIM
  • SPF
  • DMARC
  • Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records
  • production checklist
  • implementation guide
  • best practices
  • architecture decisions

Table of Contents

Article overview

Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records is the kind of topic that looks simple until it reaches production. Teams usually discover the real cost late: unclear boundaries, weak defaults, hidden maintenance work, and decisions that seemed harmless when the codebase was small.

The problem gets worse when the article, tutorial, or implementation guide only explains the happy path. This guide closes that gap with a practical framework, a comparison table, common mistakes, and a deep technical section you can use while planning real work.

Keep reading for the non-obvious part: the safest implementation is rarely the most impressive-looking one. It is the one your team can debug, test, document, and evolve without turning every future change into archaeology.

Key Takeaways

  • Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records should be evaluated as a production decision, not only as a syntax or tooling choice.
  • The best implementation keeps responsibilities visible, with clear ownership, tests, documentation, and rollback paths.
  • Search visibility improves when practical depth, structured answers, and expert examples live on the same page.

[IMAGE: A mobile-first technical article layout showing the main concept, decision table, implementation checklist, and FAQ blocks. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records expert guide for Networking]

What Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records means

Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records means applying networking knowledge to a concrete engineering decision, then turning that decision into reliable code, documentation, and operational behavior. In practice, it combines the topic's core concepts with trade-off analysis, implementation boundaries, testing strategy, and maintenance discipline.

This is the definition worth optimizing for featured snippets because it avoids hype. It tells the reader what the topic does and what a professional implementation must include.

Why it matters now

The technical web is more crowded than it was a few years ago. Thin tutorials can still get indexed, but they rarely earn trust from senior developers, buyers, AI answer systems, or teams that need production guidance.

For networking topics, the strongest content now has three layers:

  • a clear answer for fast scanning
  • a practical framework for implementation
  • expert context that explains what breaks later

That same structure helps search engines understand the page. It also helps readers decide whether the advice fits their project.

Implementation framework

Use this framework before adopting the approach described in this article.

  1. Define the user problem and the production risk.
  2. Identify the smallest reliable implementation boundary.
  3. Keep configuration, secrets, and environment-specific behavior outside the article's core logic.
  4. Add tests for the behavior that would hurt if it regressed.
  5. Document the trade-off, not only the final code.
  6. Measure the result with logs, metrics, or user-facing outcomes.
  7. Revisit the decision after real usage exposes edge cases.

The sequence is deliberately conservative. It keeps the work grounded in outcomes instead of novelty.

[IMAGE: A seven-step implementation framework with discovery, boundary design, configuration, tests, documentation, measurement, and iteration. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records implementation framework]

Practical comparison

Decision areaStrong approachWeak approachWhy it matters
ScopeSolve one clear problemMix unrelated concernsFocus improves testing and search intent
ArchitecturePut logic in explicit classes or documented boundariesHide behavior in templates or incidental callbacksFuture changes stay easier to review
Data flowPass prepared data into the view or endpointQuery or compute in presentation codeReduces regressions and performance surprises
TestingCover the risky behavior directlyTest only the happy pathCatches production failures earlier
DocumentationExplain trade-offs and limitsRepeat generic definitionsBuilds E-E-A-T and reader trust
OperationsTrack logs, metrics, and rollback stepsShip without measurementMakes the decision reversible

This table is intentionally practical. It gives a reviewer something to check before the implementation becomes expensive to change.

Expert workflow

Expert tip: "Treat Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records as a system boundary. If the next developer cannot find where the decision lives, how it is tested, and when it should be avoided, the implementation is not finished."

A useful workflow is simple:

  • Start with the smallest working example.
  • Add the constraints that exist in your real project.
  • Remove anything that only demonstrates cleverness.
  • Write down the failure modes.
  • Add links to related decisions so future readers can navigate the topic cluster.

That last point matters for both humans and search systems. A single article can answer a question; a cluster proves authority.

Common mistakes

Mistake 1: Copying a pattern without its context

A pattern that works in a small demo can fail in a real application. The missing context is usually data volume, team experience, deployment process, security requirements, or observability.

Before copying the pattern, ask what assumption made it safe in the original example.

Mistake 2: Putting business logic in the wrong layer

This is the fastest way to make future debugging expensive. In Laravel, PHP, and server-rendered websites, presentation should receive prepared data, not discover rules on its own.

Keep decision logic in models, actions, services, policies, requests, jobs, or documented helpers where it can be tested directly.

Mistake 3: Optimizing for novelty instead of maintainability

Newer tools and language features can be valuable. They can also hide simple behavior behind unfamiliar syntax.

Use the option that makes the next production incident easier to understand.

Mistake 4: Publishing without a measurement plan

If the article describes a performance, SEO, security, or architecture improvement, define how success will be checked. Logs, tests, crawl diagnostics, analytics, and user behavior are all stronger than assumptions.

[IMAGE: A common-mistakes board with context loss, wrong layer, novelty bias, and missing measurement highlighted. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records common mistakes]

Image placeholders

  • [IMAGE: A concept diagram for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records with input, decision boundary, implementation, tests, and production feedback. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records concept diagram]
  • [IMAGE: A mobile screenshot-style checklist for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records mobile checklist]
  • [IMAGE: A comparison table visualization for strong versus weak implementation choices. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records comparison table]

Video placeholder

[VIDEO: Insert a 5-8 minute YouTube walkthrough that demonstrates the main decision, the implementation boundary, the test strategy, and the production caveats for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records.]

Internal linking opportunities

Original Technical Deep Dive

The short version

Postfix is the SMTP server. It receives mail on port 25, sends mail to other MTAs, and accepts authenticated user submission on port 587 when you configure SASL.

A practical mail host looks like this:

internet MTAs -> port 25 Postfix smtpd -> local delivery or virtual alias routing
mail clients  -> port 587 Postfix submission -> authenticated outbound mail
Postfix       -> OpenDKIM milter -> DKIM signatures
Postfix       -> Rspamd milter -> spam scoring
DNS           -> MX, A, PTR, SPF, DKIM, DMARC

This guide configures:

  • Postfix as an internet-facing SMTP server;
  • a safe non-open-relay baseline;
  • virtual alias domains backed by local files;
  • TLS for inbound SMTP and encrypted submission;
  • OpenDKIM signing through a Postfix milter;
  • SPF and DMARC records in DNS;
  • Rspamd as a spam filter through the milter interface;
  • commands to test delivery, authentication, DNS, and logs.

This is not a full mailbox stack. If users need IMAP, POP3, server-side mailboxes, quotas, and password auth, add Dovecot or another mailbox service. Postfix alone is the MTA.

Confirm the prerequisites

Do not build a public mail server on a random residential IP. Before touching Postfix, confirm:

  • the server has a static public IP;
  • outbound port 25 is allowed by the provider;
  • inbound port 25 can reach the server;
  • the IP has clean reputation or no bad history;
  • you can set reverse DNS for the IP;
  • the hostname has a matching forward DNS record;
  • you can edit DNS TXT records for SPF, DKIM, and DMARC;
  • you have a real address for postmaster@your-domain.

Example names used below:

PurposeValue
Domainexample.com
Mail hostnamemail.example.com
Public IPv4203.0.113.10
DKIM selectormail2021
Admin mailboxadmin@example.com

Use your real domain and IPs. Do not publish documentation IPs.

Set DNS first

Create the forward DNS records:

mail.example.com.    300    IN    A      203.0.113.10
example.com.         300    IN    MX     10 mail.example.com.

If you use IPv6:

mail.example.com.    300    IN    AAAA   2001:db8:10::10

Ask your hosting provider or IP owner to set reverse DNS:

203.0.113.10 -> mail.example.com

You normally cannot set PTR records inside your domain zone unless you control the reverse zone for the IP range.

Verify:

dig +short A mail.example.com
dig +short MX example.com
dig +short -x 203.0.113.10

Expected:

203.0.113.10
10 mail.example.com.
mail.example.com.

Install Postfix

Debian or Ubuntu:

sudo apt update
sudo apt install -y postfix mailutils swaks openssl dnsutils ca-certificates

During the package prompt, choose:

Internet Site

Use:

mail.example.com

as the system mail name.

RHEL, Rocky Linux, AlmaLinux, or Fedora:

sudo dnf install -y postfix s-nail swaks openssl bind-utils ca-certificates
sudo systemctl enable --now postfix

Check the version and defaults:

postconf mail_version
postconf -n
sudo systemctl status postfix --no-pager

Back up the default config

Postfix configuration usually lives in:

/etc/postfix/main.cf
/etc/postfix/master.cf

Back it up:

sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.$(date +%F-%H%M%S).bak
sudo cp /etc/postfix/master.cf /etc/postfix/master.cf.$(date +%F-%H%M%S).bak

Check syntax before and after every change:

sudo postfix check

Configure the server identity

Edit:

sudoedit /etc/postfix/main.cf

Set the core identity and relay rules:

myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain

inet_interfaces = all
inet_protocols = ipv4

mydestination = $myhostname, localhost.$mydomain, localhost
mynetworks = 127.0.0.0/8
relay_domains =

smtpd_banner = $myhostname ESMTP
biff = no
append_dot_mydomain = no
readme_directory = no

smtpd_relay_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    defer_unauth_destination

smtpd_recipient_restrictions =
    reject_non_fqdn_recipient,
    reject_unknown_recipient_domain,
    permit

disable_vrfy_command = yes
smtpd_helo_required = yes

The important line is smtpd_relay_restrictions. It prevents your server from relaying mail for unauthenticated strangers.

[IMAGE: Supporting visual 1 for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records, showing Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records decisions, examples, and Linux, Postfix, SMTP. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records setting-up-postfix-mail-server-linux-smtp-dkim-spf-records visual 1]

[IMAGE: Supporting visual 1 for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records, showing Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records decisions, examples, and Linux, Postfix, SMTP. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records setting-up-postfix-mail-server-linux-smtp-dkim-spf-records visual 1]

If you support IPv6, use:

inet_protocols = all
mynetworks = 127.0.0.0/8 [::1]/128

Do not add office networks, VPN networks, or application subnets to mynetworks unless they are allowed to relay mail without SMTP authentication.

Reload:

sudo postfix check
sudo systemctl reload postfix

Open the firewall

For a public mail server, expose SMTP:

sudo ufw allow 25/tcp

Expose submission only if users or applications submit mail directly:

sudo ufw allow 587/tcp

If using firewalld:

sudo firewall-cmd --permanent --add-service=smtp
sudo firewall-cmd --permanent --add-service=submission
sudo firewall-cmd --reload

Check listeners:

sudo ss -tlnp | grep master

Test local SMTP before adding TLS

Send a local test:

printf 'Subject: local postfix test\n\nhello\n' | sendmail root

Check the queue:

mailq

Check logs:

journalctl -u postfix --since '10 minutes ago' --no-pager

On Debian-style systems, logs may also be in:

sudo tail -f /var/log/mail.log

On RHEL-style systems:

sudo tail -f /var/log/maillog

Test SMTP locally:

swaks --to postmaster@example.com --server 127.0.0.1 --from test@example.com

Do not continue until local delivery and logs are understandable.

Configure virtual alias domains

Virtual alias domains are useful when Postfix should accept addresses for one or more hosted domains and forward them to local users or real mailboxes.

This example accepts example.com and routes aliases through a local map. In main.cf:

virtual_alias_domains = example.com
virtual_alias_maps = hash:/etc/postfix/virtual

Create the map:

sudoedit /etc/postfix/virtual

Example:

postmaster@example.com    admin@example.com
abuse@example.com         admin@example.com
admin@example.com         localadmin
info@example.com          localadmin

Avoid catch-all aliases unless you have a clear reason. They attract spam and hide typo problems.

Build the lookup database:

sudo postmap /etc/postfix/virtual
sudo postfix check
sudo systemctl reload postfix

Test lookups:

postmap -q info@example.com hash:/etc/postfix/virtual
postmap -q postmaster@example.com hash:/etc/postfix/virtual

Expected:

localadmin
admin@example.com

If you need real per-domain mailboxes, use virtual_mailbox_domains and a mailbox delivery service such as Dovecot LMTP. Do not mix virtual alias routing and mailbox hosting without a clear address plan.

Add TLS certificates

Install a certificate for the mail hostname. With Certbot on a host that can answer HTTP validation:

sudo apt install -y certbot
sudo certbot certonly --standalone -d mail.example.com

On RHEL-style systems, install Certbot from the distribution or EPEL package source appropriate for your OS.

Configure Postfix TLS in main.cf:

smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes

smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_CApath = /etc/ssl/certs

Use may on port 25. Public SMTP delivery still needs opportunistic TLS because not every remote mail system can or will negotiate mandatory TLS.

Check and reload:

sudo postfix check
sudo systemctl reload postfix

Test STARTTLS:

openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com </dev/null

Look for:

Verify return code: 0 (ok)

Certificate renewal should reload Postfix after Certbot renews the certificate:

sudo systemctl reload postfix

Add that as a deploy hook if your Certbot package does not already handle service reloads.

Configure authenticated submission

Mail clients should not submit outbound mail through port 25. Use port 587 with TLS and SMTP authentication.

[IMAGE: Supporting visual 2 for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records, showing Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records decisions, examples, and Linux, Postfix, SMTP. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records setting-up-postfix-mail-server-linux-smtp-dkim-spf-records visual 2]

Postfix commonly delegates authentication to Dovecot. If you already run Dovecot, configure Postfix to use its auth socket:

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = no
smtpd_tls_auth_only = yes

Then enable the submission service in:

sudoedit /etc/postfix/master.cf

Use:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

Reload:

sudo postfix check
sudo systemctl reload postfix

Check the listener:

sudo ss -tlnp | grep ':587'

If you do not run an authentication provider, do not enable user submission. Keep the server receive-only or submit outbound application mail through a managed SMTP relay.

[IMAGE: Supporting visual 2 for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records, showing Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records decisions, examples, and Linux, Postfix, SMTP. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records setting-up-postfix-mail-server-linux-smtp-dkim-spf-records visual 2]

Install OpenDKIM

Debian or Ubuntu:

sudo apt install -y opendkim opendkim-tools

RHEL-compatible systems:

sudo dnf install -y opendkim opendkim-tools

Create a DKIM key:

sudo mkdir -p /etc/opendkim/keys/example.com
sudo opendkim-genkey \
  -b 2048 \
  -s mail2021 \
  -d example.com \
  -D /etc/opendkim/keys/example.com

sudo chown -R opendkim:opendkim /etc/opendkim/keys
sudo chmod 700 /etc/opendkim/keys/example.com
sudo chmod 600 /etc/opendkim/keys/example.com/mail2021.private

The generated files are:

/etc/opendkim/keys/example.com/mail2021.private
/etc/opendkim/keys/example.com/mail2021.txt

The .private file stays on the server. The .txt content becomes the public DNS record.

Configure OpenDKIM tables

Create trusted hosts:

sudoedit /etc/opendkim/trusted.hosts

Use:

127.0.0.1
::1
localhost
mail.example.com
example.com

Create the key table:

sudoedit /etc/opendkim/key.table

Use:

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

Create the signing table:

sudoedit /etc/opendkim/signing.table

Use:

*@example.com mail2021._domainkey.example.com

Configure OpenDKIM:

sudoedit /etc/opendkim.conf

Use this baseline:

Syslog                  yes
UMask                   002
Mode                    sv
Canonicalization        relaxed/simple
SubDomains              no
OversignHeaders         From

Socket                  inet:8891@127.0.0.1
UserID                  opendkim:opendkim

KeyTable                /etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table
ExternalIgnoreList      /etc/opendkim/trusted.hosts
InternalHosts           /etc/opendkim/trusted.hosts

Using a localhost TCP socket avoids common Postfix chroot socket path problems. A Unix socket is fine if you understand the Postfix chroot and permissions model.

Enable and start:

sudo systemctl enable --now opendkim
sudo systemctl status opendkim --no-pager
sudo ss -tlnp | grep 8891

Connect OpenDKIM to Postfix

Add the milter settings to main.cf:

milter_protocol = 6
milter_default_action = accept
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = inet:127.0.0.1:8891

Reload:

sudo postfix check
sudo systemctl reload postfix

Check active milter settings:

postconf -n | grep milter

If OpenDKIM is down, milter_default_action = accept lets mail continue without signing. Use tempfail only if unsigned outbound mail is worse for you than delayed mail.

Publish the DKIM DNS record

View the generated record:

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

Publish it as a TXT record:

mail2021._domainkey.example.com. 300 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."

Long TXT values may need to be split into multiple quoted strings in your DNS provider UI. The strings are concatenated by DNS clients.

Verify:

dig +short TXT mail2021._domainkey.example.com
sudo opendkim-testkey -d example.com -s mail2021 -vvv

Send a message out to an external mailbox and inspect headers:

DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=mail2021; ...
Authentication-Results: ... dkim=pass ...

Publish SPF

SPF authorizes the SMTP envelope domain and HELO identity. Publish it at the domain itself as a TXT record:

example.com. 300 IN TXT "v=spf1 mx ip4:203.0.113.10 -all"

If you send through a third-party relay too:

example.com. 300 IN TXT "v=spf1 mx ip4:203.0.113.10 include:_spf.provider.example -all"

Rules:

  • publish one SPF record per name;
  • keep it small;
  • avoid stacking many include: mechanisms;
  • use ~all while testing only if you need a soft rollout;
  • use -all after you know every legitimate sender is covered.

Verify:

dig +short TXT example.com | grep 'v=spf1'

Publish DMARC

DMARC ties SPF and DKIM to the visible From: domain and tells receivers what policy you want.

[IMAGE: Supporting visual 3 for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records, showing Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records decisions, examples, and Linux, Postfix, SMTP. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records setting-up-postfix-mail-server-linux-smtp-dkim-spf-records visual 3]

Start with monitoring:

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

After reports show legitimate mail passing alignment, move in stages:

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

Then:

_dmarc.example.com. 300 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@example.com; adkim=s; aspf=s"

Verify:

dig +short TXT _dmarc.example.com

Use a real mailbox or report processor for rua. DMARC aggregate reports are XML files sent by receivers; they are not useful if nobody parses them.

Add basic spam filtering with Rspamd

Postfix should reject obvious protocol abuse, but content scoring belongs in a filter. Rspamd integrates cleanly through the milter protocol.

Debian or Ubuntu:

sudo apt install -y rspamd redis-server
sudo systemctl enable --now redis-server rspamd

RHEL-compatible systems vary by repository. Use the distribution-supported Rspamd package source, then enable the service:

sudo systemctl enable --now rspamd

Set conservative thresholds:

sudo mkdir -p /etc/rspamd/local.d
sudoedit /etc/rspamd/local.d/actions.conf

Use:

reject = 15;
add_header = 6;
greylist = 4;

Restart:

sudo systemctl restart rspamd
sudo ss -tlnp | grep 11332

Add Rspamd to the Postfix milter chain after OpenDKIM:

milter_protocol = 6
milter_default_action = accept
smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:11332
non_smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:11332

Reload:

sudo postfix check
sudo systemctl reload postfix

[IMAGE: Supporting visual 3 for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records, showing Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records decisions, examples, and Linux, Postfix, SMTP. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records setting-up-postfix-mail-server-linux-smtp-dkim-spf-records visual 3]

Test Rspamd:

rspamc stat

Test the standard GTUBE spam test pattern from a safe test mailbox:

printf 'Subject: GTUBE test\n\nXJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X\n' \
  | sendmail test@example.com

Then check:

journalctl -u rspamd --since '10 minutes ago' --no-pager
journalctl -u postfix --since '10 minutes ago' --no-pager

Do not reject aggressively on day one. Watch scores, false positives, and business-critical senders first.

Add SMTP-level hardening

Start with safe checks:

smtpd_helo_required = yes
disable_vrfy_command = yes

smtpd_sender_restrictions =
    reject_non_fqdn_sender,
    reject_unknown_sender_domain,
    permit

smtpd_recipient_restrictions =
    reject_non_fqdn_recipient,
    reject_unknown_recipient_domain,
    permit

Optional DNS blocklists can help, but they are policy dependencies. If you use one, understand its terms and failure modes:

smtpd_recipient_restrictions =
    reject_non_fqdn_recipient,
    reject_unknown_recipient_domain,
    reject_rbl_client zen.spamhaus.org,
    permit

Do not stack random blocklists from old forum posts. A bad RBL choice can reject legitimate mail.

Test from outside the server

From another host:

swaks --to postmaster@example.com --from external-test@example.net --server mail.example.com

Test STARTTLS:

swaks --to postmaster@example.com \
  --from external-test@example.net \
  --server mail.example.com \
  --tls

Test that the server is not an open relay:

swaks --to someone@gmail.com \
  --from attacker@example.net \
  --server mail.example.com

Expected result:

Relay access denied

If unauthenticated external users can relay to arbitrary domains, stop and fix smtpd_relay_restrictions before publishing the server.

Test outbound delivery

Send to an external mailbox:

printf 'Subject: outbound test\n\nPostfix outbound test\n' \
  | sendmail you@external-mailbox.example

Watch logs:

journalctl -u postfix -f

Look for:

status=sent

If mail is deferred:

mailq
postqueue -p
postcat -vq QUEUE_ID

Common causes:

  • provider blocks outbound port 25;
  • missing or wrong PTR record;
  • remote server rejects poor IP reputation;
  • SPF does not include the sending IP;
  • DKIM DNS record has not propagated;
  • hostname in SMTP banner does not match DNS expectations.

Keep logs operational

Useful commands:

postconf -n
postfix check
mailq
postqueue -f
journalctl -u postfix --since today --no-pager
journalctl -u opendkim --since today --no-pager
journalctl -u rspamd --since today --no-pager

Queue triage:

postqueue -p
postcat -vq QUEUE_ID
postsuper -d QUEUE_ID

Only delete queued mail when you understand why it is queued.

Rotate DKIM keys safely

Do not replace a DKIM selector in place.

Use a new selector:

sudo opendkim-genkey -b 2048 -s mail2026 -d example.com -D /etc/opendkim/keys/example.com

Publish:

mail2026._domainkey.example.com. 300 IN TXT "v=DKIM1; k=rsa; p=..."

Update:

mail2026._domainkey.example.com example.com:mail2026:/etc/opendkim/keys/example.com/mail2026.private
*@example.com mail2026._domainkey.example.com

[IMAGE: Supporting visual 4 for Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records, showing Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records decisions, examples, and Linux, Postfix, SMTP. Alt: Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records setting-up-postfix-mail-server-linux-smtp-dkim-spf-records visual 4]

Reload OpenDKIM:

sudo systemctl reload opendkim

Keep the old DNS record published until old signed mail is no longer in transit or likely to be verified from archives. Then remove the old selector.

Production checklist

Before calling the server ready:

  1. mail.example.com has forward DNS.
  2. The public IP has PTR back to mail.example.com.
  3. MX points to the mail hostname.
  4. Port 25 accepts inbound SMTP.
  5. Port 587 requires TLS and authentication if enabled.
  6. The server rejects unauthenticated relay attempts.
  7. TLS certificate validates with openssl s_client.
  8. DKIM signs outbound mail and verifies externally.
  9. SPF includes every legitimate sender and only those senders.
  10. DMARC starts at p=none with monitored reports.
  11. Rspamd is scanning and not producing unacceptable false positives.
  12. Postfix logs and queue monitoring are watched.
  13. postmaster@ and abuse@ route to a human.
  14. Backups include /etc/postfix, /etc/opendkim, and DNS records.

FAQ

What is Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records?

Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records is a practical networking topic that should be evaluated through implementation scope, production risk, testing, documentation, and long-term maintainability.

When should a team use Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records?

Use Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records when it solves a real project constraint, improves clarity, or reduces operational risk. Avoid it when it only adds novelty or hides behavior from future maintainers.

What is the biggest risk with Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records?

The biggest risk is copying a pattern without its context. Production systems need clear boundaries, rollback options, tests, and observability before a technique becomes dependable.

How do you test Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records?

Test the smallest unit that owns the behavior, then add integration coverage for the path users or systems actually rely on. Include failure cases, configuration differences, and regression checks.

How does Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records affect SEO and AI search visibility?

It improves visibility when the article gives a direct answer, expert context, structured headings, internal links, trustworthy references, and FAQ content that matches the visible page.

Conclusion

Setting Up Postfix Mail Server on Linux: SMTP, DKIM & SPF Records is worth doing when the implementation improves clarity, reliability, or delivery speed. It is not worth doing when it hides ownership, increases operational risk, or makes the system harder to explain.

Use the framework above as a review checklist. Then connect this topic to the rest of the project documentation so readers can move from concept to implementation without losing context.

Top