Last updated: August 2025

Mail Server Basics (Postfix and Dovecot)

Mail Server Basics

Note: This article series covers configuring Debian 12 for hosting multiple domains and web sites on a single dedicated server. As such, some strategies may be inappropriate for your environment. Sockets for example are appropriate for communication between services hosted on the same machine but not suited to a set up with distributed services (where you'd use ports). Please consult the overview for more information.


Operating System: Debian 12
Postfix: version 3.7.11
Dovecot: version 2.3.19.1 (9b53102964)

Almost all internet web sites send and receive email. If you're from a Windows environment you'll most likely be used to your MTA (Mail Transfer Agent) and MDA (Mail Delivery Agent) being bundled in one application.

Mail Transfer Agents deal with sending and receiving the actual messages whilst Mail Delivery Agents are concerned with providing interfaces for your users to collect and interact with those emails (ie. IMAP and POP3).

In Linux, those 2 jobs are handled by 2 discrete services that work with each other (Postfix MTA and Dovecot MDA) and can be configured in a variety of ways which makes for a very flexible suite for possible solutions but can be a little confusing at times, especially as online tutorials from different time periods show you ways of achieving things in different ways. Older complicated methods are sometimes replaced by a simple switch in later versions.

I'm going to show you how to set up mail services on your Linux server which will serve multiple domains hosted on the same machine. I've spread it over 3 articles because I want to show you how to set up SSL certificates for multiple domains and I want to show you how to set up a Dovecot sieve filter that runs a script when mail arrives.

This first article covers setting up Postfix and Dovecot for multiple domains and basic SSL. If you're a casual and you just want a step-by-step guide to get yourself up and running in that environment then you've come to the right place.

Linux Mail Services can be a bit of a dark art so if you're a pro in a multi-server environment I recommend reading a book on this one, I also highly recommend you consult the Postfix and Dovecot manuals and pay careful attention to the words on the page, it's easy to overlook something that later becomes obvious. For example, I remember being a bit confused about the distinction between mail_home and mail_location for a while and that was leading to all kinds of errors and warnings!

Let's start by updating your package manager:

sudo apt update

Install Postfix (MTA):

sudo apt install postfix

Choose 'Internet Site', I use the FQDN of 'blnkserver.com'.

Install Dovecot (MDA):

sudo apt install dovecot-core dovecot-imapd dovecot-pop3d

If you run a firewall, you'll need to allow traffic on some ports for your Postfix and Dovecot services. You want to open ports 25 (SMTP), 587 (SMTP) and 465 (SMTP) and ports 110 (POP3), 995 (POP3s), 143 (IMAP) and 993 (IMAPs).

Obviously, if you don't plan to use both POP3 and IMAP then don't open those ports!


Configure Postfix for virtual mailbox domains

Linux mail can be sent and received for a system user (often how you set up an office environment) or you can set the server up to manage multiple virtual domains and users (for internet sites).

With virtual domains you have a single system user (vmail in our case!) that you use for all mail boxes and you tell your services about the domains, mail boxes, SSL certificates and user logins.

I'm going to set up 2 domains - benosborne.com and blnk.co.uk
...and 2 users - ben@benosborne.com and ben@blnk.co.uk

At first, Postfix and Dovecot will access the mail boxes by knowing their location on the disk but later on we'll pass the mail from Postfix to Dovecot via LMTP (Local Mail Transport Protocol) which will enable us to filter it a bit when it arrives.

Add the user and group vmail. If the vmail user already exists on your system, your software will warn you and not re-create or overwrite it:

sudo adduser vmail
sudo addgroup vmail


Make a directory to store the virtual mail:

sudo mkdir /var/mail/vmail

Take ownership (chown) of that folder with vmail. Before the : is the user, after is the group:

sudo chown vmail:vmail /var/mail/vmail

get the user and group id's, we're going to tell Postfix about them.

sudo id vmail

Note the user (uid) and group (gid) id's. In my case uid=1001, gid=1001.

So you understand what we're doing here, virtual_mailbox_domains is just a list of domains that we want Postfix to be responsible for.

virtual_mailbox_maps (/etc/postfix/vmailbox) is going to be a list of mail boxes and their location on the disk whilst virtual_alias_maps (/etc/postfix/valiases) is going to be a list of aliases and which mail boxes to redirect them to (eg. sales@benosborne.com redirects to ben@benosborne.com).

The mailbox_base stuff just tells Postfix where mail boxes are stored and gives the user and group it needs to read / write to that location.

Edit the Postfix configuration (main.cf), obviously use your domain names and preferences:

sudo /etc/postfix/main.cf

virtual_mailbox_domains = benosborne.com, blnk.co.uk
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_alias_maps = hash:/etc/postfix/valiases

virtual_mailbox_base = /var/mail/vmail
virtual_uid_maps = static:1001
virtual_gid_maps = static:1001
Save changes then create your vmailbox and valiases files.

virtual_mailbox_maps defines vmailbox as the map file and tells postfix where to store mail on the disk for a certain email address. Mailbox name goes on the left side of the file, disk location on the right: eg. ben@blnk.co.uk blnk.co.uk/ben/

sudo nano /etc/postfix/vmailbox

ben@blnk.co.uk			blnk.co.uk/ben/
ben@benosborne.com		benosborne.com/ben/

Note the trailing / indicates ben is a directory (maildir format) - this helps postfix decide whether to use mbox (a single file) or maildir format (multiple files). You want maildir for a number of reasons.

valiases tells postfix which inbox to redirect incoming mail to (eg. sales to ben@blnk.co.uk or a catch all @blnk.co.uk to ben@blnk.co.uk). Same deal as vmailbox, left of the file is the from mailbox and right side is the to mailbox:

sales@benosborne.com	ben@benosborne.com
or a catch all:

@benosborne.com		ben@benosborne.com
It's worth remembering that if you do define a catch all the you must include aliases for all of your mailboxes or everything gets delivered to the catch all mailbox instead!

sudo nano /etc/postfix/valiases

After you've edited these files, they need to be in a format that postfix can read so you have to run postmap on them both, this creates vmailbox.db and valiases.db:

postmap /etc/postfix/vmailbox
postmap /etc/postfix/valiases


Configure Dovecot

Make sure dovecot knows which user and group owns the email, use the id's you noted earlier (vmail account):

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

mail_uid = 1001
mail_gid = 1001
Set the mail_location and mail_home (used by LMTP and sieve later!). mail_home is where the mailbox lives whilst mail_location is where the messages are stored in that mailbox:

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

mail_home = /var/mail/vmail/%d/%n
mail_location = maildir:~/mail 
%d is the domain name and %n is the user name when defining mail_home.

Set the userdb and passdb to the file type and PLAIN for password. We'll be securing that file later to stop users reading it, don't worry the plain text password will only be transmitted over SSL.

Edit /etc/dovecot/conf.d/auth-passwdfile.conf.ext:

sudo nano /etc/dovecot/conf.d/auth-passwdfile.conf.ext

passdb {
  driver = passwd-file
  args = scheme=PLAIN username_format=%u /etc/dovecot/users
}

userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/users
}
Comment out the static file (for authenticating local users) in /etc/dovecot/conf.d/10-auth.conf and uncomment the auth-passwdfile.conf.ext (bottom of the file), also add login to the list of auth_mechanisms (for older clients).

The disable_plaintext_auth = yes option here prevents dovecot from sending the password unless over SSL (which is encrypted):

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

disable_plaintext_auth = yes
...
auth_mechanisms = plain login
...
#!include auth-system.conf.ext
#!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-static.conf.ext
Create the users / passwords file and enter your users login info:

The format is username (ben@benosborne.com), a colon :{PLAIN}password followed by 6 colons :::::: (for the defaults!) eg. ben@benosborne.com:{PLAIN}some_password::::::

sudo nano /etc/dovecot/users

ben@benosborne.com:{PLAIN}some_password::::::
ben@blnk.co.uk:{PLAIN}some_password::::::

Basic SSL / TLS Encryption

We are going to enable basic SSL encryption for the domain specified in reverse DNS lookups (your primary domain, in my case blnkserver.com).

Get a Certbot certificate for your mail server primary domain:

sudo certbot certonly --apache -d blnkserver.com

It generates the key files and gives you the paths :

eg.
/etc/letsencrypt/live/blnkserver.com/fullchain.pem
/etc/letsencrypt/live/blnkserver.com/privkey.pem
Enable SSL in dovecot:

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

ssl = required
ssl_cert = </etc/letsencrypt/live/blnkserver.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/blnkserver.com/privkey.pem
Note that the < character indicates that dovecot use the file contents.

SASL (check user is allowed to send)

We want Postfix to check the Dovecot users for authorisation before sending email so we're going to enable a socket for that purpose. The request for authorisation goes to Dovecot via a socket and it looks up the user to check they are authorised to send messages. This prevents our server from relaying messages from unauthorised users.

In Dovecot, Edit 10-master.conf, service auth section and add a listener for Postfix:

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

service auth {
  ...
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    # Assuming the default Postfix user and group
    user = postfix
    group = postfix
  }
  ...
}
In 10-auth.conf ensure you support older mail clients (login method):

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

auth_mechanisms = plain login
Edit Postfix main.cf and enable SASL (the authentication method for sending emails):

sudo nano /etc/postfix/main.cf

# SASL DOVECOT
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

# support older clients
broken_sasl_auth_clients = yes

smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous

smtpd_tls_auth_only = yes
Before I could send to some clients eg. Gmail I needed to set up an spf record for the domain (it's just adding a TXT record to your DNS, I'll let you Google it!) and bind the Postfix server to one of my reverse IP's, for information about setting up reverse IP lookup see the article on Basic DNS:

sudo nano /etc/postfix/main.cf

# SETTING TO AN IP WITH REVERSE LOOKUP
smtp_bind_address=74.201.177.83
I also had to set my TLS settings to my Postfix server SSL certificates (because Postfix uses them to relay mail to enabled servers):

sudo nano /etc/postfix/main.cf

smtpd_tls_cert_file=/etc/letsencrypt/live/blnkserver.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/blnkserver.com/privkey.pem
smtpd_tls_security_level=may
Make sure you restart Postfix to pick up your new settings:

sudo systemctl restart postfix.service

Secure it a bit!

Also, one thing I like to do is obfuscate / secure that Dovecot users file (/etc/dovecot/users):

Firstly, change its name in auth-passwdfile.conf.ext to .users (prefixing a file with . in Linux makes it hidden in that dir):

sudo nano /etc/dovecot/conf.d/auth-passwdfile.conf.ext

passdb {
  driver = passwd-file
  args = scheme=PLAIN username_format=%u /etc/dovecot/.users
}

userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/.users
}
Rename the file:

sudo mv /etc/dovecot/users /etc/dovecot/.users

Change permissions on the file so that users cannot read it:

Take ownership for the dovecot user and group
sudo chown dovecot:dovecot /etc/dovecot/.users

Set rw for user, r for group and none for everyone else
sudo chmod 640 /etc/dovecot/.users

Restart dovecot:

sudo systemctl restart dovecot.service

Remember: From now on you'll want to sudo (become root) when you add a user and edit the /etc/dovecot/.users file:

sudo nano /etc/dovecot/.users

To view the logs for Postfix or Dovecot if you find yourself needing to diagnose a problem:

sudo journalctl -r -u dovecot.service
sudo journalctl -r -u postfix@-.service


Optional (for your web sites)

Set up PHP to send mail via Postfix.

Now that you've got Postfix set up, you might like to allow your PHP scripts to send mail using it.

Edit php.ini - the location may vary depending on the version of php you're using:

sudo nano /etc/php/8.2/apache2/php.ini

In the [mail function] section:

[mail function]
...
sendmail_path = /usr/sbin/sendmail -t
...
I had to add -t to get the mail to send via Postfix using the standard 'mail' function (Allows you to specify the To email address). I was sending the To address in the headers as well and I was finding that some providers moan about a duplicate To address in the headers (because Postfix was adding one) so I had to modify my code and remove the To address from the header.

Check your Postfix logs after you send, it shows the mail transaction and gives you feedback about the outcome, it'll tell you if and why it failed. On Debian 12, logs are accessed using journalctl (I like reverse order and sent to a pager, so f (forward), b (back) and arrow keys), I use:

sudo journalctl -r -u postfix@-.service

You now have a basic mail server set up with basic SSL. You can access your inbox with IMAP (securely) but it's a bit clunky because you have to specify your primary domain in your account settings to use SSL. The next article covers adding SSL certificates for each domain which will make setting IMAP accounts up in clients like Thunderbird a cinch!

Some clients (like Gmail) insist on using the reverse lookup domain SSL certificate for IMAP (blnkserver.com in my case) whereas other GUIs allow you to enter an appropriate domain for mail authentication (like mail.benosborne.com).




2025