The Complete Email Server Guide: Self-Host Your Own Email

7 min read
Advanced Email Postfix Dovecot SPF DKIM Guide

Prerequisites

  • A VPS with a clean IP (not previously used for spam)
  • A domain name with DNS access
  • Basic Linux command line knowledge
  • Ports 25, 465, 587, 993 not blocked by your VPS provider

Quick Answer: Self-hosting email is hard and not recommended for most people. Use a hosted service (Zoho free, Google Workspace, Fastmail) unless you specifically need full control. If you do self-host: Postfix (sending) + Dovecot (receiving) + Let's Encrypt (SSL) + SPF/DKIM/DMARC (deliverability) + SpamAssassin (filtering).

Need a VPS? Vultr (free credit), DigitalOcean ($200 free credit), or RackNerd (cheap annual deals).


Should You Self-Host Email?

Honest assessment:

Self-Host Use a Provider
Full control over your data Works out of the box
No monthly fees (beyond VPS) Guaranteed deliverability
Learn how email really works Professional support
Custom filtering rules Automatic spam filtering
BUT: Deliverability headaches BUT: Third party has your data
BUT: Maintenance burden BUT: Monthly cost ($5-12/user)
BUT: IP reputation management BUT: Less control

Recommendation: For personal email or learning, self-host. For business email that must be reliable, use Google Workspace or Fastmail.


Part 1: How Email Works

Sending email:
  You → Your Mail Client → Your Mail Server (SMTP/587) → Recipient's Mail Server (SMTP/25) → Recipient

Receiving email:
  Sender → Sender's Mail Server (SMTP/25) → Your Mail Server → Your Mail Client (IMAP/993)

Protocols

Protocol Port Purpose
SMTP 25 Server-to-server delivery
SMTP Submission 587 Client sends email (with STARTTLS)
SMTPS 465 Client sends email (implicit TLS)
IMAP 993 Client reads email (with TLS)
POP3 995 Client downloads email (legacy)

Components

Component What It Does Software
MTA (Mail Transfer Agent) Sends and receives email Postfix
MDA (Mail Delivery Agent) Delivers to mailboxes Dovecot
MUA (Mail User Agent) Email client Thunderbird, Outlook, webmail
Spam Filter Filters junk SpamAssassin, Rspamd
Authentication Proves you're legitimate SPF, DKIM, DMARC

Part 2: Prerequisites

DNS Records Needed

Before installing anything, set up these DNS records:

Type Name Value
A mail Your server IP
MX @ mail.yourdomain.com (priority 10)
TXT @ SPF record (see Part 6)
TXT _dmarc DMARC record (see Part 6)
PTR (reverse DNS) mail.yourdomain.com (set via VPS provider)

Reverse DNS (PTR Record)

Critical: Email servers check that your IP's reverse DNS matches your mail server's hostname. Set this in your VPS provider's control panel:

IP: 203.0.113.50 → mail.yourdomain.com

Check Port 25

Many VPS providers block port 25 by default. Test:

telnet smtp.gmail.com 25
# If it connects, port 25 is open
# If it hangs, ask your provider to unblock it

Set Hostname

sudo hostnamectl set-hostname mail.yourdomain.com

# Add to /etc/hosts
echo "203.0.113.50 mail.yourdomain.com mail" | sudo tee -a /etc/hosts

Part 3: Install Postfix (Sending)

Postfix is the most widely used MTA (Mail Transfer Agent).

sudo apt update
sudo apt install postfix -y

During installation, select:

  • Internet Site
  • System mail name: yourdomain.com

Configure

Edit /etc/postfix/main.cf:

# Basic settings
myhostname = mail.yourdomain.com
mydomain = yourdomain.com
myorigin = $mydomain
mydestination = $myhostname, $mydomain, localhost
mynetworks = 127.0.0.0/8

# TLS (encryption)
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtp_tls_security_level = may

# SASL authentication (for clients)
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination

# Mailbox
home_mailbox = Maildir/

# Size limits
message_size_limit = 52428800    # 50MB
mailbox_size_limit = 0           # Unlimited

# Submission port (587)
# Configured in master.cf

Enable Submission Port (587)

Edit /etc/postfix/master.cf — uncomment the submission section:

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

Get SSL Certificate

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

Start

sudo systemctl restart postfix
sudo systemctl enable postfix

Part 4: Install Dovecot (Receiving)

Dovecot handles IMAP (clients reading email).

sudo apt install dovecot-core dovecot-imapd dovecot-lmtpd -y

Configure

Edit /etc/dovecot/conf.d/10-mail.conf:

mail_location = maildir:~/Maildir

Edit /etc/dovecot/conf.d/10-auth.conf:

disable_plaintext_auth = yes
auth_mechanisms = plain login

Edit /etc/dovecot/conf.d/10-ssl.conf:

ssl = required
ssl_cert = </etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
ssl_min_protocol = TLSv1.2

Edit /etc/dovecot/conf.d/10-master.conf — add Postfix auth socket:

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

Start

sudo systemctl restart dovecot
sudo systemctl enable dovecot

Part 5: Create Email Accounts

# Create a system user for each email account
sudo adduser sam
# This user can now receive email at [email protected]

# Set password (used for IMAP/SMTP login)
sudo passwd sam

Connect with Email Client

Setting Value
Incoming (IMAP) mail.yourdomain.com, port 993, SSL/TLS
Outgoing (SMTP) mail.yourdomain.com, port 587, STARTTLS
Username sam
Password System password

Works with Thunderbird, Outlook, Apple Mail, or any standard email client.


Part 6: Email Authentication (SPF, DKIM, DMARC)

Without these, your emails go straight to spam. These DNS records prove you're a legitimate sender.

SPF (Sender Policy Framework)

Tells receiving servers which IPs are allowed to send email for your domain.

Add DNS TXT record:

Name: @
Type: TXT
Value: v=spf1 mx a ip4:YOUR_SERVER_IP ~all

DKIM (DomainKeys Identified Mail)

Adds a cryptographic signature to every email you send.

sudo apt install opendkim opendkim-tools -y

# Generate DKIM key
sudo mkdir -p /etc/opendkim/keys/yourdomain.com
sudo opendkim-genkey -b 2048 -D /etc/opendkim/keys/yourdomain.com -d yourdomain.com -s default
sudo chown -R opendkim:opendkim /etc/opendkim

Configure /etc/opendkim.conf:

Syslog yes
Mode sv
Domain yourdomain.com
Selector default
KeyFile /etc/opendkim/keys/yourdomain.com/default.private
Socket inet:8891@localhost

Add to Postfix /etc/postfix/main.cf:

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

Get the DNS record:

sudo cat /etc/opendkim/keys/yourdomain.com/default.txt

Add this TXT record to your DNS.

sudo systemctl enable --now opendkim
sudo systemctl restart postfix

DMARC

Tells receiving servers what to do with emails that fail SPF/DKIM checks.

Add DNS TXT record:

Name: _dmarc
Type: TXT
Value: v=DMARC1; p=quarantine; rua=mailto:[email protected]; fo=1

Verify Authentication

# Send a test email to [email protected]
# It replies with your SPF, DKIM, DMARC results

# Or use our tool:

Check your records: SPF & DMARC Checker

Full guide: SPF/DKIM/DMARC Guide


Part 7: Spam Filtering

SpamAssassin

sudo apt install spamassassin spamc -y
sudo systemctl enable --now spamassassin

Modify the existing smtp inet line in /etc/postfix/master.cf to add the content filter. Then add the SpamAssassin transport at the end of the file. Note: if user spamd does not exist, create it with sudo adduser --system --group spamd.

smtp      inet  n       -       y       -       -       smtpd
  -o content_filter=spamassassin

spamassassin unix -     n       n       -       -       pipe
  user=spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Update Rules

sudo sa-update
sudo systemctl restart spamassassin

Part 8: Firewall

sudo ufw allow 25/tcp      # SMTP (server-to-server)
sudo ufw allow 587/tcp     # Submission (client)
sudo ufw allow 993/tcp     # IMAP (client)
sudo ufw allow 465/tcp     # SMTPS (client, optional)

Part 9: Testing

Send a Test Email

echo "Test from my server" | mail -s "Test" [email protected]

Check Headers

When you receive the email, check the headers for:

  • SPF: pass
  • DKIM: pass
  • DMARC: pass

In Gmail: Open email → three dots → "Show original" → look for authentication results.

Common Delivery Issues

Problem Fix
Emails go to spam Check SPF, DKIM, DMARC all pass. Check IP reputation
Emails rejected Check reverse DNS (PTR record). Check IP blacklists
Can't send to Gmail Google requires SPF + DKIM. Also check if port 25 is open
Connection timed out Port 25 blocked by VPS provider. Contact support
SSL errors Check certificate paths in Postfix and Dovecot

Check IP Reputation

Use our IP Blacklist Checker to see if your server IP is on any spam lists.


Part 10: Maintenance

Monitor Mail Queue

# View queue
mailq

# Flush queue (retry delivery)
sudo postfix flush

# Delete all queued messages
sudo postsuper -d ALL

Certificate Renewal

Certbot auto-renews, but Postfix and Dovecot need to reload:

# Add to certbot renewal hook
echo 'systemctl reload postfix dovecot' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh

Log Monitoring

# Watch mail logs
sudo tail -f /var/log/mail.log

# Check for errors
sudo grep "error\|warning\|reject" /var/log/mail.log | tail -20

# Check delivery status
sudo grep "status=" /var/log/mail.log | tail -20

Easier Alternative: Docker Mailserver

If manual Postfix/Dovecot setup is too much, use Docker Mailserver — bundles everything in one Docker container:

# Download
wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/main/compose.yaml
wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/main/mailserver.env

# Configure
nano mailserver.env

# Start
docker compose up -d

# Add email account
docker exec -it mailserver setup email add [email protected]

Still needs the DNS records (MX, SPF, DKIM, DMARC, PTR) but the server setup is automated.


Related Guides

Related Tools