Postfix Sasl Courier MySQL DNS PostfixManager Antivirus howto

Huhh… hát elég sokat szoktam szarakodni, különböző servicek megalkotásával, főleg mert többnyire midnent SSL-es lehetőséggel akarok ellátniés mysqles adminisztrációval. Ilyenkor mindig lelek valmilyen howto-t, de mikor megint szügséges lenne elvész vagy már elérhetetlenné vállik. Ezért a mostani elég koplex mindennel foglalkozó howto-t learchiválom a blogba is, de amúgy itt érhető el.

This is a document that I give all of my efforts to make it wonderful…


          I had started this howto as a cookbook for installation of postfix in a virtual environment
only for me. I hadn´t wanted to read all installation steps of these softwares in each of my setups.

I thought this guide must not be only for me and then I have modified the  document to make it
suitable for others to understand. Finally I have published it in the hope that everybody (even a
person who is new to linux environment) can install postfix by using this guide. This  document
can also be useful for those who want to provide webhosting services. Since it contains instructions
for building automated web hosting service in Linux.
      Finally, lots of thanks to those who are mentioned in reference part.

Here are some information about what you are going to have after completing this tutorial.

1)   When you follow the steps explained in this document, instead of creating system accounts in
      /etc/passwd file you will be able to create them in a MySQL database and keep those passwords
      in clear text which means that you will be able to see your user’s passwords. Passwords will not

      be in encrypted form (Actually I may change this strategy very soon)
2)   You will be able to define quota for your user´s mailboxes.
3)   You can either give access to pop3, imap or webmail individually. e.g You give only webmail access
       and deny usage of smtp and pop3 services.

4)    With Squirrelmail webmail software, users can change their passwords by themselves and see
       their disk usage for e-mails quotas.
5)    Spamassassin software will filter spam and you will see spam messages rarely. It is a amazing

6)  Your users will use their e-mail addresses for authentication instead of username. What it means
       is that, you will not write your username in login page of webmail. Instead, you will write e.g email address.
7)   You will be able to add, delete users, manage your domains and add,remove aliases from PostfixManager

      software through web interface.
8)   You will be able to create your ftp accounts in a MySQL database and let authentication to be done
      through that database.
9)    Since, DNS is the primary system that allows all these systems to work, you will also install and administer

       Primary and a secondary DNS server and make this server more secure.
10) You will be able to redirect all your mails to an internal mail server or any other server
       around the galaxy :) This way, your mail server can be a mail gateway for many servers. You can use
       this gateway for spam and virus filtering.
11)   And finally, your users will be protected by Amavisd-new and Clamav from viruses or worms.


(09.04.2005)-Proftpd instllation is removed
                           -Courier-authlib is added because this is the new authentication method for
                           -Concepts section is added

                           – BIND section has been improved

(08.08.2004) –   0.3.1 version of PostfixManager has been released with a better interface
                          and better error checking

(31.07.2004) –    Amavisd-new and Clamav Antivirus Installation tutorial  are added to the
(30.07.2004) –   0.3.0 version of PostfixManager has been released. This new version
                           adds quota management and  user attribute modification capability e.g disabling

                           imap or pop3 access for any user
(24.07.2004)  –  Secondary DNS server and secure BIND installation tutorial document is added.
(17.07.2004)  –  SSL virtual host configuration for Squirrelmail is added.
(16.07.2004)  –  Some major changes have been made for some conceptual errors. Domains are not

                          added into postfix_transport table anymore. Virtual domains and transport domains have
                          seperate tables in MySQL from now. Since, problems occured when I have added smtp gateway
                          setup, this change become necessary. If you have installed postfix previously from this tutorial
                          I recommend you to make these changes in and mysql tables.
(12.07.2004)  – Bind DNS server installation tutorial is added

(12.07.2004)  – Proftpd with MySQL support installation tutorial is added
(07.07.2004)  – Apache2 , ssl and php installation tutorial is added
(02.07.2004)  – MySQL server installation tutorial is added. 
(30.06.2004)  – A new option (maildrop_destination_recipient_limit) is added to the postfix due to a problem

                            saying „mailer configuration error in postix log” . Please apply new maildrop setting to the
                            configuration file. Changes to the config are displayed in blue colour
                       – PostfixManager-0.2.1  is added for postfix web management interface

                       – Spamassassin individual user configuration setting has been added
                       – Postfix variable explanations has been added and some mistakes are corrected.


                   – SPF(Sender Policy Framework) integration into Postfix and BIND
                   – Mail list setup in virtual user setup.


I would like to thank Mehdi H. for his help and support for this page and Huseyin Caglar for his correctios.



                  Here is the definition of RFC2821 for a relay system:

A „relay” SMTP system (usually referred to just as a „relay”) receives
mail from an SMTP client and transmits it, without modification to
the message data other than adding trace information, to another SMTP
server for further relaying or for delivery.

                Is this a clear definition for you?  If not. I will make it clear with my example:

          I want to send an e-mail to my friend in California.
          My mail server is and my e-mail address is and destination
          e-mail address is When I press send button in mail client program, it

          makes a connection to machine’s 25. port and says that ” I have a message
          from to please send this message for me ” . In fact, total
          story is this. If you have permission to use mail server, it sends the message

          for you to address. This is RELAYING. Smtp relays your message for you.
                 But we should ask a question. How smtp server authenticates me? How does it know me?

          Usual methods are IP based or smtp-auth. You can define a network which is allowed to send
          emails through your mail server. However, What if you have a dynamic IP? Then smtp-auth
          solution comes.   

                Smtp-auth is a method used to authenticate users based on user and password
          information. Then you don’t need to define any network in your smtp server. You just
          enter your username and password in your mail client program and send e-mail from


TLS(Transport Layer Security):
                We live in fast growing technology world and every information that you send over Internet
           can be captured by anyone, if you haven’t taken necessary precautions. If you don’t use TLS,

           your username and password information is sent clear text over TCP channels. TLS allows you
           to use a secure communication channel. It is a service extention to smtp protocol. Read RFC2487
           for further information. But Wietse Venema(Postfix developer) says that:
                    You also turn on thousands and  thousands of lines of OpenSSL library code. Assuming that OpenSSL is written as carefully as Wietse’s own code, every 1000 lines introduce one additional bug into Postfix.




   Download the following softwares into /usr/local location and extract those in this directory
as described below. For our setup to work, we have to add some users. These users will be used
by courier and courier-authlib packages. You must create an account named courier for this purpose.

Since /usr/local is only writable by root user, create a user called courier and give ownership of /usr/local
directory to courier like below;

Note: Don’t think that I have chosen this account name because I like it. Courier package has been changed
a lot and you should use this account name for proper functioning of courier and courier-authlib.

# groupadd courier
# useradd courier -g courier -d /usr/local
# chown courier /usr/local

   Then proceed all the steps below with courier user. If you see a dollar sign ( $ ) in command prompt,
  please do that step as a unprevileged user(courier) ( not root, the King! ).
Otherwise you may encounter unexpected results. If you see a pound sign ( #) in the command prompt
do that step as root.

Note : Please use the latest versions of software below. These are the versions when
I have prepared this documentation. I hope new versions will not cause any problem
for your setup.

Berkeley DB
Cyrusl SASL
Courier IMAP
Courier Maildrop
Courier auth
Mysql Server
c-client (uw-imap)
Bind (DNS server)





Many of the above softwares can be downloaded into your linux box with the help

of wget utility allowing you to resume your downloads. You will see the usage of this
utility below.
            Throughout installation stages, you may see that some programs are already installed
in your system. If so, skip those installations please. The aim of this long document is not
only for showing the installation of postfix but also to introduce many aspects of
various programs not familiar to new linux users.
            Now, the long journey for Postfix is about to begin, sit back and be ready.



(If you have a working DNS server you can skip this DNS server setup part but
you may find useful information for taking bind into jail(chroot) environment)

            Many administrators usually do not care much about DNS system. Once DNS doesn’t

  work, you understand its meaning. Even if your IP structure works, it makes no sense. 
So we have to care DNS more than we do (deal?). Let’s begin with a brief introduction
telling what DNS looks like ?

            In daily Internet usage, we use letters to write e-mail and web page addresses.

Internet is managed by routers (devices or software on a computer) and these devices control
the flow of information by examining the fields of IP packets, which designate where the packet
comes from and goes to .

If you don’t know how a packet resembles, here is the well known IP Packet Header :)


       You see that there are two fields „Source IP Address” and „Destination IP Address”

in the IP packet. These source and destination fields can only have 32 bit addresses in IPv4.
In another word, these fields cannot be composed of letters. This means
that we should find a way of converting these human readable words and letters
(web page addresses, email domains) to the the form where routers can understand
to route the packet to its intended destination.
       Have you ever asked where these IP addresses come from and let the routing

       In this stage, DNS acts the leading role which makes this conversion possible. When you
write a web page address such as into your browser, here what happens;
(As a side note: We assume that you write this URL in a browser in Linux, since it
seems that Windows doesn’t respect TTL(Time To Live) values and cache responses from
DNS server for a constant periof of 24 Hours. For a more detailed explanation visit this page )

if you want to learn someting how a browser in linux cache data visit this page

How does name resolution work ?
Assume we have written in our browser

1) The application first checks some special database. For example, if you use a web browser,

your browser first check its internal memory cache before asking the query to DNS server.
if there is an answer, no need to ask further.
2) Application checks /etc/resolv.conf file for nameserver entries to perform the query.
3) Lets say that application got nameserver addresss as
4) name server first checks its cache whether there is an entry with the 
     related query or not. If it has the answer, no further query

5) Then name server checks to determine that this domain is local or not. Meaning
     that, this ns server is responsible for that domain or not.
6) If not, ns server takes Top Level Domain (TLD) part .tr and queries a root server
     for this .tr domain to learn which server is responsible for it and got the answer with IP address of
7) Then the process is going on like a chain. name server then askes for

     domain for that, who is responsible for This goes on until reaching the final
     name server which has the authoritive answer for
8) After receiving final record answer name server caches this data for further

            Now we are going to install BIND ( Berkeley Internet Name Daemon) and create our

domains for our Postfix virtual system to work. Since running this daemon as root can be dangerous,
we will put this daemon into a jail environment.( In this environment, daemon is restricted to live
in a predefined directory location like a prisoner in jail:)


#cd /usr/local
#wget -c

#tar zxf bind-9.3.0.tar.gz
#cd bind-9.3.0
#./configure –prefix=/usr/local/bind
#make install
#mkdir -p /usr/local/bind/{etc,namedb,dev,var/run}

(The above command creates all necessary directories in one step – You can use curly brackets for this purpose)

For SElinux systems, I have seen that  installation differs. You must be so careful about SElinux systems.
When above stages are finished, BIND is installed into /usr/local/bind base directory.
Now create configuration files(depicted as red paths) of BIND below


options {
        directory „/namedb”;
        version „I do not give any version info”;
         pid-file „/var/run/”;
         allow-transfer { none ;};


zone „.” IN {
        type hint;
        file ” /etc/named.root „;



Create this /usr/local/bind/etc/named.conf file which is the main configuration file for BIND
We will write all instructions into this file.  Options block is for general settings and zone blocks are for setting values for our domains. Specified file PATHs in named.conf file are relative to /usr/local/bind directory. e.g directory „/namedb”   line actually refers to /usr/local/bind/namedb directory, not /namedb directory . Another example, /var/run/ file is actually the file /usr/local/bind/var/run/ I hope it is clear now.Don’t forget that bind is in a jail environment.
So you should think every path relative.
        In the named.conf file in zone „.” section, there is a file called ” named.root ” . This is the file which contains all IP addresses of root servers . Rarely, root server IP addresses change.

You can obtain the latest named.root file from address. Lets download named.root file to /usr/local/bind/etc directory.



#cd /usr/local/bind/etc

           We have completed main configuration file a little bit, now create jail directories and
system account for bind.

#groupadd named
#useradd named -d /usr/local/bind -s /bin/false -g named -c „DNS Jail User”
#mknod /usr/local/bind/dev/null c 1 3
#mknod /usr/local/bind/dev/random c 1 8
#cp /etc/localtime /usr/local/bind/etc/

Since we have installed this system into a jail environment, we will have some problems while logging
dns records. Linux perform this logging by sending records to /dev/log socket but this location is out of our
jail :(  Let’s make some tricks.. and change syslog behaviour. Below is an explanation about how you
can change syslogd configuration. Be careful that, lines that have to be changed are not in syslog
daemon configuration file . You must make modification in startup configuration of syslog daemon
program and this startup location differs as distribution differs as defined below;

Startup file for syslog daemon in Redhat is at location ” /etc/rc.d/init.d/syslog „.
(If it didn’t change after my last use of Redhat). There is a line in this file like;

daemon syslogd -m 0
change this line into the line below .

 daemon syslogd -m 0 -a /usr/local/bind/dev/log

Add  ” -a /usr/local/bind/dev/log ” in /usr/bin/syslogd line in /etc/rc.d/rc.inet2  file

Sysklogd startup file is ” /etc/init.d/sysklogd „. Edit file and change line SYSLOGD=””
to SYSLOGD=”-a /usr/local/bind/dev/log” . Thanks to William Golden for debian setup
and correction about var directory permission.

NOTE: „- a” switch in syslogd startup lines doesn’t mean that syslogd will do logging
to /usr/local/bind/dev/log, it defines an additional socket that syslogd has to listen

Make directories more secure

#chown named:named /usr/local/bind
#chown -R named:named /usr/local/bind/var

#chmod 700 /usr/local/bind


Start DNS Server

#/usr/local/bind/sbin/named -u named -t /usr/local/bind -c /etc/named.conf

Check that daemon is started or not

#ps aux | grep -v grep | grep named


If you see the output which says that daemon is running…it is great you did it.

If you reach this point without any problem, let’s do your first query in your DNS server.
#host has address

You will probably have a similar output like above. Your dns server is working and
answer your queries. Now we are going to create a sample domain with you.

   Let’s say that you have bought a domain name called from a registery such as , etc. and you want to accept e-mails for this domain in your mail server.

Do you want to learn ? keep reading then :)

      You must create an entry in named.conf file for each of your domain. For this,
Add  the lines below  to the bottom of /usr/local/bind/etc/named.conf file. This way you tell
that you have a domain called which has the domain configuration file

      This file will be located under /usr/local/bind/namedb/ . Remember!!! there is a
directory section in named.conf file. It defines where zone files are located.


zone „” {

        type master ;
        file ” „;
        allow-query {any;};
        allow-update { none; };  


Now after defining the named of the configuration file it is time to create the content of zone file
for domain


$TTL 14400

@               IN SOA (

                        2005030601      ; serial
                        7200           ; Refresh
                        7200            ; Retry
                        604800          ; Expire

                        86400 )         ; Minimum                            IN      NS                            IN      A                    IN      A                   IN      A                             IN     MX 5              IN     A  IN     A



This is our zone file. Zone files need TTL (time to live) values. These values define
how long other DNS servers should cache your name information without asking your

DNS server again. If this TTL value is 86400 secs  , once a name server  asks  IP address
of, it will not ask your server for the next 86400 secs (1 day :) in SOA line is the name server responsible for this domain name and is the
administrator e-mail address for this domain. Be careful it is an e-mail address (
but you must put „.” instead of @ character.

       Another thing, you have to increment serial number by one in each change of this file.
Important line for our mail server is ;                IN      MX 5

  This line says that mails sent for domain must be sent to
machine which has the IP address of  . Number 5 is the priority value and it is only
meaningful when there are two mail servers co-exist. Now….increment your serial number for the
first time and reload your bind DNS server. Let’s do it..

#kill -1 `pidof named`

Informational Note: For those who are new to Linux,  I would like to explain  the command issued above. Backtick

sign ( ` ) in linux allows you to run a command. This allows you to take output of a command and use that
output as an input of an another command. In the example above, pidof command is the command which gives
the process ID of named program. Output of `pidof named` command becomes an input for kill -1 command.
By this way, you don’t have to write ” ps ax ” and learn process ID of the program and use kill command.
This saves your time.

    We have sent a HUP signal to named daemon and dns server reloaded its configuration file.
Now it knows what the mail exchanger (responsible mail server) is for domain .
Let’s ask it to new dns server whether it knows or not.

#host -t mx mail is handled by 5

We have asked for the mail exhanger of and DNS server said that is
responsible for domain. Now we have a fully functional DNS server which can
answer for our new domain.We can go to the next step to accept mail in our mail server.


(If you don’t need a secondary DNS server please skip this step too)

        If one of your aims is to become a good DNS Administrator, you should read RFC1034
and 1035 after reading this tutorial. How DNS works is explained in detail in those documents.
As for our document, RFC says that if you have an authoritive DNS server for a domain, you must
locate your DNS servers in physically different networks. If one of your servers is in one ISP,
you should put your secondary server in another ISP, if you have no tolerance for network failures.
This is just for high availability purposes. If you have a small site, probably, you will not need any one
of these.

       Secondary DNS server is a server transferring domain information from the master one at a
predefined time interval. In fact, there is no difference between a master and slave server from the point
of resolver (e.g you)  . When you try to access a site called and if there are two servers serving
that domain, one of the DNS servers will give dns reply to you resolver. If one server is down for any reason,
the other one continues to answer queries. You must understand that none of these servers are redundant.
They both answer queries for the zones that they are responsible for.
       In my document, both slave server and secondary server have the same meaning. Additionally,

master server and primary servers have also the same meaning so don’t confuse when I interchange words.
       After giving a brief introduction about DNS system, let’s configure our secondary server.

  In your second linux server, install bind, like the one above BUT do not create any zone file. Since secondary
will transfer zone files from the master.
      Only difference will be in named.conf configuration file. For our setup, ( is
your master DNS server and ( is your slave DNS server.

Now, create files below in your second linux server.

options {
        directory „/namedb”;
        version „I do not give any version info”;
         pid-file „/var/run/”;
         allow-transfer { none ;};


zone „.” IN {
        type hint;
        file „named.root”;
zone „” {
        type slave ;

         masters {; };
        file „”;
        allow-query {any;};
        allow-update { none; };  


Have you noticed the change in named.conf file?  This time, instead of writing ” master ” to the
type line, we have written ” slave ” since this domain is slave and retrieve its record sets from the
master server.
        Ok … we have set up our secondary server and it is ready for transferring zone information but
Is master server ready for accepting zone transfer requests coming from this secondary server ?
No.. we should tell the master server to accept AXFR (transfer type) requests originated

  from IP address. Now open named.conf file in the primary server and change ;


allow-transfer { none ;};


allow-transfer { ;};

This line permits transfer requests from secondary name server. When you make any
little change to domain in the primary server, change will be reflected to the secondary server
  as a notify. So you will not have to make the same change on the secondary server.
    When you add another domain to the primary server, you have to add configuration lines for
your new domain to the named.conf file of secondary server as mentioned above. Reload servers and
you will see that secondary server copies zone files from the master and write those new zone files
under /namedb directory. It is amazing , isn’t it ? :)


I would want to do more on security of these primary and secondary server setups but I know that
when I add more functionality, things are getting more complex and the probability of making mistakes
increases:) I don’t want this document to be a error-rich document. I just would like to tell some parts that
you should consider below;

1) RFCs suggest that you should not provide caching services on the server that provides

    authoritive data for zones. Your cache-only server and authoritive server serving your zones
    should not be on the same server. For example, you should not use these authoritive servers
    in your /etc/resolv.conf files for cache purposes. This is not recommended from the security
    point of view. You can read requirements for root servers RFC.

2) We have installed our DNS servers to serve both authoritive data and cache information. I have just

     done this to demonstrate how this system works. To disable caching service of these servers
     you can remove;
zone „.” IN {
                         type hint;
                        file „named.root”;

     these lines. When you remove these lines, DNS server will not be aware of root servers’ IP addresses
     and can not answer for NS queries for zones that it is not currenly authoritive for. It is a nice trick right :)

3) You should also disable recursive queries on your DNS server. You don’t have to make all queries

       recursively. Your servers don’t have to do all the stuff for queries. This will also save bandwidth, if you
       have lack of it. Add this line to named.conf in between options block.  

allow-recursion { none; } ;

        This way, you will not provide recursive service to any resolver and every resolver will only
         receive NS IP addresses of the next responsible  DNS server for that zone and not the answer of

         the query.

4)    If you are a ultra secure person :) , you can also disable any query except your zone files from any client.
      This way, your server will  say „CONNECTION REFUSED” to the resolvers which want to query other
       domains that you are not responsible for. If you had paid attention there is a line

allow-query {any;};
      in every zone block that I have added. This says that, server allows any query for this domain. When you add
allow-query { none; };
      line to options block of named.conf file , DNS server will not allow any query other than your domains and
      refuse connections.

I know that these options have close relations when doing their task. When you mainly use DNS, you can discover
how they are needed.

           One of my aims was to write a good „Secure DNS” document. I hope I did small percent of what I wanted…
I think this DNS information is a little more for a postfix document but I believe that when DNS is not configured
properly, there is no way of a MTA to work.

Now, lets first start with OPENSSL installation.


Just to remember, all untar operations are done under /usr/local directory

#su – courier
$cd /usr/local
$wget -c
$tar -zxf openssl-0.9.7g.tar.gz
$cd openssl-0.9.7g
$./config shared

$make test
#make install
# echo „/usr/local/ssl/lib” >> /etc/


$su – courier

$cd /usr/local
$wget -c
$tar -jxf httpd-2.0.53.tar.bz2
$cd httpd-2.0.53
$./configure –prefix=/usr/local/apache2 \
–enable-so –enable-ssl=shared –enable-rewrite=shared \

#make install

Lets make directories and files secure

#cd /usr/local/apache2
#chown 0 . bin conf logs
#chgrp 0 . bin conf logs
#chmod 755 . bin conf logs
#chown 0 /usr/local/apache2/bin/httpd
#chgrp 0 /usr/local/apache2/bin/httpd

#chmod 511 /usr/local/apache2/bin/httpd

Apache Security:
    We should also prevent apache giving server version and type
information to the outside. By default apache gives information about its version
and some of application it uses. e.g php,openssl. We don’t want to give this info
to the others right?


Edit file:
/usr/local/apache2/conf/httpd.conf and find these two lines and modify them as below;
ServerTokens Prod
ServerSignature Off

#UserDir public_html
Comment this UserDir line too.


#cd /usr/local/ssl/certs
#/usr/local/ssl/bin/openssl req -new > webmail.csr
{This command will ask you some questions for ssl certificate. The

important answer is for „Common Name” question. Your answer should be the web
page address where you will serve ssl site. e.g, if you give another name
here, you will have CN mismacth problems in apache}

# /usr/local/ssl/bin/openssl rsa -in privkey.pem -out webmail.key
#/usr/local/ssl/bin/openssl x509 -in webmail.csr -out webmail.crt -req \ -signkey webmail.key -days 999
#mkdir /usr/local/apache2/conf/ssl.crt 

#mkdir /usr/local/apache2/conf/ssl.key
#cp webmail.key /usr/local/apache2/conf/ssl.key/ webmail.key
#cp webmail.crt /usr/local/apache2/conf/ssl.crt/ webmail.crt

Open /usr/local/apache2/conf/ssl.conf and convert lines below

SSLCertificateFile /usr/local/apache2/conf/ssl.crt/server.crt
SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/server.key


SSLCertificateFile /usr/local/apache2/conf/ssl.crt/webmail.crt
SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/webmail.key

Would you like to make these changes without manually editing ssl.conf file?
Here comes my perl solution:)

#cd /usr/local/apache2/conf/
#perl -pe ‘s/ server.crt /webmail.crt/g ; s/ server.key /webmail.key/g’ ssl.conf > ssl.conf.tmp
#cp ssl.conf.tmp ssl.conf

Above commands contain regular expression which you should be so familiar if you
want to be a Linux system administrator. What it does is that, searching and replacing
server.crt and server.key statements with webmail.crt and webmail.key words.

This certificate file modification is just for apache2 to work for the time being. We will come back

to this subject later. More detailed ssl configuration about ssl virtualhost is written at the end
of the document in Virtualhost-SSL configuration part.

Now you can probably :) start apache-ssl safely with the command;

#/usr/local/apache2/bin/apachectl startssl

Apache is installed. Would you like to make a performance test on this fresh apache :) ?

There is a utility called ” ab ” in apache which allows us to make benchmarking.

#/usr/local/apache2/bin/ab -n 100 -c 10

Above command will make a performance test on apache. ( Don’t forget to
write ending slash in the address, otherwise it won’t work.

Paramater Meanings  

” -c ” stands for 10 multiple requests to perform at a time and
” -n „ stands for number of requests.


  We are going to install php with imap support to use our webmail but php

requires c-client library for this to work. For reference click

#cd /usr/local
#wget -c
#tar -Zxf imap.tar.Z
#cd imap-2004c1

#make slx SSLTYPE=none
(Answer Y to the question asked when above command is issued)
#mkdir include
#mkdir lib
#cp c-client/*.h include/
#cp c-client/*.c lib/

#mv c-client/c-client.a lib/libc-client.a


It is time for MySQL database server setup. First we will do some
preparation for the server. Steps are explained below.
Attention: I recommend you to not to install 4.1.x version of MySQL . I have experienced problems in this version.


# cd /usr/local
#wget -c
Create mysql user and group
#groupadd mysql
#useradd -g mysql mysql
Unpack mysql archive

# tar -zxf mysql-4.0.24.tar.gz Change your working directory to new mysql directory
#cd mysql-4.0.24/
Configure mysql with /usr/local/mysql base directory
#./configure –prefix=/usr/local/mysql
Build source files
Install compiled files to the directory specified in prefix
#make install

Mysql uses a configuration file to determine some parameters on startup. It must be modified depending on your machine’s capacity. Copy mysql configuration file and startup script for a medium sized system to /etc/my.cnf .  Read my-*.cnf files for your own system on the untarred location of MySQL. Those files allow you to chose which file to use for your system.
#cp support-files/my-medium.cnf /etc/my.cnf
#cp support-files/mysql.server /etc/init.d/
#chmod 755 /etc/init.d/mysql.server
Go to base directory and create MySQL grant tables with mysql user (If this MySQL is your second
MySQL installation in your linux, defaults-file variable can be set to your new conf file)

#cd /usr/local/mysql
/mysql_install_db –user=mysql

Change ownership of binaries to root and ownership of data directory to mysql user
#chown -R root  .
#chown -R mysql var
#chgrp -R mysql .
Introduce new libraries to our Linux
#echo „/usr/local/mysql/lib/mysql” >> /etc/
#ldconfig Start MySQL daemon

#/etc/init.d/mysql.server start
Connect to the MySQL server and give mysql root password. Since, there is no default root password
Please pay attention to this part, I have seen many who don’t give any root password to their servers.

#/usr/local/mysql/bin/mysql -u root

mysql> use mysql;
mysql> update user set password=Password(‘ 1234 ‘) where user=’root’;

mysql> flush privileges;

Now, MySQL will ask password for root user, enter password and your are in… then exit and continue
to the rest of the setup. You will create some tables in this database server later.

#/usr/local/mysql/bin/mysql -u root -p

Add your mysql binaries path to your environmental variable PATH not to face with
mysql_config errors in courier imap compilation stage :) Don’t forget to add this into your /etc/profile file

#export PATH
#echo „PATH=$PATH:/usr/local/mysql/bin” >> /etc/profile

#echo ” export PATH” >> /etc/profile


1.2.2 version is necessary for proper functioning of Clamav

#cd /usr/local

#wget -c
#tar -zxf zlib-1.2.2.tar.gz
#cd zlib-1.2.2
#make install


Berkeley DB is a requirement for Courier-imap server or Postfix.
If you have problems while installing postfix saying the file „db.h” isn’t found
then visit

$cd /usr/local
$wget -c
$tar -zxf db-4.3.27.tar.gz

$cd db-4.3.27/build_unix/
$../dist/configure –prefix=/usr/local/bdb
#make install
#echo „/usr/local/bdb/lib” >> /etc/


Before installing CYRUS, you should know that mysql libraries are assumed to be
stored in /usr/local/mysql/lib/mysql and header files  are in /usr/local/mysql/include/mysql
directories. If you are using Redhat, your mileage may differ a little bit. Yours will be probably
in /usr/lib/mysql or something like that. So don’t panic if cyrus displays errors about libraries then start

looking for where your libraries are stored.

$cd /usr/local
$wget  -c
$tar zxf  cyrus-sasl-2.1.20.tar.gz

$cd cyrus-sasl-2.1.20
$export CPPFLAGS=”-I/usr/local/mysql/include/mysql”
$./configure \
–enable-anon \
–enable-plain \
–enable-login \
–enable-sql \
–disable-krb4 \
–disable-otp \

–disable-cram \
–disable-digest \
–with-mysql=/usr/local/mysql/lib/mysql \
–without-pam \
–without-saslauthd \
–without-pwcheck \
–with-dblib=berkeley \
–with-bdb-libdir=/usr/local/bdb/lib \
–with-bdb-incdir=/usr/local/bdb/include \

–with-openssl=/usr/local/ssl \
#make install
#ln -s /usr/local/lib/sasl2 /usr/lib/sasl2
#echo „/usr/local/lib/” >> /etc/


This the attention zone don’t go witnout looking at these warnings;
Attention1: Many people reported me that they have experienced problems
installing postfix saying „the db.h file is not found” . I haven’t received such an error
but you can have an answer for this error probably at

or one of the senders (Fraxon Hector Lubingu) told me that he solved this problem
with the commands below;
#ln -s /usr/local/bdb/include/db.h /usr/include/db/db.h
#ln -s /usr/local/bdb/include/db.h /usr/include/db.h

Since I am testing this setup on a Gentoo environment, the above commands don’t work
for me. I don’t have a /usr/include/db directory but if you have, these solution suggestions

may have a meaning for you.

Attention2 : If compiling postfix fails with ;

undefined reference to `pthread_condattr_setpshared’
undefined reference to `pthread_mutexattr_destroy’
undefined reference to `pthread_mutexattr_init’

undefined reference to `pthread_mutex_trylock’

Add the „-lpthread” library to the „make makefiles” command.
This means that your make makefiles command will be ;

make makefiles ‘CCARGS=-DHAS_MYSQL \
-I/usr/local/mysql/include/mysql  -DUSE_SASL_AUTH \
-I/usr/local/include/sasl -I/usr/local/bdb/include \

-DUSE_TLS -I/usr/local/ssl/include/openssl ‘ \
  ‘AUXLIBS=-L/usr/local/mysql/lib/mysql -lmysqlclient \
-lz -lm -L/usr/local/lib -lsasl2  -L/usr/local/bdb/lib\
-L/usr/local/ssl/lib -lssl -lcrypto -lpthread ‘ ‘

instead of the one written below.

I hope you will not face with any problems other than these. Since I have

implemented this documentation, I have mainly received these error reports
from those who used this document. Now start installing postfix, if you receive
any errors return here and try to find the answer.

#cd /usr/local
#groupadd postfix -g 1000
#useradd postfix -u 1000 -g 1000
#groupadd postdrop

$wget -c
$tar -zxf postfix-2.2.2.tar.gz
$cd postfix-2.2.2
$ make makefiles ‘CCARGS=-DHAS_MYSQL \
-I/usr/local/mysql/include/mysql  -DUSE_SASL_AUTH \
-I/usr/local/include/sasl -I/usr/local/bdb/include \
-DUSE_TLS -I/usr/local/ssl/include/openssl ‘ \
  ‘AUXLIBS=-L/usr/local/mysql/lib/mysql -lmysqlclient \

-lz -lm -L/usr/local/lib -lsasl2  -L/usr/local/bdb/lib\
-L/usr/local/ssl/lib -lssl -lcrypto’
#make install

Postfix will ask some configuration questions. If you don’t use sendmail,
don’t hesitate to accept default values.



Libjpeg and Libpng have to be downloaded for the compilation of PHP to be done
without any problem.

Libjpeg Package(Dependency for PHP)

#wget -c

#tar �zxf jpegsrc.v6b.tar.gz
#cd jpeg-6b
#make test
#make install
#make install-lib
#make install-headers

Libpng Package (Dependency for PHP)

#wget -c
#tar �jxf libpng-1.2.8.tar.bz2
#cd libpng-1.2.8
#cp scripts/makefile.linux Makefile
#make install

Now install PHP software (Don’t forget to change imap source dir in configure step)

#cd /usr/local
#tar -jxf php-4.3.11.tar.bz2
#cd php-4.3.11
#./configure \
–with-apxs2=/usr/local/apache2/bin/apxs \
–with-mysql=/usr/local/mysql \
–enable-track-vars \
–with-openssl=/usr/local/ssl \

–with-imap= /usr/local/imap-2004c1 \
–with-gd \
–enable-ftp \
–enable-sysvsem \
–enable-sysvshm \
–enable-sockets \
–with-gettext \
–with-jpeg-dir=/usr/local \
–with-zlib-dir=/usr/local \


#make install
#cp php.ini-dist /usr/local/lib/php.ini

Note: For the time being, you must set register_globals=On in /usr/local/lib/php.ini file if you are going to use PostfixManager. If you do so, please edit php.ini file and change this setting. I am working on a more advanced version of PostfixManager which doesnt use register globals.

Add the lines written below to /usr/local/apache2/conf/httpd.conf. Where you place these lines doesn’t make any difference actually but find other AddType paramaters in httpd.conf
and place these below those paramaters.

AddType application/x-httpd-php .php
AddType application/x-httpd-php .phtml
AddType application/x-httpd-php .php3

Add also index.php   to DirectoryIndex in httpd.conf  so that apache can search for

index.php by default when a directory is requested.

DirectoryIndex index.html index.html.var index.php

Restart your apache and now you have ssl and php enabled apache. Keep installing :) don’t get bored I know it is very long…:) but I tried to eliminate most mistakes. I hope this helps you a little bit.

#/usr/local/apache2/bin/apachectl restart


Courier has been changed a lot. I sometimes become tired to update this document. It changes really fast.You must install this authentication library for proper functioning.

If you use redhat instead of gentoo or slackware, you have to add ” –with-redhat ” option to the
    configure step below.

#su – courier
$wget -c
$tar -jxf courier-authlib-0.55.tar.bz2

$cd courier-authlib-0.55
$./configure \
–with-mysql-includes=/usr/local/mysql/include/mysql/  \
–with-authmysql –with-authmysql=yes
#make install
#make install-configure


Here are some important paramaters that we should reherse
before going further.

1) You have to extract courier-imap archive as a standard user and compile it with the same user
   as well. I am not joking. Courier-imap documentation wants us to do it in this way.
2) If you use redhat instead of gentoo or slackware, you have to add ” –with-redhat ” text to the

    configure step below.
3) Configure step of courier-imap takes a bit time. Don’t think that this step has entered into a loop
    in fact it hasn’t.

$cd /usr/local
$wget -c

$tar jxf courier-imap-4.0.2.tar.bz2
$cd courier-imap-4.0.2
$ ./configure  –enable-workarounds-for-imap-client-bugs \
–with-authchangepwdir –enable-unicode –with-trashquota
#make install
#make install-configure

NOTE:   If you encounter some problems while receving mail from pop3 or imap server
of courier please consult to courier-imap bug page


#groupadd vmail -g 1001
#useradd vmail -u 1001 -g 1001

#su – courier
$wget -c
$tar -jxf maildrop-1.8.0.tar.bz2
$cd maildrop-1.8.0
$export CPPFLAGS=”-I/usr/local/mysql/include”
$export LDFLAGS=”-L/usr/local/mysql/lib”
$./configure –enable-maildirquota \
–enable-maildrop-uid= 1001 \
–enable-maildrop-gid= 1001 \

#make install
#chown root /usr/local/bin/maildrop
#chmod u+s /usr/local/bin/maildrop


CPAN network will do everything for you and commands issued

below will install spamassassin binary to /usr/bin/spamassassin path. Be aware that,
this program is not a daemon. You don’t have to run it yourself and wait for connection.
In fact you don’t have to worry after installing this software where spamassassin is
and how it works.

if you use perl 5.8, make the following changes in LANG variable and don’t forget to add these

to your startup configs too. ( /etc/profile )

# export LANG=en_US   
# perl -MCPAN -e shell 
cpan> o conf prerequisites_policy ask
cpan> install Mail::SpamAssassin

cpan> q
# echo „export LANG=en_US” >> /etc/profile

Now, if everything went ok, you probably have spamassassin at /usr/bin/spamassassin
Your system-wide spamassassin configuration file will be installed into the following location
automatically: /etc/mail/spamassassin/
     Your user specific spamassassin configuration file will be specified in the installation

of maildrop software. If you want to define user specific rules you must set some directives
in maildrop configuration file which will be explained in maildrop section.



Here, I should explicitly define default values not to cause any misunderstanding.

Default values for MySQL are below. Adjust them for your setup.

mysql root password                                              :          1234

database username(for virtual system)                  :          vmailuser
database username password                                :         password123

    Connect to the mysql database server and create a database named mail . Then add a new database
  user called vmailuser with „password123 ” password. By doing these steps as mentioned below,
you  will  also give full privilege to vmailuser on mail database.

NOTICE: All three GRANT lines at the bottom are necessary. Please apply all of them, otherwise you may
  face with an error like ” SASL LOGIN authentication failed ” in your log file:) I assume that
is your hostname. I mean it is the output coming from „hostname” command.

#mysql -u root -p1234

mysql>GRANT all privileges on mail.* TO vmailuser@localhost IDENTIFIED BY ‘password123’ ;
mysql>GRANT all privileges on mail.* TO vmailuser@ IDENTIFIED BY ‘password123’ ;
mysql>GRANT all privileges on mail.* TO vmailuser@ IDENTIFIED BY ‘password123’ ;

      We have created our database and user, now it is time to insert data to our new database.

Write the lines written below in the box into a file called virtual_user.sql after paying attention
to the warnings below.

         Please read these warnings before creating tables below. Since there may be some
default values which  you may want to set for future use.

1) UID and GID values in postfix_users table which will be created below, must be the same as

vmail system user’s IDs. i.e users that we have added with useradd commands to /etc/password file
      In my setup vmail user ID and GID 1001. You can see that I have set these values in virtual_user.sql
     (For newbies: These id and gid numbers are 3. and 4. fields in /etc/passwd file)

2) There are four fields providing great flexibility in postfix_users table. Two of these fields ;

     disablepop3 : If this field’s value is ” 1 ” for a user, that user can not log in to his pop3 account instead
     you recieve a message something like ” POP3 access is disabled ” . If the field is ” 0 ” pop3 access is allowed.
disableimap :  When this field’s value is „1” for a user, that user can not log into his imap account and

     recieve a message somethink like „IMAP access is disabled”. If the field is „0” imap access is allowed.
     We can’t use disablewebmail field, if we don’t use Sqwebmail software.  But you can disable webmail
     access, by disabling imap for a user through squirrelmail. Indirectly, this is what I do for my setup since
     we don’t use Sqwebmail.

3) By default in this setup, users are allowed to send e-mails by relaying through your mail

server after a successful sasl authentication. You can ask me that if user’s authentication is
successful then we should allow him to send email through our smtp server. Is this always true?
What if you want your users to send mails through only webmail? Then you need an extra field.
Instead I have added an extra field to postfix_users table so that I can enable or disable  smtp usage 
based on where user entered into my system.
     If smtpaccess field in postfix_users table is „ N „, users can not use your smtp server for sending mail

even  after succesfull authentication. This is a solution for me to provide sending mail through only webmail
and not to allow all users to send their mails using my mail server. I hope you understood what I am
trying to do. If you didn’t, you will see how it is necessary when you use this system.

Save these lines in this box to virtual_user.sql file

CREATE TABLE postfix_alias (
  id int(11) unsigned NOT NULL auto_increment,
  alias varchar(128) NOT NULL default ”,
  destination varchar(128) NOT NULL default ”,

CREATE TABLE postfix_relocated (
  id int(11) unsigned NOT NULL auto_increment,
  email varchar(128) NOT NULL default ”,
  destination varchar(128) NOT NULL default ”,

CREATE TABLE postfix_transport (
  id int(11) unsigned NOT NULL auto_increment,
  domain varchar(128) NOT NULL default ”,
  destination varchar(128) NOT NULL default ”,
  UNIQUE KEY domain (domain)


CREATE TABLE postfix_virtual_domains (
  id int(11) unsigned NOT NULL auto_increment,
  domain varchar(128) NOT NULL default ”,
  destination varchar(128) NOT NULL default ”,

  UNIQUE KEY domain (domain)

CREATE TABLE postfix_users (
  id int(11) unsigned NOT NULL auto_increment,
  email varchar(128) NOT NULL default ”,
  clear varchar(128) NOT NULL default ”,

  crypt varchar(128) NOT NULL default ”,
  name tinytext NOT NULL,
  uid int(11) unsigned NOT NULL default ‘ 1001 ‘,
  gid int(11) unsigned NOT NULL default ‘ 1001 ‘,

  homedir tinytext NOT NULL,
  maildir tinytext NOT NULL,
  quota tinytext NOT NULL,
  access enum(‘Y’,’N’) NOT NULL default ‘Y’,
  postfix enum(‘Y’,’N’) NOT NULL default ‘Y’,
disablepop3 char(1) NOT NULL default ‘ 0 ‘,

disableimap char(1) NOT NULL default ‘ 0 ‘,
disablewebmail char(1) NOT NULL default ‘ 0 ‘,
sharedgroup varchar(128) NOT NULL default ‘ 0 ‘,
  smtpaccess enum(‘Y’,’N’) NOT NULL default ‘ Y ‘,


  UNIQUE KEY email (email)

CREATE TABLE postfix_virtual (
  id int(11) unsigned NOT NULL auto_increment,
  email varchar(128) NOT NULL default ”,
  destination varchar(128) NOT NULL default ”,


CREATE TABLE postfix_access (
  id int(10) unsigned NOT NULL auto_increment,
  source varchar(128) NOT NULL default ”,
  access varchar(128) NOT NULL default ”,

  type enum(‘recipient’,’sender’,’client’) NOT NULL default ‘recipient’,

Lets create our new table

#mysql -u root -p1234 mail < virtual_user.sql


    Asume that you are using sendmail and you want to convert your directory structure to Maildir
format from mbox format. Because our new system use Maildir format, each email will be stored
in seperate files not in a big file which is the case in mbox format.

    Each user will have a mail directory.  e.g :   you have an e-mail
Mail directory for this user will be „ /home/vmail/ ” . By this way, all users’s mail
directories will be created under their domain directory( This is so great, you keep users
of the same domain under the same directory.


#mkdir /home/vmail
#chown vmail:vmail /home/vmail
#chmod 700 /home/vmail


open /etc/postfix/   file and change

flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}


flags=Ru user=vmail argv=/usr/local/bin/maildrop -d ${recipient}

Note: Don’t forget the leading two spaces in this file.

After that,
open /etc/postfix/   file and add the lines below in the box to the end of this file. 

WARNING: Texts seperated by commas in must be written in one line.
Please be careful.

myhostname =
mydomain =
mydestination = $myhostname
local_recipient_maps = $alias_maps $virtual_mailbox_maps unix:passwd.byname
home_mailbox = Maildir/

smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,
            check_recipient_access mysql:/etc/postfix/,reject_unauth_destination,permit
# The above line must be fitted in one line DONT FORGET
smtpd_sender_restrictions = check_sender_access mysql:/etc/postfix/

smtpd_client_restrictions = check_client_access mysql:/etc/postfix/

alias_maps = mysql:/etc/postfix/
relocated_maps = mysql:/etc/postfix/

transport_maps = mysql:/etc/postfix/
maildrop_destination_recipient_limit = 1
virtual_transport = maildrop
virtual_mailbox_domains = mysql:/etc/postfix/
virtual_alias_maps = mysql:/etc/postfix/

virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = mysql:/etc/postfix/
virtual_uid_maps = mysql:/etc/postfix/
virtual_gid_maps = mysql:/etc/postfix/

# If you want to use TLS add three lines below
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/postfix/postfix.pem
smtpd_tls_key_file = $smtpd_tls_cert_file

smtpd_helo_required = yes
disable_vrfy_command = yes
smtpd_data_restrictions = reject_unauth_pipelining
smtpd_etrn_restrictions = reject

Details about some directives declared in  file:

myhostname Fully-qualified domain name of the machine. e.g
mydomain Domain name of your system . By default it is the hostname without the leading word e.g
mydestination The list of domains that are delivered via the local transport mail delivery agent. This agent looks up all receipents in /etc/passwd and /etc/aliases . Do not specify the names of virtual domains here, they are declared as virtual_mailbox_domains.
local_recipient_maps Names or addresses of local recipients and a recipient address is local when its domain
matches $mydestination,$inet_interfaces and $proxy_interfaces. If this parameter is   non-empty (the default), then the Postfix SMTP server will reject mail for unknown local users
home_mailbox Optional pathname of a mailbox file relative to a user’s home directory
smtpd_helo_required It forces an SMTP client to introduce itself at the beginning of the SMTP session. This is useful for fighting against SPAM . Since many spam software doesn’t use this helo step
disable_vrfy_command It disables verify command request . You can vrfy a user whether it exists in the system or not. You don’t want to allow others to check your users right ?
smtpd_etrn_restrictions Reject ETRN requests . With ETRN, a site can tell the mail server of its provider to „Please deliver all my mail now”. The SMTP server searches the queue for mail to the customer, and delivers that mail by connecting to the customer’s SMTP server
virtual_transport Default delivery transport for domains that match in $virtual_mailbox_domains. If you don’t specify this variable then you will not be able to use maildrop facilities for virtual domains such as spamassassin filter, quota etc.
broken_sasl_auth_clients There are some e-mail clients not conforming with standards  (best example  is OE), Postfix advertise AUTH support in a non-standard way to comply


With these commands, we create ssl certificate for postfix. Important point here is,
when openssl asks for Common Name, write your smtp server address. i.e the address
that you are going to write in your mail client. When you use your mail client, please
choose secure smtp(TLS).

#cd /etc/postfix
#/usr/local/ssl/bin/openssl \
req -x509 -newkey rsa:1024 -keyout postfix.pem -out postfix.pem -nodes -days 365

Now, it is time to create ” .cf ” files  specified in file above. Create files below with the same

names in /etc/postfix directory.

user = vmailuser
password = password123
dbname = mail

table = postfix_alias
select_field = destination
where_field = alias
hosts =


user = vmailuser
password = password123
dbname = mail
table = postfix_relocated
select_field = destination
where_field = email

hosts =

user = vmailuser
password = password123
dbname = mail

table = postfix_transport
select_field = destination
where_field = domain
hosts =


user = vmailuser
password = password123
dbname = mail
table = postfix_virtual_domains
select_field = destination
where_field = domain

hosts =
user = vmailuser
password = password123
dbname = mail
table = postfix_virtual

select_field = destination
where_field = email
hosts =

user = vmailuser

password = password123
dbname = mail
table = postfix_access
select_field = access
where_field = source
additional_conditions = and type = ‘recipient’

hosts =

user = vmailuser
password = password123
dbname = mail

table = postfix_access
select_field = access
where_field = source
additional_conditions = and type = ‘sender’
hosts =

user = vmailuser
password = password123
dbname = mail
table = postfix_access
select_field = access

where_field = source
additional_conditions = and type = ‘client’
hosts =

user = vmailuser

password = password123
dbname = mail
table = postfix_users
select_field = maildir
where_field = email
additional_conditions = and postfix = ‘y’

hosts =
user = vmailuser
password = password123
dbname = mail
table = postfix_users

select_field = uid
where_field = email
additional_conditions = and postfix = ‘y’
hosts =
user = vmailuser

password = password123
dbname = mail
table = postfix_users
select_field = gid
where_field = email
additional_conditions = and postfix = ‘y’

hosts =

There are some passwords which souldn’t be seen by others so let’s make them secure.

#chmod 640  /etc/postfix/mysql-*

#chgrp postfix /etc/postfix/mysql-*


#cd /usr/local/etc/authlib
#pico authdaemonrc

In the file authdaemonrc ,  change the line starting with „authmodulelist=”  as below.

authmodulelist=”authmysql authpam”

Open authmysqlrc file and modify lines as described following.

(NOTE:  CONCAT line in this file must be on the same line with MYSQL_AUXOPTIONS_FIELD.
Additionally, you can also use MYSQL_SOCKET option pointing to your socket file instead of MYSQL_SERVER option
look authmysqlrc file more info)


MYSQL_USERNAME          vmailuser

MYSQL_PASSWORD          password123
MYSQL_SOCKET            /tmp/mysql.sock
#If you can’t do that, use MYSQL_PORT
#If your socket path is in a different location, please modify it.
MYSQL_OPT               0

MYSQL_DATABASE          mail
MYSQL_USER_TABLE        postfix_users
MYSQL_UID_FIELD         uid

MYSQL_GID_FIELD         gid
MYSQL_HOME_FIELD        homedir
MYSQL_NAME_FIELD        name

CONCAT(„disableimap=”,disableimap,”,disablepop3=”,disablepop3,”,disablewebmail=”,disablewebmail,”,sharedgroup=”,sharedgroup) MYSQL_WHERE_CLAUSE      access=’y’

Note: MYSQL_CRYPT_PWFIELD line can exist or not. Its existence doesn’t cause any problem. Since we are going to
put clear text passwords into our database.

Secure this file;

# chmod 400 authmysqlrc


Make following modifications in imapd file



Do the following changes in the new pop3d file
/usr/lib/courier-imap/etc /pop3d


If you want to use pop3 this POP3DSTART must be YES



Do the following change in new pop3d-ssl file


Create ssl certificate for POP3

#cd /usr/lib/courier-imap/share
# /usr/local/ssl/bin/openssl req -x509 -newkey rsa:1024 -keyout pop3d.pem -out \
  pop3d.pem -nodes -days 365


Do the following change in  imapd-ssl file


Create ssl certificate for IMAPD

#cd /usr/lib/courier-imap/share
# /usr/local/ssl/bin/openssl req -x509 -newkey rsa:1024 -keyout imapd.pem -out \

  imapd.pem -nodes -days 365


create /etc/maildroprc file and save lines below to this file. Don’t forget to change spamassassin

path for your own.

if ( $SIZE < 26144 )
    exception {

       xfilter „/usr/bin/spamassassin –prefspath=$HOME/$DEFAULT/.spamassassin/user_prefs

if (/^X-Spam-Flag: *YES/)

    exception {
        to „$HOME/$DEFAULT/.Spam/”

    exception {
        to „$HOME/$DEFAULT”

NOTE1:   Messages filtered by spamassassin will be stored in $HOME/$DEFAULT/.Spam directory.
e.g :  /home/vmail/

NOTE2: If you want to use individual preference for each user ” –prefspath=$HOME/$DEFAULT/.spamassassin/user_prefs ”

text must exist  in the maildroprc   configuration file. Otherwise remove it from the line.
$HOME/$DEFAULT/.spamassassin/user_prefs stands for  /home/vmail/
as an example


write the lines below to /usr/local/lib/sasl2/smtpd.conf file

# smtpd.conf
pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: plain login

sql_engine: mysql
sql_hostnames: localhost
sql_user: vmailuser
sql_passwd: password123
sql_database: mail

sql_select : select clear from postfix_users where email=’%u@%r’ and smtpaccess=’Y’;

We have again confidential information in this file. We must give least possible permission.

#chown postfix:postfix /usr/local/lib/sasl2/smtpd.conf
#chmod 400 /usr/local/lib/sasl2/smtpd.conf

This smtpd.conf file needs some extra explanation. If you want to use smtp authentication in
your client programs, password that you enter is compared with the text returned from sql_select query .
If there is a match and also smtpaccess field for user is „Y”, mail is allowed to be sent . This means , make
sure that smtpaccess field is „Y” for users that you want to give smtp relaying.



Now, we have already finished but how are we going to add a new user ?
In the example given below, we are adding a user with
The whole maildir will be /home/vmail/

postfix_virtual_domains table is used to add your domain names.
postfix_users table is used to add your e-mails.

New Domain:
Before adding a new user which is the first user of a new domain, you must
add the domain name to the database;

#mysql -u vmailuser -p password123
mysql>use mail;
mysql>INSERT INTO postfix_virtual_domains VALUES (‘ ‘,’’,’maildrop:’) ;

New User:

mysql> INSERT INTO postfix_users (email,clear,name,homedir,maildir,quota) VALUES
  (‘ ‘,’ mypassword ‘,’ GencoYILMAZ ‘,’ /home/vmail/ ‘,’ ‘,’ 10000000 ‘) ;

Create user home directory and set quota 10 MB.

#su – vmail
$mkdir -p /home/vmail/
$/usr/lib/courier-imap/bin/maildirmake /home/vmail/

$ /usr/lib/courier-imap/bin/maildirmake -q 10000000S /home/vmail/

Starting Daemons:
Note: Probably you have already started mysql to carry out mysql related operation. This is the starting squence of these daemons.

#/etc/init.d/mysql.server start

#/usr/local/sbin/authdaemond start
#/usr/lib/courier-imap/libexec/imapd.rc start
#/usr/lib/courier-imap/libexec/pop3d.rc start
#postfix start

After these steps, we have created a user called . The point here is that
user name is not genco .  It is . Meaning that , you should use in
your client programs as username.



   postfix_virtual table can be used for alias and forwarding purposes. Alias and forward
have almost the same function in this setup. For example, we want to forward e-mails sent
  to address to address. When you do the insertion to the
postfix_virtual table as below, it will be okay. No extra configuration or reloading is necessary
for it to work. Note that, doesn’t have to be a locally hosted e-mail. It can be
any address.

#mysql -u vmailuser -p password123
mysql>use mail;
mysql>INSERT INTO postfix_virtual VALUES (‘ ‘,’’,’’) ;


      If you want to redirect a mail for a specific domain to another mail server this is just
a piece of cake in postfix :) When adding your domain name into postfix_transport table,  
instead of writing „maildrop:” into destination field, write ” smtp:[remote_smtp_server_address] ” .
then for that domain, mails will be forwarded to the remote_smtp_server_address after received
by . Let’s explain this with a simple example.

Our domain is and in mx records, points to our smtp server but we want to forward mails for this domain to mail server,
then add your domain like below to postfix_transport table.

#mysql -u vmailuser -p password123

mysql>use mail;
mysql>INSERT INTO postfix_transport VALUES (‘ ‘,’ ‘,’smtp:[ ]’) ;

Then add  this line to /etc/postfix/

relay_domains = /etc/postfix/relay_domains

Create /etc/postfix/relay_domains file and put domain names, that you want to forward, into this file.

#echo „” >> /etc/postfix/relay_domains
#postfix reload


Be sure that you do not include this new forwarded domain in any one of the following tables or files;


Also , if there is any entry in virtual_mailbox_maps for any user of this domain, your mail will be

delivered locally and will not be sent to the remote mail server.  So, be careful.
Let’s explain this situation with an example (the best thing)


    You want to forward all emails for domain to smtp server.
Assume that previously you were hosting domain in your mail server and you
have changed your mind. You will forward all mails for this domain to an internal mail server.

Then to make forwarding active, you have deleted domain entry from virtual_mailbox_domains
and add domain to /etc/postfix/relay_domains file. After that, you have added smtp:[]
entry to postfix_transport table in our mysql database. Everything seems okay ? If you are a forgetful
person like me :) you forget to remove email entries from postfix_virtual tables which is used for aliasing.
Then you try to send email to , which is thought to be received by main server
and forwarded to the internall mail server But it doesn’t  work and main server accepts mail. (Since you have an entry in postfix_virtual for this e-mail that was working

previously) But if you send an e-mail which is not configured in postfix_virtual table, your mail is
forwarded to the internal mail server. This was the mistake that I have made…   but as I mainly say
in my daily life, I haven’t learnt a lot from my right things as much as I have learnt from my wrong ones.
This mistake showed me that I can distribute mail users for a specific domain into two mail servers. 
Lets say , %40 of email users can be located in one server and %60 of e-mail users can be located
in the other server. It is really amazing to learn this from one of my mistakes:)

In fact, everything is written in documentation page but you have to be very careful

while you are reading those documents. Thanks to Wietse Venema friend for this great documentation.

Now you have a fully functional mail server that can also forward emails for domain names
that it doesnt host, to another mail exchanger.

CONGRATULATIONS !!! If you come to this point. I am sorry that I don’t have a gift to give you :)
but you have an amazing,fantastic,fastest,incredible,wonderful mail server now ..:)

RELAYHOST (Choosing another mail server to send your mails for you)

    Suppose that you have set your mail server up but you want to send your servers’ mails to
another server and let that remote server send your local mails on behalf of you. Your mail
server will not be the smtp client for other destination mail servers but your remote host
(relayhost) will be. Here, how it is done;


When you add above line to /etc/postfix/, all of your non-local(not locally hosted) mail will be
sent to first when no entry is matched in optional transport table and then delivered through
  that relay host to the destination for you. But for this to work, machine should give you
relaying permission.


    AMAVISD-NEW is an interface between your MTA (Postfix) and content checkers (clamav,spamassassin etc)
We are going to install amavisd-new first then tell amavisd-new to use clamav for virus checking.

Amavisd-new and Clamav Installer script

I have written an installer which automates all these amavisd-new and clamav installation steps. Installer
does the following actions;

1) Create all the necessary directory,files,user and group names.
2) If the installer cannot find the amavis and clamav archives in the current directory, it downloads
     them by using wget utility , unpack and compile.
3) Installer script installs all the necessary modules for amavisd-new by issuing
     perl -MCPAN -e „install $MODULE_NAME” command.  This means you dont need to enter all these

     long commands.
4) At the end of installing process, installer script updates the clam virus database to the latest version.
5) Finally you will receive an information text message that you should do manually e.g appending some text
    to your postfix. I didn’t want to insert some of the configs automatically. I thought it will be better to add them

6) Final REMARKS;
     Adjust URLs of amavis and clamav files.
     Installer requires internet connectivity to update clamav. Please make sure that there is no
     problem with the connection.
     Installer uses ascii colors to emphasize on path names please use a supported terminal

You can download installer script here
Project Home page is
Notes: Extension of the file is txt. Remove txt and make extension .sh

If you want to install manually here is the process of installing. My installer performs the same actions
described below;

Let’s begin installation of amavisd-new


Amavisd requires some packages before it can be used. Please install following files;

File utility: 4.06 or higher version is recommended.  If  ” file -v ” command outputs a
smaller version download and install the recent file utility.

Perl 5.8.2 or a higher version is recommended. Please install these versions if you haven’t.

Some perl modules will need to be installed for proper working. Use CPAN network and install the following
modules as below; (Some modules may give a message saying „it is up to date” … no problem)
Please follow module installation in order:

Note : If you want to install all these modules without writing these commands manually

use my way automatic module installation way below this box.

#perl -MCPAN -e shell
cpan>install  Archive::Tar
cpan>install  Archive::Zip

cpan>install  Compress::Zlib
cpan>install  Convert::UUlib
cpan>install  MIME::Base64

cpan>install  Mail::Internet
cpan>install  Net::Server
cpan>install  Net::SMTP

cpan>install  Digest::MD5
cpan>install  IO::Stringy
cpan>install  Time::HiRes

cpan>install  Unix::Syslog
cpan> install  BerkeleyDB
cpan>install MIME:Tools

cpan>install  Convert::TNEF


Save these module names( below box #1 ) into a file called modules.txt then save the lines
in box 3 to a file called then run the following command and

it will install all the modules.


1 (modules.txt)                 2                                                3(




for module in $(cat modules.txt)

perl -MCPAN -e „install ‘${module}’ ”


Prepare user account and home directory for Amavisd-new

#mkdir /var/amavis
#groupadd vscan
#useradd vscan -g vscan -d /var/amavis  -s /bin/bash 
#chmod 750 /var/amavis

#mkdir /var/amavis/tmp
#mkdir /var/amavis/db
#chown -R vscan:vscan /var/amavis

Installing AMAVISD-NEW

#cd /usr/local
#wget -c
#tar -zxf amavisd-new-2.2.1.tar.gz
#cd amavisd-new-2.2.1
#cp amavisd /usr/local/sbin

#chown root /usr/local/sbin/amavisd
#chmod 755 /usr/local/sbin/amavisd
#cp amavisd.conf /etc
#chown root /etc/amavisd.conf
#chmod 644 /etc/amavisd.conf
#mkdir /var/virusmails

#chmod 750 /var/virusmails/
#chown vscan /var/virusmails/

Edit /etc/amavisd.conf file and adjust variables as below (If you haven’t used the above scheme for directory
structure, you will also need to change more variables than below)


$mydomain = ‘’;
$virus_admin      = „genco\@$mydomain”;
$mailfrom_notify_admin     = „genco\@$mydomain”;
$mailfrom_notify_recip     = „genco\@$mydomain”;

$mailfrom_notify_spamadmin = „NOSPAMMER\@$mydomain”;

You can set many virus scanners in amavisd.conf file but we are going to use only clamav.
So remove comment „#” character and change socket path into /tmp/clamd on the lines
below in amavisd.conf. These lines starts with text which are in
av_scanners array.


Uncomment the line
@bypass_spam_checks_maps = (1);
so that amavisd-new will not use spam check function. 
   \&ask_daemon, [„CONTSCAN {}\n”, ” /tmp/clamd „],
   qr/\bOK$/, qr/\bFOUND$/,
   qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],


#wget -c
#groupadd clamav

#useradd -g clamav -s /bin/false -c „Clam Antivirus” clamav
#tar -zxf clamav-0.83.tar.gz
#cd clamav-0.83
#./configure –sysconfdir=/etc
#make install

#mkdir /var/lib/clamav
#chown clamav:clamav /var/lib/clamav

Make a test to see how clamav is working. We are doing our test under /usr/local/clamav-7.5 directory which
contains sample virus like files. This test will write the output into scan.txt file. Investigate it :)

#/usr/local/bin/clamscan -r -l scan.txt /usr/local/clamav-0.83


Edit /etc/clamav.conf and modify variables like below;

#Example       {Put # in fronf of Example line}
LogFile /tmp/clamd.log
DatabaseDirectory /var/lib/clamav


Since every second a new virus/worm is created, we must update our database. Freshclam program does this

#chmod 600 /var/log/clam-update.log

#chown clamav /var/log/clam-update.log
{Below command will update clamav database but before issuing that command open /etc/freshclam.conf and comment line starting with „Example” word as you have done in /etc/clamav.conf}
#/usr/local/bin/freshclam –datadir=/var/lib/clamav -l /var/log/clam-update.log

Create a crontab entry so that clamav will update its database everyday at 08:00 regularly. Put these lines into

your crontab

06 08 * * * /usr/local/bin/freshclam –quiet -l /var/log/clam-update.log

Special NOTE from Lennard Warnaar: Lennard took my attention to the scheduled update time of
clamav. I had not noticed this. Clamav-support docs is saying that : „Please don’t choose any multiple of 10

because there are already too many servers using those time slots.” So please update your clamav at
02,03,04 etc. minutes instead of 10 multiples (00,10,20)



Run amavisd-new daemon

First make sure that amavisd is working properly. To test this run amavisd with debug paramater like;
#/usr/local/sbin/amavisd -u amavis debug
If this doesn’t cause any errors, exit and start amavisd in the background as below
#su – amavis -c „/usr/local/sbin/amavisd”

This should start amavis daemon with amavis user privilege


Write these lines into the end of /etc/postfix/ (We are using lmtp interface not smtp here)

smtp-amavis unix –      –       n       –       2  lmtp

    -o lmtp_data_done_timeout=1200
    -o lmtp_send_xforward_command=yes inet n  –       n       –       –  smtpd

    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_client_restrictions=
    -o smtpd_helo_restrictions=

    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o mynetworks=
    -o strict_rfc821_envelopes=yes
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001

    -o smtpd_hard_error_limit=1000

Now it is time to tell postfix to use a content filter. Open file and write the following;



Now it is time to reload postfix ” postfix reload ” and postfix will load its new config. To see whether
mail scanning works or not, send an e-mail which only contains characters below and look under /var/virusmails
directory for new detected virus e-mail.


Finally add commands („/usr/local/sbin/clamd”,” su – amavis -c „/usr/local/sbin/amavisd” ”
issued above to run clamd and amavis daemons to your startup scripts to run those daemons at every reboot

Now you have a MTA which does everything….. it scans emails containing viruses now… Congratulations…


Add lines below to /usr/local/apache2/conf/httpd.conf file to view from
your apache web server. There are also some sample lines in which you can play with the configuration
settings as below.


#Enable name based virtual hosting
NameVirtualHost *:80

<VirtualHost *:80 > 
    DocumentRoot /usr/local/apache2/htdocs/mail


    In apache, for each ssl site, you must provide another IP address to the web server.  SSL
sites are not like non-ssl sites.
  These sites are IP based sites. You can’t easily create multiple ssl sites as we have done above

in non-ssl virtual sites.So we should create an A record in DNS for and
point this address to a different IP address.
      In apache 2.0.50, ssl configuration file is /usr/local/apache2/conf/ssl.conf . You are going to
play with this file for ssl configurations and virtual host settings. For our ssl sites to work ,
we are going to put our ssl-virtualhost settings block in between  ;
  <IfDefine SSL>



blocks in this file. Whatever written below for ssl configuration will be between these blocks. (Be careful)
Let’me explain what the ssl configuration below says :
      By adding ” NameVirtualHost ” line, apache will serve ssl site with IP address. If you want to add another ssl site with IP address you

must also add ” NameVirtualHost ” line. Note that this line (NameVirtualHost)
doesn’t exist, you must add it above the first virtual host definition like the one below.
      VirtualHost declaration starts with <VirtualHost> . In default
apache ssl.conf file <VirtualHost _default_:443> is written. You can change _default_
with our new IP address.

SSLCertificateFile and SSLCertificateKeyFile lines define disk locations of our certificate
and key files previuosly created at the beginning of our document.
       When you restart apache after this configuration, page
will show content under /usr/local/apache2/htdocs/mail directory in a secure way.


<VirtualHost >
DocumentRoot „/usr/local/apache2/htdocs/mail”
ErrorLog /usr/local/apache2/logs/error_log

TransferLog /usr/local/apache2/logs/access_log

SSLEngine on
SSLCertificateFile /usr/local/apache2/conf/ssl.crt/webmail.crt
SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/webmail.key

<Files ~ „\.(cgi|shtml|phtml|php3?)$”>
    SSLOptions +StdEnvVars
<Directory „/usr/local/apache2/cgi-bin”>
    SSLOptions +StdEnvVars

SetEnvIf User-Agent „.*MSIE.*” \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog /usr/local/apache2/logs/ssl_request_log \
          „%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x „%r” %b”


    Please install quota_usage, change_mysqlpass and compatibility plugins for squirrelmail.
These plugins will allow you to change user password and see quota usage from webmail interface.

I hope you haven’t faced with any problem in this document. If you think that there are errors or
some parts in which security is not cared please feel free to contact me from the contact information

written at the end.


If you have a currently working system with many users you must find a way of converting all these users’
e-mail messages to the new maildir style email format.

In this address, there is a file called . It is used for converting mbox format to maildir format.
I have also written some perl scripts for adding user from command line and batch converting from mbox to maildir format.

1) Script to add user from command line:
2)  For example, you are keeping your users in /etc/passwd and mail mappings in /etc/postfix/virtual or /etc/sendmail/virtual
      with script, you can add all e-mails and create home directories in one step

3) You are using mbox format and want to convert all users’ emails to the new format in one step, use the script below after reading
    explanations in the script. script uses script and according to the records in /etc/postfix/virtual
    file, all mbox formatted e-mails is converted into new style and saved in new home directories.


              You can add,display,remove users and domains through postfix manager. Additionaly you can
      add,remove and display aliases. For the time being setting quota and attribute is managed through files but if I have time , I will add
      functionality to change attributes through postfix manager. Please read INSTALL file in postfixmanager
      directory. You have to set some variables. If anyone uses this program , I would like to receive some feedback about it.

     You can see screenshots of PostfixManager here

     You can download postfixmanager from


1) You may not realize mistakes that you have made for a period of time until you get an error message.  When you change
    your postfix configuration watch your log files for some time with the command;

#egrep ‘(warning|error|fatal|panic):’ /var/log/maillog | less

This will show you the problems if something goes wrong. Then take necessary action for the mistake. For more
debugging refer to debugging howto.

2) If you have any problems which you may think that it is common :) Just visit There are many examples and problems at this page. This may be your
  first step when you have a problem.

P.S: I would be pleased to hear from you about your feedbacks. If you see any mistake,any
security problem or any addition you want to do, please mail me…


Vélemény, hozzászólás?

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük