Back to tutorials
Tutorial

Mail Server Setup Tutorial (2026): Configure Postfix + Dovecot + SPF/DKIM/DMARC on a Hosting VPS

Mail server setup tutorial (2026) for a VPS: Postfix + Dovecot, TLS, SPF/DKIM/DMARC, and deliverability checks.

By Anurag Singh
Updated on Jun 14, 2026
Category: Tutorial
Share article
Mail Server Setup Tutorial (2026): Configure Postfix + Dovecot + SPF/DKIM/DMARC on a Hosting VPS

Email is often the first service to fail when DNS is off by one character. It can also break fast when TLS points to the wrong file. This mail server setup tutorial shows a production-ready Postfix + Dovecot setup on an Ubuntu 24.04 VPS. It also covers the DNS records and verification steps you need for reliable delivery in 2026.

By the end, you’ll have SMTP submission on 587, IMAPS on 993, Let’s Encrypt certificates, and SPF/DKIM/DMARC. You’ll also have a short ops checklist to keep the stack stable.

If you’d rather avoid ongoing sysadmin work, a managed VPS hosting plan from HostMyCode (Affordable & Reliable Hosting) keeps patching, monitoring, and incident response off your calendar.

What you’ll build (and what you should decide first)

Before you install anything, define what “one mail server” means for your use case. For most VPS-based setups, you’ll want:

  • Postfix for SMTP receive/send.
  • Dovecot for IMAP mailbox access (and SASL auth for Postfix).
  • Let’s Encrypt certificates for TLS.
  • SPF, DKIM, DMARC so major providers trust your mail.
  • rDNS (PTR) for your server IP. Missing or mismatched PTR still hurts deliverability.

This tutorial assumes:

  • Ubuntu Server 24.04 LTS
  • One hostname for the mail server, for example mail.example.com
  • One domain you’ll send as, for example example.com
  • You control the domain’s DNS zone

Mail server setup tutorial prerequisites: hostname, rDNS, and firewall

Mail delivery depends on basic identity checks. Get these right first. The rest of the setup stays straightforward.

1) Set the server hostname and FQDN

Pick a stable FQDN for the VPS. You’ll match it to DNS in the next step.

sudo hostnamectl set-hostname mail.example.com
hostname -f

hostname -f should return mail.example.com.

2) Create DNS records (A/AAAA and MX)

In your DNS provider, add:

  • A: mail.example.com → your VPS IPv4
  • AAAA (optional but recommended): mail.example.com → your VPS IPv6
  • MX: example.commail.example.com priority 10

If you prefer to keep DNS and hosting under one roof, you can register/transfer domains through HostMyCode Domains and manage changes in one place.

3) Set reverse DNS (PTR) for the sending IP

Set your IP’s PTR record to mail.example.com. Then confirm forward and reverse lookups agree.

HostMyCode has a dedicated guide for this step: Reverse DNS setup guide.

Quick checks:

dig +short mail.example.com A
dig +short -x YOUR.SERVER.IP

4) Open only the ports you need

If you use UFW, allow SSH, SMTP, submission, and IMAPS.

You can add port 465 later if you truly need implicit TLS.

sudo ufw allow 22/tcp
sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp
sudo ufw enable
sudo ufw status

If your VPS firewall rules are still wide open, lock them down first using UFW firewall setup tutorial, then return here.

Install Postfix and Dovecot (IMAP + SASL auth)

Ubuntu’s mail packages are well-tested and work cleanly with systemd. Install Postfix, Dovecot, and a few utilities for testing.

sudo apt update
sudo apt install -y postfix dovecot-imapd dovecot-pop3d dovecot-lmtpd \
  dovecot-sieve dovecot-managesieved \
  libsasl2-modules \
  mailutils openssl

During the Postfix installer prompts:

  • Select Internet Site
  • System mail name: example.com (your primary sending domain)

Confirm services are running

sudo systemctl status postfix --no-pager
sudo systemctl status dovecot --no-pager

Configure Postfix for submission (587), TLS, and sane defaults

Postfix works out of the box. However, the default config is too loose for modern client submission.

In this section, you’ll set identity, enable SASL auth, and tighten relay rules.

1) Edit /etc/postfix/main.cf

Open the file:

sudo nano /etc/postfix/main.cf

Add or adjust these settings (replace domains/hostnames):

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

# Listen on all interfaces
inet_interfaces = all
inet_protocols = all

# Accept mail for these destinations
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

# Networks allowed to relay (keep tight)
mynetworks = 127.0.0.0/8 [::1]/128

# Mailbox format (Maildir works well with Dovecot)
home_mailbox = Maildir/

# TLS (we'll point to Let's Encrypt paths later)
smtpd_tls_security_level = may
smtp_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes

# Restrict relaying
smtpd_recipient_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_unauth_destination

# Enable SASL via Dovecot
auth_mechanisms = plain login
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

# Hardening
smtpd_helo_required = yes
disable_vrfy_command = yes
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

# Message size (example: 25MB)
message_size_limit = 26214400

2) Enable the submission service in /etc/postfix/master.cf

Open:

sudo nano /etc/postfix/master.cf

Uncomment (or add) the submission service.

This configuration forces authenticated submission on 587:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject_unauth_destination

3) Reload Postfix

sudo systemctl restart postfix
sudo postconf -n

postconf -n prints only non-default settings. Save the output somewhere. It speeds up troubleshooting later.

Configure Dovecot for IMAP, Maildir, and Postfix auth

Dovecot does two jobs here. It serves IMAP over TLS. It also exposes an auth socket for Postfix submission.

1) Set Maildir

Edit:

sudo nano /etc/dovecot/conf.d/10-mail.conf

Ensure:

mail_location = maildir:~/Maildir

2) Enable plaintext auth only over TLS

Edit:

sudo nano /etc/dovecot/conf.d/10-auth.conf

Set:

disable_plaintext_auth = yes
auth_mechanisms = plain login

3) Create the Postfix auth socket

Edit:

sudo nano /etc/dovecot/conf.d/10-master.conf

Find the service auth block and add (or adjust) this stanza:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

4) Enable IMAP and (optional) POP3

Edit:

sudo nano /etc/dovecot/dovecot.conf

Ensure:

protocols = imap

POP3 is still supported, but it increases exposure. If you don’t have a specific need, leave it disabled.

5) Restart Dovecot

sudo systemctl restart dovecot

Add TLS with Let’s Encrypt (and wire it into Postfix + Dovecot)

Modern clients expect TLS everywhere. Let’s Encrypt keeps certificates current without manual renewals.

1) Install Certbot

sudo apt install -y certbot

If this VPS also runs a site on 80/443, use the appropriate Certbot plugin (nginx/apache) and request the certificate there.

For a mail-only server, standalone mode works as long as port 80 is reachable.

2) Request a certificate

Make sure mail.example.com resolves to this server before running:

sudo certbot certonly --standalone -d mail.example.com

Certificates land under:

  • /etc/letsencrypt/live/mail.example.com/fullchain.pem
  • /etc/letsencrypt/live/mail.example.com/privkey.pem

3) Point Postfix to the cert

Edit /etc/postfix/main.cf and set:

smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem

Reload:

sudo systemctl reload postfix

4) Point Dovecot to the cert

Edit:

sudo nano /etc/dovecot/conf.d/10-ssl.conf

Set:

ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem

Restart:

sudo systemctl restart dovecot

5) Verify TLS from your workstation

openssl s_client -connect mail.example.com:587 -starttls smtp -servername mail.example.com
openssl s_client -connect mail.example.com:993 -servername mail.example.com

Look for a clean certificate chain and a hostname match.

Create mailboxes and test local delivery

This setup uses Linux system users with Maildir stored in each user’s home directory. It’s easy to reason about and works well for small teams.

If you host many domains and users, you’ll usually move to virtual users and database-backed maps.

1) Create a user

sudo adduser alice

Dovecot will create the Maildir structure on first delivery. Send a local test message:

echo "hello" | mail -s "test" alice

Confirm the mailbox exists:

sudo ls -la /home/alice/Maildir

2) Test IMAP login

Use a mail client (Thunderbird, Outlook, Apple Mail) or a CLI tool. IMAP settings:

  • Server: mail.example.com
  • Port: 993 (IMAPS)
  • Username: alice (or alice@example.com if you map it that way)
  • Authentication: password

SMTP submission settings:

  • Server: mail.example.com
  • Port: 587
  • Encryption: STARTTLS
  • Authentication: required

Publish SPF, DKIM, and DMARC (deliverability basics that actually move the needle)

If you skip authentication, expect major receivers (Gmail, Outlook, Yahoo) to treat your server as suspicious.

In 2026, even low-volume domains need clean SPF/DKIM/DMARC.

SPF: declare who can send for your domain

Add a TXT record for example.com:

example.com.  TXT  "v=spf1 mx -all"

This reads as “only the MX hosts may send for this domain; everything else fails.” If you use a third-party sender, add it explicitly.

Avoid weakening SPF with ~all unless you have a clear reason.

DKIM: sign outgoing mail with your domain key

Install OpenDKIM and tools:

sudo apt install -y opendkim opendkim-tools

Create a key directory:

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

Generate a 2048-bit key (selector name: mail):

sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s mail
sudo chown opendkim:opendkim /etc/opendkim/keys/example.com/mail.private

Configure OpenDKIM:

sudo nano /etc/opendkim.conf

Ensure these lines exist (or match):

Syslog                  yes
UMask                   002
Mode                    sv
Canonicalization        relaxed/simple
Socket                  local:/run/opendkim/opendkim.sock
UserID                  opendkim:opendkim
KeyTable                /etc/opendkim/key.table
SigningTable            /etc/opendkim/signing.table
ExternalIgnoreList      /etc/opendkim/trusted.hosts
InternalHosts           /etc/opendkim/trusted.hosts

Create the mapping files:

sudo nano /etc/opendkim/key.table
mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com/mail.private
sudo nano /etc/opendkim/signing.table
*@example.com mail._domainkey.example.com
sudo nano /etc/opendkim/trusted.hosts
127.0.0.1
localhost
mail.example.com

Make Postfix talk to OpenDKIM (milter):

sudo nano /etc/postfix/main.cf

Add:

milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:/run/opendkim/opendkim.sock
non_smtpd_milters = unix:/run/opendkim/opendkim.sock

Ensure OpenDKIM creates the socket where Postfix can reach it. On Ubuntu, confirm the service uses /run/opendkim/opendkim.sock:

sudo systemctl restart opendkim
sudo systemctl restart postfix

Publish the DKIM DNS record. Print it:

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

Create the TXT record shown (host: mail._domainkey).

DMARC: tell receivers what to do when SPF/DKIM fail

Start in monitoring mode. Switch to enforcement once you trust your sending sources.

Add TXT at _dmarc.example.com:

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

After reports look clean, move to p=quarantine, then p=reject. HostMyCode’s step-by-step guide is here: SPF/DKIM/DMARC setup guide.

Verify DNS and authentication end-to-end

Don’t rely on assumptions. Check the records directly.

Then validate with real deliveries.

1) Check MX, SPF, DKIM, DMARC records

dig +short example.com MX
dig +short example.com TXT
dig +short mail._domainkey.example.com TXT
dig +short _dmarc.example.com TXT

2) Send a message and inspect headers

Send an email from your new server to a mailbox you control (Gmail/Outlook). Open “Show original” and confirm:

  • SPF: PASS
  • DKIM: PASS
  • DMARC: PASS (or aligned)

If messages still land in spam, follow HostMyCode’s troubleshooting flow: email deliverability troubleshooting.

Lock down SMTP abuse (rate-limits, bans, and safe defaults)

If your server becomes a spam relay, deliverability collapses fast.

Strong auth plus basic abuse controls beats hours of “tuning” later.

1) Confirm you are not an open relay

From another machine, attempt a relay test (replace domains). A correctly configured server should reject unauthenticated relaying.

swaks --to victim@external-domain.com --from test@example.com --server mail.example.com

If you don’t have swaks, install it on your workstation. What matters is the outcome.

The relay attempt should be denied.

2) Add Fail2Ban for Postfix and Dovecot

Install:

sudo apt install -y fail2ban

Enable common jails with a small override file:

sudo nano /etc/fail2ban/jail.d/mail.conf
[postfix]
enabled = true

[dovecot]
enabled = true

Restart and check:

sudo systemctl restart fail2ban
sudo fail2ban-client status
sudo fail2ban-client status postfix
sudo fail2ban-client status dovecot

For a broader baseline (including SSH), see: Fail2Ban setup tutorial.

3) Keep logs readable

Mail troubleshooting is mostly log reading. These are the usual suspects:

  • /var/log/mail.log
  • /var/log/mail.err
  • journalctl -u postfix
  • journalctl -u dovecot

Quick tail while testing:

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

Operational checklist: backups, updates, and queue health

A mail server needs routine care. Without it, you often learn about failures when password resets or invoices stop arriving.

1) Back up what matters

  • Mailboxes: /home/*/Maildir (or your virtual mailbox path)
  • Configs: /etc/postfix, /etc/dovecot, /etc/opendkim
  • Let’s Encrypt: /etc/letsencrypt

If you already run snapshots plus offsite copies, include these paths.

For a clean approach on Ubuntu, follow VPS backup setup guide and add the mail directories to your backup set.

2) Watch the mail queue

A growing queue usually points to DNS issues, poor IP reputation, or remote throttling.

sudo postqueue -p
sudo mailq

To inspect a specific queued message:

sudo postcat -q QUEUE_ID

If you need a structured flow, HostMyCode has a practical guide: Email queue troubleshooting.

3) Patch safely and predictably

Mail servers are high-value targets. Schedule updates, plan reboots, and keep a simple maintenance log.

This pairs well with a general routine: Linux Server Maintenance Tutorial (2026).

Common pitfalls (and fast diagnostics)

  • PTR missing or mismatched: mail gets spammed. Fix rDNS, confirm forward/reverse alignment.
  • Using port 25 from a residential ISP: outbound SMTP may be blocked. Use a VPS IP with clean reputation.
  • Broken TLS chain: clients fail to connect. Re-run openssl s_client tests and check cert paths.
  • Open relay: you’ll be blacklisted quickly. Re-check smtpd_recipient_restrictions and mynetworks.
  • SPF too permissive: spoofing risk. Prefer explicit senders and -all once stable.

Summary: a production-ready mail stack you can operate

You now have a working Postfix + Dovecot mail server with encrypted client connections, authenticated submission, and the DNS authentication records that drive deliverability in 2026.

Reliability comes from operations: backups, log review, and staying ahead of queue growth.

If you want a VPS sized for email and general hosting workloads, start with a HostMyCode VPS. If you’d rather offload patching, monitoring, and urgent fixes, choose managed VPS hosting and spend your time building, not chasing mail logs.

Running your own mail server works well if you control DNS, take backups seriously, and keep security tight. HostMyCode can run it on a reliable VPS, or you can offload routine maintenance to managed VPS hosting so your mail stack stays patched, monitored, and recoverable.

FAQ

Do I need both SPF and DKIM?

Yes. SPF validates the sending server. DKIM validates the message signature. DMARC ties them together and tells receivers what to do on failure.

Should I enable port 465 (SMTPS) in 2026?

Most clients work well with port 587 + STARTTLS. Enable 465 only if you have legacy clients that require implicit TLS, and still require authentication.

Can I host email for multiple domains on the same VPS?

You can, but plan it first. You’ll add extra DKIM selectors, SPF policies (or include mechanisms), and possibly virtual mailbox mapping.

For multi-tenant needs, a control panel or managed service often reduces mistakes.

My emails are authenticated but still land in spam. What next?

Check rDNS alignment, IP reputation, and content patterns. Then read HostMyCode’s deliverability troubleshooting tutorial and review your logs for deferrals and throttling.

How do I monitor whether Postfix is quietly failing?

Watch mailq size and set alerts on queue growth, disk usage, and failed services. A lightweight reporting approach is Logwatch daily reports for mail and auth logs.

Mail Server Setup Tutorial (2026): Configure Postfix + Dovecot + SPF/DKIM/DMARC on a Hosting VPS | HostMyCode