Virtual Users And Domains With Postfix, Courier And MySQL (Fedora Core 5)

Version 1.0
Author: Falko Timme

This tutorial is Copyright (c) 2006 by Falko Timme. It is derived from a tutorial from Christoph Haas which you can find at You are free to use this tutorial under the Creative Commons license 2.5 or any later version.

This document describes how to install a mail server based on Postfix that is based on virtual users and domains, i.e. users and domains that are in a MySQL database. I'll also demonstrate the installation and configuration of Courier (Courier-POP3, Courier-IMAP), so that Courier can authenticate against the same MySQL database Postfix uses.

The resulting Postfix server is capable of SMTP-AUTH and TLS and quota (quota is not built into Postfix by default, I'll show how to patch your Postfix appropriately). Passwords are stored in encrypted form in the database (most documents I found were dealing with plain text passwords which is a security risk). In addition to that, this tutorial covers the installation of Amavisd, SpamAssassin and ClamAV so that emails will be scanned for spam and viruses.

The advantage of such a "virtual" setup (virtual users and domains in a MySQL database) is that it is far more performant than a setup that is based on "real" system users. With this virtual setup your mail server can handle thousands of domains and users. Besides, it is easier to administrate because you only have to deal with the MySQL database when you add new users/domains or edit existing ones. No more postmap commands to create db files, no more reloading of Postfix, etc. For the administration of the MySQL database you can use web based tools like phpMyAdmin which will also be installed in this howto. The third advantage is that users have an email address as user name (instead of a user name + an email address) which is easier to understand and keep in mind.

This tutorial is based on Fedora Core 5 (i386). You should already have set up a basic Fedora system, as described here (for a x86_64 system, but the procedure for i386 systems is the same): and Plus, you should make sure that the firewall is off (at least for now) and that SELinux is disabled (this is important!), as shown on

This howto is meant as a practical guide; it does not cover the theoretical backgrounds. They are treated in a lot of other documents in the web.

This document comes without warranty of any kind! I want to say that this is not the only way of setting up such a system. There are many ways of achieving this goal but this is the way I take. I do not issue any guarantee that this will work for you!


1 Edit /etc/hosts

Our hostname in this example is, and it has the IP address, so we change /etc/hosts as follows:

vi /etc/hosts

# Do not remove the following line, or various programs
# that require network functionality will fail.               localhost.localdomain localhost  server1


2 Configure An Additional Repository For Fedora Packages

Some of the packages we have to install (such as courier-imap) are not included in the official Fedora repositories, so we have to add another repository to yum:

rpm -ivh

Afterwards, we must set enabled to 1 in /etc/yum.repos.d/enlartenment.repo:

vi /etc/yum.repos.d/enlartenment.repo

name=Enlartenment Repository for $releasever - $basearch

name=Enlartenment Repository for $releasever - Sources

Next, we import that repository's GPG key:

rpm --import


3 Install Postfix, Courier, Saslauthd, MySQL, phpMyAdmin

This can all be installed with one single command:

yum install ntp httpd mysql-server php php-mysql php-mbstring rpm-build gcc mysql-devel openssl-devel cyrus-sasl-devel pkgconfig zlib-devel maildrop courier-imap courier-authlib-mysql phpmyadmin pcre-devel openldap-devel

When you see this:

warning: rpmts_HdrFromFdno: Header V3 DSA signature: NOKEY, key ID 4f2a6fd2
Public key for ntp-4.2.0.a.20050816-11.FC5.i386.rpm is not installed
Retrieving GPG key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora
Importing GPG key 0x4F2A6FD2 "Fedora Project <[email protected]>"
Is this ok [y/N]:

please answer with y.


4 Apply Quota Patch To Postfix

We have to get the Postfix source rpm, patch it with the quota patch, build a new Postfix rpm package and install it.

cd /usr/src
rpm -ivh postfix-2.2.8-1.2.src.rpm
cd /usr/src/redhat/SOURCES
gunzip postfix-2.2.8-vda.patch.gz
cd /usr/src/redhat/SPECS/

Now we must edit the file postfix.spec:

vi postfix.spec

Change %define MYSQL 0 to %define MYSQL 1, add Patch0: postfix-2.2.8-vda.patch to the # Patches stanza, and finally add %patch0 -p1 -b .vda to the %setup -q stanza:

%define MYSQL 1
# Patches

Patch0: postfix-2.2.8-vda.patch
Patch1: postfix-2.1.1-config.patch
Patch3: postfix-alternatives.patch
Patch4: postfix-hostname-fqdn.patch
Patch6: postfix-2.1.1-obsolete.patch
Patch7: postfix-2.1.5-aliases.patch
Patch8: postfix-large-fs.patch
Patch9: postfix-2.2.5-cyrus.patch
%setup -q
# Apply obligatory patches
%patch0 -p1 -b .vda
%patch1 -p1 -b .config
%patch3 -p1 -b .alternatives
%patch4 -p1 -b .postfix-hostname-fqdn
%patch6 -p1 -b .obsolete
%patch7 -p1 -b .aliases
%patch8 -p1 -b .large-fs
%patch9 -p1 -b .cyrus

Then we build our new Postfix rpm package with quota and MySQL support:

rpmbuild -ba postfix.spec

You will see lots of warnings like these that you can ignore:

msg.h:12:1: warning: "/*" within comment
msg.h:14:1: warning: "/*" within comment
msg.h:33:1: warning: "/*" within comment
msg.h:34:1: warning: "/*" within comment
msg.h:35:1: warning: "/*" within comment
msg.h:36:1: warning: "/*" within comment

Our Postfix rpm package is created in /usr/src/redhat/RPMS/i386, so we go there and install it:

cd /usr/src/redhat/RPMS/i386
rpm -ivh postfix-2.2.8-1.2.i386.rpm

(In case you have problems creating the Postfix rpm package, you can download mine from here.)


5 Set MySQL Passwords And Configure phpMyAdmin

Start MySQL:

chkconfig --levels 235 mysqld on
/etc/init.d/mysqld start

Then set passwords for the MySQL root account:

mysqladmin -u root password yourrootsqlpassword
mysqladmin -h -u root password yourrootsqlpassword

Now we configure phpMyAdmin. Create /usr/share/phpmyadmin/

vi /usr/share/phpmyadmin/

$cfg[PmaAbsoluteUri] = '';
$cfg['Servers'][$i]['auth_type']          = 'http';

Then we change the Apache configuration so that phpMyAdmin allows connections not just from localhost:

vi /etc/httpd/conf.d/phpmyadmin.conf

Alias /phpmyadmin/ "/usr/share/phpmyadmin/"
#<Location "/phpmyadmin/">
#        Order allow,deny
#       Allow from

Then we create the system startup links for Apache and start it:

chkconfig --levels 235 httpd on
/etc/init.d/httpd start

Now you can direct your browser to and log in with the user name root and your new root MySQL password.

Share this page:

8 Comment(s)

Add comment


From: trcodera

ive been configuring fedora for almost two week already, i did all the things asked at perfect setup for fc5. im in the stage where i'm asked to set password for mysqladmin, but is says, access denied for user root@localhost, and i'm pretty sure i did something wrong and now i'm completely lost.. help..... i'm also planning of reinstalling fedora and go over all the process again.


Just a quick note to say thanks to both Falko Timme for the tutorial and bsquare for the 'addition instructions', some of which I needed, some I didn't.

All in all, great work.


Looking back over my notes, I did forget to mention that I did have some trouble getting amavis to run, giving errors about in syslog when issuing a /etc/init.d/amavisd start.

To get around this problem I did the following (from memory):-
yum remove perl-Net-DNS

..... which removes the following dependencies....

Then do :-
perl -MCPAN -e shell
install Net::DNS
install Mail::SPF::Query
>>> Y to dependencies 'Sys::Hostname::Long'
install Mail::SpamAssassin::Plugin::Razor2

Then reinstall :-
yum install perl-Mail-SPF-Query
yum install perl-Razor-Agent
yum install spamassassin
yum install amavisd-new

From: trcodera


From: bsquare

Before all, after having read several tutorials, I can say this one is very interesting.

Anyway, I would like to add some potentially needed instructions (it was the case for me).

 * the cyrus-sasl-plain package must be installed too, to avoid SASL Authentication error from postfix,

 * check if the "loadplugin Mail::SpamAssassin::Plugin" instruction are uncomment for DCC, Razor and Pyzor into *.pre files usually under /etc/mail/spamassassin directory,

 * dcc_add_header and  pyzor_add_header are deprecated (Cf., instead use respectively add_header all DCC _DCCB_: _DCCR_ and add_header all Pyzor _PYZOR_,

Anyway, amavisd remove a great part of the header created by spamassassin and so won't be shown into "final" mail (but it will be shown using spamassassin directly like command "spamassassin - t /path/of/mail").

 * to make amavis keep a part of the spamassassin header, add the following lines to your amavisd.conf :

$remove_existing_spam_headers = 0;

$sa_spam_report_header = 1;

 * For dccifd to work, DCCIFD_ENABLE must be set to 1 into the dcc_conf file (under /var/dcc directory in this tutorial), and the good path of the socket is /var/dcc/dccifd specified by the option dcc_dccifd_path (defined into the spamassassin file),

 * a link can be made from /var/dcc/libexec/rcDCC to /etc/init.d/dcc to "define" the dcc service (use then 'chkconfig --add dcc' for it to be automatically launched at startup),

 * it can be needed, to be sure that path are respected, to add the following lines to the file :

dcc_home /var/dcc/

razor_config /var/spool/amavisd/.razor/razor-agent.conf

bayes_path /var/spool/amavisd/.spamassassin/bayes

* for the spamassassin bayes system to be used, it is needed to make it learn with a mail corpus (with mbox format), one with at least 200 spams, and the other 200 hams. For instance, this format is used by Thunderbird. It is easy to create a mbox (a simple folder under Thunderbird) for each kind of mails and then call the sa-learn tool on each mbox, for instance :

/usr/bin/sa-learn -C /var/spool/amavisd/.spamassassin --showdots --ham --mbox /path/mbox/with/only/ham

/usr/bin/sa-learn -C /var/spool/amavisd/.spamassassin --showdots --spam --mbox /path/mbox/with/only/spam

It seems that the optimal number of each mails, for the best learning, is 1000 for each.

It is very important that the number of ham is upper than the one of spam. 

 * the use of the sa-update tool should be defined automatically under cron like

  - to begin, be sure that gnupg is installed, else use the command yum install gnupg,

  - import the spamassassin GPG Key :

cd /etc/mail/spamassassin
gpg --import GPG-SIGNING-KEY

  - sa-update --updatedir /usr/share/spamassassin      (can be used into cron table)


 * in any case, to check if personal rules and updated rules are valid, use the spamassassin --lint command  


There is still some little problems whose solution remain to be found :

 * why when starting clamd.amavis there is always a warning about a at least 7 days old database, although freshclam is frequently launched without any problem,

 * why sometimes the DCC header tags are not replaced by corresponding information (when DCC check failed with X-DCC complain).


As soon as I find answer, I will report them there.

Hoping this additional instructions will help.

Best regards. 



Just a small note, db4-devel is needed by postfix-2.2.8-1.2.i386

# rpmbuild -ba postfix.spec
error: Failed build dependencies:
        db4-devel is needed by postfix-2.2.8-1.2.i386

To fix yum db4-devel

# yum install db4-devel


I've been running a mail server built using this HOWTO for a while now.  I recently updated the entire server with a "yum update".  Email clients could no longer connect to the server via POP3 or IMAP if SSL was enabled.  I was getting errors like this in the error log: 

Oct 23 13:19:32 mailhost pop3d-ssl: couriertls: connect: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
Oct 24 10:36:13 mailhost imapd-ssl: couriertls: connect: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

I was able to fix this by editing the following files:


 I changed the TLS_PROTOCOL setting from SSL3 to SSL23 in both of these files:


Then, I restarted courier-authlib and courier-imap and things were working again:

 service courier-authlib restart
 service courier-imap restart

The following commands were helpful in testing things out:

openssl s_client -connect mailhost:993 -state -debug
openssl s_client -connect mailhost:995 -state -debug
openssl s_client -ssl2 -connect mailhost:993 -state -debug
openssl s_client -ssl3 -connect mailhost:993 -state -debug
openssl s_client -ssl2 -connect mailhost:995 -state -debug
openssl s_client -ssl3 -connect mailhost:995 -state -debug

I hope this helps someone else, as I spent way too much time trying to solve it.



One more thing to add to my last comment:

After the update, I also cannot send email.  The error logs show this:

 Oct 25 11:55:19 mailhost postfix/smtpd[10671]: warning: SASL authentication failure: cannot connect to Courier authdaemond: Permission denied
Oct 25 11:55:19 mailhost postfix/smtpd[10671]: warning: unknown[xx.xx.xx.xx]: SASL LOGIN authentication failed: generic failure

With a quick google I found a solution:

chmod o+x /var/spool/authdaemon

That solved it for me!