Home > Documentation > Debian Tutorial

Debian Postfix/Dovecot Tutorial

This tutorial will help you configure your mail server for use of virtual domains/users under Postfix and Dovecot SMTP/POP/IMAP servers. It will also explain how to setup anti-spam and anti-virus protection for your users.

Tutorial is heavely based on tutorials writen by Johnny Chadda and Christoph Haas as I am too lazy to write them myself. :o) So, thanks to them for great work.

Tutorial is concentrated on Debian, for Red Hat based distributions please go to Red Hat tutorial.

Overview

The software we will use in this tutorial is listed below. Tutorial should not be version depended but there might be slight differences in configuration options between different versions of the software.

  • MySQL
  • Ratuus
  • Postfix
  • Postgrey
  • Amavis
  • Spamassasin
  • ClamAV
  • Dovecot
  • Horde/IMP
MySQL SETUP

This will be the core of our system since all email domains and users will be stored in MySQL database. So all software we install and configure in this tutorial will depend on it.

To install and run MySQL run next commands in command prompt.

# apt-get install mysql-server mysql-client
# update-rc.d mysql defaults
# /etc/init.d/mysql start

At this moment MySQL server is up and running, but it is not very secure - root account has no password. To solve this, login to mysql and issue this query:

# mysql -u root
mysql> DROP DATABASE test;
mysql> USE mysql
mysql> UPDATE user SET password=PASSWORD('new_password') WHERE user='root';
mysql> DELETE FROM user WHERE password='';
mysql> FLUSH PRIVILEGES;
DELETE query will delete all users without password set. Although it is safe to issue this query on a freshly installed database, think twice before running it on a database which was previously set up.

You could do the same with 'mysqladmin' command but I prefer not to use it. There is nothing wrong with it, it is just personal prefference.

Now it is time to create database and user which we will use for our mail server:

mysql> CREATE DATABASE mail;
mysql> GRANT ALL ON mail.* TO mail_user@'localhost' 
    -> IDENTIFIED BY 'some_password';
mysql> FLUSH PRIVILEGES;
RATUUS SETUP

Download latest version of Ratuus, unpack it in your web server's document root, setup up proper file permissions:

# chown www-data: include/db_config.php
# chown www-data: sm_comp/cache/
# chown www-data: sm_comp/templates_c/

# chmod 640 include/db_config.php
# chmod 755 sm_comp/cache/
# chmod 755 sm_comp/templates_c/

and point your browser to Ratuus installation page (http://www.your-domain.com/ratuus/install/). When you are prompted to enter database information you need to enter information about the database we created in the previous step.

DB Host: localhost
DB User: mail_user
DB Password: some_password
DB Name: mail

When you click Submit button Ratuus tables will be created and your database will be ready. Follow instructions to finish Ratuus installation.

POSTFIX SETUP

Now we have MySQL database ready so we can proceed with Postfix. First we need to install it:

# apt-get install postfix postfix-mysql
# update-rc.d postfix defaults

One of the good things about Postfix is the ease of the configuration. Not only the configuration options are very clear, but you don't need even to use an ditor for modifying config files. Postfix comes with utility called postconf which enables you to modify configuration directly from the command line. So, let's first set some basic options.

# postconf -e 'biff = no'
# postconf -e 'append_dot_mydomain = no'
# postconf -e 'myhostname = mail.mycompany.com'
# postconf -e 'myorigin = mycompany.com'
# postconf -e 'mydestination = localhost'
# postconf -e 'mynetworks = 127.0.0.0/8'
# postconf -e 'mailbox_size_limit = 0'
# postconf -e 'recipient_delimiter = +'

It should be pretty clear what this options are used for. If not you can check Postfix documentation for more information.

Now, we will instruct Postfix it should work with domains and users stored in MySQL database.

# postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql/virtual_domains_maps.cf'
# postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf'
# postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql/virtual_alias_maps.cf'

As you can see we will store MySQL settings in folder /etc/postfix/mysql/. The files stored there will have the connection parameters and also information about database layout. Content of these files is below, all that needs to be changed is database information (user, password, hosts and dbname fileds).

#/etc/postfix/mysql/virtual_alias_maps.cf
#========================================
user = mail_user
password = some_password
hosts = localhost
dbname = mail
table = alias
select_field = goto
where_field = address
additional_conditions = and active = '1'
# query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
#/etc/postfix/mysql/virtual_domains_maps.cf
#==========================================
user = mail_user
password = some_password
hosts = localhost
dbname = mail
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'
#query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
#/etc/postfix/mysql/virtual_mailbox_limit_maps.cf
#================================================
user = mail_user
password = some_password
hosts = localhost
dbname = mail
table = mailbox
select_field = quota
where_field = username
additional_conditions = and active = '1'
#query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'
#/etc/postfix/mysql/virtual_mailbox_maps.cf
#==========================================
user = mail_user
password = some_password
hosts = localhost
dbname = mail
table = mailbox
select_field = maildir
where_field = username
additional_conditions = and active = '1'
#query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'

We need to define where will Postfix store the data, and under which user it will run.

# postconf -e 'virtual_mailbox_base = /data/mail'
# postconf -e 'virtual_minimum_uid = 150'
# postconf -e 'virtual_uid_maps = static:150'
# postconf -e 'virtual_gid_maps = static:8'

So, in this case, all data will be stored in /data/mail, and user with the ID 150 and group ID 8 will be used. I created a new user 'vmail' for this purpose and gave it UID 150. GID 8 on Debian is used for 'mail' group.

We also need to instruct Postfix to use Dovecot for mail delivery.

# postconf -e 'virtual_transport = dovecot'
# postconf -e 'dovecot_destination_recipient_limit = 1'

Besides this, you will also need to modify /etc/postfix/master.cf file and add next two lines on the end of the file.

dovecot unix - n n - - pipe flags=DRhu user=
	vmail:mail argv=/usr/lib/dovecot/deliver -d $(recipient)
Please note that it is necessary to keep the empty space on the begining of the second line.

We want our server to be secure, so we need to allow only authenticated users to send email.

# postconf -e 'smtpd_sasl_auth_enable = yes'
# postconf -e 'smtpd_sasl_exceptions_networks = $mynetworks'
# postconf -e 'smtpd_sasl_security_options = noanonymous'
# postconf -e 'broken_sasl_auth_clients = yes'
# postconf -e 'smtpd_sasl_type = dovecot'
# postconf -e 'smtpd_sasl_path = private/auth'
# postconf -e 'smtpd_recipient_restrictions = permit_mynetworks
	permit_sasl_authenticated
	reject_unauth_destination
	permit'
DOVECOT SETUP

Time for Dovecot. Below is the complete Dovecot configuration file, I will explain important options later.

#/etc/dovecot/dovecot.conf
#=========================
base_dir = /var/run/dovecot/
protocols = imap pop3

protocol imap {
	listen = *:143
	# ssl_listen = *:993
}

protocol pop3 {
	listen = *:110
	# ssl_listen = *:995
}

log_timestamp = “%Y-%m-%d %H:%M:%S ”
syslog_facility = mail

mail_location = maildir:/data/mail/%d/%u

mail_extra_groups = mail
first_valid_uid = 150
last_valid_uid = 150
maildir_copy_with_hardlinks = yes

protocol imap {
	login_executable = /usr/lib/dovecot/imap-login
	mail_executable = /usr/lib/dovecot/imap
	imap_max_line_length = 65536
	imap_client_workarounds = outlook-idle delay-newmail
}

protocol pop3 {
	login_executable = /usr/lib/dovecot/pop3-login
	mail_executable = /usr/lib/dovecot/pop3
	pop3_uidl_format = %08Xu%08Xv
	pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}

protocol lda {
	postmaster_address = postmaster@mydomain.com
	sendmail_path = /usr/lib/sendmail
	auth_socket_path = /var/run/dovecot/auth-master
}

mail_debug = no
auth_verbose = no
auth_debug = no
auth_debug_passwords = no

auth default {
	mechanisms = plain
	passdb sql {
		args = /etc/dovecot/dovecot-sql.conf
	}
	userdb sql {
		args = /etc/dovecot/dovecot-sql.conf
	}
	user = nobody
	socket listen {
		master {
			path = /var/run/dovecot/auth-master
			mode = 0660
			user = vmail
			group = mail
		}
		client {
			path = /var/spool/postfix/private/auth
			mode = 0660
			user = postfix
			group = postfix
		}
	}
}

At the moment, we have configured just plain POP3 and IMAP, SSL support will be added later. With mail_location option we defined where will emails be stored (/data/mail/domain.com/user). Next are the user and group options, this should be set to the same user and group as Postfix. Than we set up some protocol specific options, together with workarounds for broken clients. And on the end we define authentication methods. We specify file from which Dovecot can get MySQL configuration (this is needed for fetching user information) and location of sockets. When configuring Postfix, we specified that authentication should be performed through SASL Dovecot mechanism (smtpd_sasl_path option). Therefore it is important to instruct Dovecot to add a socket for client authentication on the same place where Postfix expects it to be.

So, Dovecot should get all the data related to a user from MySQL. In dovecot.conf we specified that it should read MySQL connection parameters from file /etc/dovecot/dovecot-sql.conf. This file holds information not only about connection parameters, but also about queries Dovecot has to execute in order to get the data.

#/etc/dovecot/dovecot-sql.conf 
#=============================
driver = mysql

connect = host=localhost dbname=mail user=mail_user password=some_password

default_pass_scheme = MD5

password_query = SELECT username as user, password, '/data/mail/%d/%n' as userdb_home, 'maildir:/data/mail/%d/%n' as userdb_mail, 150 as userdb_uid, 8 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'

user_query = SELECT '/data/mail/%d/%n' as home, 'maildir:/data/mail/%d/%n' as mail, 150 AS uid, 8 AS gid, concat('dirsize:storage=', quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'

To be finished....