Applies to: Debian 13 (Postfix 3.10.13, Dovecot 2.4.1) and Ubuntu 26.04 (Postfix 3.10.6, Dovecot 2.4.2); tested end to end in Docker on both. Not for Ubuntu 24.04, whose Dovecot 2.3 uses different settings

A basic email server needs two programs: Postfix, which receives mail from the internet on port 25 and sends your users’ mail, and Dovecot, which lets mail apps read the mailboxes over IMAP and checks passwords. This guide sets up both for one domain, with a mailbox per Linux user, encrypted logins and a submission port for sending. Plan for the work that comes after: spam filtering, backups and keeping your server’s reputation clean. If you only need mailboxes, a hosted service such as Google Workspace is less work.

What you need

  • A VPS or dedicated server with a fixed IP address and outgoing port 25 open. Check it first: test outgoing port 25. All Ucartz servers have port 25 open.
  • A domain (here example.com) and a mail host name (here mail.example.com).
  • A certificate for the mail host name, for example from Let’s Encrypt with Certbot, which stores it as /etc/letsencrypt/live/mail.example.com/fullchain.pem and privkey.pem.

1. DNS records

  • A record: mail.example.com to your server’s IP address.
  • MX record for example.com: priority 10, value mail.example.com. In cPanel: add an MX record.
  • Reverse DNS (PTR) for the IP address: mail.example.com. Google’s sender guidelines require that the PTR name and the A record point at each other: set reverse DNS.
  • SPF, DKIM and DMARC: add these before you send real mail (see the links at the end).

2. Install Postfix and Dovecot

sudo hostnamectl set-hostname mail.example.com
sudo apt update
sudo apt install postfix dovecot-imapd

When Postfix asks, choose Internet Site and enter example.com as the system mail name.

3. Configure Postfix

sudo postconf -e 'myhostname = mail.example.com' \
  'mydestination = $myhostname, example.com, localhost.localdomain, localhost' \
  'home_mailbox = Maildir/' \
  'smtpd_sasl_type = dovecot' 'smtpd_sasl_path = private/auth' \
  'smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem' \
  'smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem'

home_mailbox = Maildir/ delivers each user’s mail to ~/Maildir, and the SASL lines let Postfix check passwords through Dovecot. Then turn on the submission port 587, where mail apps send after logging in:

sudo postconf -M submission/inet="submission inet n - y - - smtpd"
sudo postconf -P "submission/inet/syslog_name=postfix/submission" \
  "submission/inet/smtpd_tls_security_level=encrypt" \
  "submission/inet/smtpd_sasl_auth_enable=yes" \
  "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"
sudo postfix check

The default smtpd_relay_restrictions on Debian 13 and Ubuntu 26.04 (permit_mynetworks permit_sasl_authenticated defer_unauth_destination) only let local programs and logged-in users send to other domains, so your server is not an open relay. In our test, an outside address trying to relay got 454 4.7.1 <someone@example.net>: Relay access denied.

4. Configure Dovecot

Create /etc/dovecot/local.conf, which Dovecot reads after its other files:

mail_driver = maildir
mail_path = %{home}/Maildir
mail_inbox_path = .

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

The mail_inbox_path = . line matters: Debian’s default files set the inbox to /var/mail/ for the older mbox format. When we cleared it instead, Dovecot 2.4 looked for the inbox in ~/Maildir/.INBOX and showed an empty inbox although mail had arrived. In /etc/dovecot/conf.d/10-ssl.conf, point ssl_server_cert_file and ssl_server_key_file at the same certificate files as Postfix. Check with sudo doveconf -n.

5. Create mailboxes and start

Each Linux user is a mailbox; the address is the user name at your domain. For people who only use email, give them no shell:

sudo useradd -m -s /usr/sbin/nologin anna
sudo passwd anna
sudo systemctl restart postfix dovecot

Open the ports in the firewall: 25 (incoming mail), 587 (sending from apps) and 993 (IMAP over TLS). With UFW: sudo ufw allow 25,587,993/tcp.

6. Test it

We tested with swaks (sudo apt install swaks) and curl:

$ swaks --to anna@example.com --server 127.0.0.1 --port 25
<-  250 2.0.0 Ok: queued as B5B37BCCB1

$ curl -s "imaps://mail.example.com/INBOX;MAILINDEX=1" -u anna
To: anna@example.com

$ swaks --to someone@example.net --from anna@example.com --server mail.example.com --port 587 -tls --auth PLAIN --auth-user anna
<~  235 2.7.0 Authentication successful
<~  250 2.0.0 Ok: queued as 4968ABCE86

Without a login, port 587 refuses to send: 554 5.7.1 ... Client host rejected: Access denied. A wrong IMAP password gives NO [AUTHENTICATIONFAILED] Authentication failed. Watch the log while you test: sudo journalctl -f | grep -E "postfix|dovecot".

Mail app settings

  • Incoming: IMAP, server mail.example.com, port 993, SSL/TLS.
  • Outgoing: SMTP, server mail.example.com, port 587, STARTTLS, with authentication.
  • User name: the Linux user name (anna), not the full address.

Dovecot refuses password logins without encryption from other computers (auth_allow_cleartext = no is its default), so always use TLS in the app.

Before you send real mail

  1. Publish SPF, sign with DKIM and publish DMARC.
  2. Test authentication and deliverability.
  3. Protect the server from misuse and back up /home/*/Maildir.

Want a dedicated server for this with port 25 open? See email server hosting.

Official documentation: Postfix basic configuration and Postfix SASL with Dovecot.

Was this answer helpful?

Still stuck? Open a ticket