Postfix and Dovecot mail server on a VPS

A practical guide to a Postfix and Dovecot mail server on a VPS: packages, TLS, virtual users, spam filtering and the DNS records that keep mail out of spam.

RespireCloud Team 5 min read Mail

Key takeaways

  • Postfix receives and sends mail, Dovecot stores it and lets people read it over IMAP, and Rspamd filters spam and signs outgoing mail.
  • Virtual users in a Dovecot password file keep mail accounts separate from Linux accounts, and Postfix asks Dovecot to check logins.
  • Dovecot 2.4 (docs 2.4.5 as of 30 October 2026) changed its setting names, so older tutorials with mail_location no longer apply.
  • The server is the easy part: reverse DNS, SPF, DKIM, DMARC and a provider that allows port 25 decide whether mail arrives.

A Postfix and Dovecot mail server is the classic way to host your own email. It is not hard to install, but there are many small parts, and mail fails quietly. This guide shows a minimal working stack on a Debian or Ubuntu VPS: virtual users, TLS, spam filtering and the DNS that goes with it. Replace example.com and mail.example.com with your own names, and run everything as root or with sudo.

What each part does

  • Postfix is the mail transfer agent. It accepts mail from other servers on port 25, accepts mail from your users on port 587, and delivers outgoing mail.
  • Dovecot stores messages, serves them to mail apps over IMAP on port 993, and checks passwords for Postfix.
  • Rspamd scores incoming mail for spam and signs outgoing mail with DKIM.
  • Certbot or another ACME client supplies the TLS certificate.

Before you start, check that your provider allows outbound port 25 (Hetzner and DigitalOcean block it by default as of 30 October 2026, see why mail from your own server lands in spam), and that you can set reverse DNS for the server's address.

Install the packages

apt update
apt install postfix dovecot-core dovecot-imapd dovecot-lmtpd certbot

Choose "Internet Site" if the Postfix installer asks, and enter example.com as the mail name. Set the server's hostname to mail.example.com and make sure that name has an A record and that the address's reverse DNS returns it.

Get a TLS certificate

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

The certificate and key end up in /etc/letsencrypt/live/mail.example.com/. Use the same certificate for Postfix and Dovecot, and reload both after each renewal with a certbot deploy hook. How certificates are issued, and what a wildcard needs, is covered in automatic wildcard SSL.

Create a mail user and virtual mailboxes

Virtual users keep mailboxes separate from system accounts. Create one system user to own all the mail:

groupadd -g 5000 vmail
useradd -g vmail -u 5000 -d /var/vmail -m -s /usr/sbin/nologin vmail

Make the password hash and a user file for Dovecot:

doveadm pw -s SHA512-CRYPT

Put the result in /etc/dovecot/users, one line per mailbox:

anna@example.com:{SHA512-CRYPT}$6$...hash...

Configure Dovecot

Dovecot 2.4 renamed many settings. The 2.4.5 documentation we opened on 30 October 2026 uses mail_driver and mail_path instead of the old mail_location, passdb passwd-file with passwd_file_path, and ssl_server_cert_file for the certificate. Your package may carry an older 2.3 release, and then the old names apply, so run dovecot --version and read the matching documentation. A 2.4 file at /etc/dovecot/conf.d/99-mail.conf looks like this (the first lines of a 2.4 configuration, dovecot_config_version and dovecot_storage_version, must also be present as the default file shows):

mail_driver = maildir
mail_path = /var/vmail/%{user | domain}/%{user | username}/Maildir

ssl = required
ssl_server_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_server_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem

passdb passwd-file {
  passwd_file_path = /etc/dovecot/users
}
userdb passwd-file {
  passwd_file_path = /etc/dovecot/users
  fields {
    uid:default = vmail
    gid:default = vmail
    home:default = /var/vmail/%{user | domain}/%{user | username}
  }
}

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

The Dovecot documentation recommends that certificate files are owned by root and that the key is not readable by the Dovecot user itself, since Dovecot reads it as root at startup. The auth listener gives Postfix a socket to ask "is this password right?" without learning the passwords. Restart with systemctl restart dovecot.

Configure Postfix

Append to /etc/postfix/main.cf (or run each line with postconf -e):

myhostname = mail.example.com
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
smtp_tls_security_level = may

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

virtual_mailbox_domains = example.com
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_transport = lmtp:unix:private/dovecot-lmtp

Then list the mailboxes and build the map:

echo "anna@example.com  example.com/anna/Maildir/" > /etc/postfix/vmailbox
postmap /etc/postfix/vmailbox

Dovecot also needs an LMTP listener at /var/spool/postfix/private/dovecot-lmtp (same mode and owner as the auth listener) so that Postfix hands finished messages to it. Enable the submission service in /etc/postfix/master.cf by uncommenting the submission block and adding -o smtpd_tls_security_level=encrypt and -o smtpd_sasl_auth_enable=yes (SASL login is off by default, so port 25 stays login-free), so users must log in and use TLS on port 587. The last restriction in the list, reject_unauth_destination, is what stops your server being an open relay, so never remove it. Reload with systemctl reload postfix. Every option above was checked on 30 October 2026 against the postconf(5) manual page (Postfix 3.11; Debian 13 ships 3.10). smtpd_tls_security_level accepts none, may and encrypt, and smtpd_sasl_type plus smtpd_sasl_path select the SASL plug-in and its rendezvous point (the manual page lists the available types with postconf -a). milter_default_action = accept lets mail through if Rspamd is down; the default (tempfail before Postfix 3.11, shutdown from 3.11) defers mail instead, which you may prefer. milter_protocol is already 6 by default, so it needs no line.

Add Rspamd for spam filtering and DKIM

Rspamd publishes a repository for Debian and Ubuntu; the install steps on docs.rspamd.com (checked 30 October 2026) are to add its signing key and the apt source, then apt install rspamd. To connect it to Postfix, add:

smtpd_milters = inet:localhost:11332
milter_default_action = accept

and in /etc/rspamd/local.d/worker-proxy.inc set milter = yes; and self_scan = yes; on the default upstream. Set a password for its web interface with rspamadm pw and put the hash in /etc/rspamd/local.d/worker-controller.inc. The Rspamd quickstart also configures Redis for its statistics. For outgoing signing, generate a key as shown in SPF, DKIM and DMARC setup and enable the dkim_signing module with a selector and a path to the key.

Publish the DNS records

At minimum: an A record for mail.example.com, an MX record for example.com pointing to it, reverse DNS from your provider, and SPF, DKIM and DMARC TXT records. Google's sender guidelines also expect valid forward and reverse DNS and a TLS connection for everyone (checked 30 October 2026 at support.google.com/a/answer/81126). MTA-STS and TLS-RPT are optional extras described in how to set up a mail server the right way.

Test it

  1. openssl s_client -connect mail.example.com:993 should show your certificate.
  2. Log in from a mail app with the full address and the password you hashed, IMAP on 993 and SMTP on 587.
  3. Send a message to a Gmail address and read the Authentication-Results header.
  4. Send one back and check /var/log/mail.log to see it arrive.
  5. Try relaying through the server from an address that is not logged in; it must be refused.

What a panel automates

Everything above is repeated for each new domain: mailbox maps, DKIM keys, DNS records, certificate renewal and spam tuning. A control panel does this when you add a domain. RespireCloud's mail feature publishes the records and issues the certificates, but doing it once by hand first is the best way to understand what it is doing.

Questions

Which Linux distribution should I use?

Debian or Ubuntu LTS are the most common choices because Postfix, Dovecot and Rspamd are packaged and documented for them. The commands below use apt and apply to both.

How much memory does a small mail server need?

A server for a few domains and a handful of mailboxes runs in 2 GB, but Rspamd with Redis and any antivirus scanning want more. Size it by mailbox count and by whether you scan attachments.

Can I run webmail on the same server?

Yes. Roundcube or SnappyMail talk to Dovecot over IMAP and to Postfix on the submission port, so they need no special access.

Do I need a static IP address and reverse DNS?

Yes. Receivers check that your address has a matching reverse DNS name, and a changing address loses its reputation.

Is it worth it compared with a panel?

Doing it by hand teaches you how mail works and costs nothing but time. For many domains, repeating the DNS, TLS and filter work by hand is where mistakes creep in, which is what a panel automates.

PostfixDovecotMail serverVPS
Share LinkedIn X Email

RespireCloud Team

The people who build RespireCloud

The engineers and testers behind RespireCloud write here about what the panel does, how it is built and what we found when we tried to break it. Every claim links to the feature it describes.

More posts by RespireCloud Team

See it on a real server.

The free plan covers 1 account, 3 sites and 5 mailboxes on one server, with the whole base product. Or ask us for a walk through.