Qmail

From WBITT's Cooker!

Revision as of 13:45, 27 March 2013 by Kamran (Talk | contribs)
Jump to: navigation, search

Title: Qmail-Using John Simpson method


Created: 08/07/2009

Last Modified: 08/21/2009

Note: This is a highly volatile document at the moment. It is a research/development work, with VERY SHARP EDGES, and you should not use it in your production servers UNLESS you know what you are doing. With that said, the details are being used on at least two production internet mail server, which I know. :)

Important sites:-

  • Life with Qmail [LWQ] : lifewithqmail.org
  • John Simpson's Qmail website [JMS] : http://qmail.jms1.net/
  • Qmail Rocks website [QMR]: qmailrocks.org


The intent of this installation is to install qmail the way DJB intended, but bring along those, who are used to installing QMR only. That is the method followed in LifeWithQmail. QMR has made a mix of many of these and other qmail installations and created QMR. John Simpson and others have some serious objections on the way QMR is setup. My objective in this document is to provide an easy to follow approach (as easy as QMR), yet confirming to the suggestions and standards of JMS and LWQ and others.


Contents

Basic Information

  • OS: CENTOS 5.3 32 bit on a KVM virtual machine
  • Hostname: qmail.example.com
  • IP: 192.168.122.90

Step: Preparations

  • Disable SELINUX
  • Disable Default Firewall

Install nmap and disable unnecessary services.

yum -y install nmap

[root@qmail ~]# for i in avahi-daemon autofs cups exim sendmail gpm ip6tables iptables lvm2-monitor mdmonitor netfs nfslock pcscd portmap restorecond rpcgssd rpcidmapd xfs yum-updatesd ; do chkconfig --level 35 $i off; service $i stop ; done

Shutting down Avahi daemon:                                [  OK  ]
Stopping automount:                                        [  OK  ]
Stopping cups:                                             [  OK  ]
Shutting down exim:                                        [  OK  ]
error reading information on service sendmail: No such file or directory
sendmail: unrecognized service
Shutting down console mouse services:                      [  OK  ]
Not stopping monitoring, this is a dangerous operation. Please use force-stop to override.
Stopping NFS statd:                                        [  OK  ]
Stopping PC/SC smart card daemon (pcscd):                  [  OK  ]
Stopping portmap:                                          [  OK  ]
Stopping RPC idmapd:                                       [  OK  ]
Shutting down xfs:                                         [  OK  ]
Stopping yum-updatesd:                                     [  OK  ]
[root@qmail ~]#

Check the open ports:

[root@qmail ~]# nmap localhost
... 
Not shown: 1679 closed ports
PORT   STATE SERVICE
22/tcp open  ssh

Nmap finished: 1 IP address (1 host up) scanned in 0.091 seconds
[root@qmail ~]#

Step: Local CENTOS repository (Optional)

Setup the local CentOS repository on the server and update the Yum repository configuration on qmail server. This step is not necessary on servers, which have direct high speed connection to the internet.

[root@qmail ~]# vi /etc/yum.repos.d/CentOS-Local.repo

# CentOS-Local.repo
#

[local]
name=CentOS-$releasever - Local
baseurl=http://192.168.122.1/centos53-32/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5


Step: Kernel update / OS update

It is also right time to update your kernel. Or, better yet, update the entire OS installation.

Current:

[root@qmail ~]# uname -r
2.6.18-128.el5


[root@qmail ~]# yum list | grep kernel
kernel.i686                              2.6.18-128.el5                installed
kernel-devel.i686                        2.6.18-128.el5                installed
kernel-headers.i386                      2.6.18-128.el5                installed
kernel.i686                              2.6.18-128.4.1.el5            updates
kernel-PAE.i686                          2.6.18-128.4.1.el5            updates
kernel-PAE-devel.i686                    2.6.18-128.4.1.el5            updates
kernel-debug.i686                        2.6.18-128.4.1.el5            updates
kernel-debug-devel.i686                  2.6.18-128.4.1.el5            updates
kernel-devel.i686                        2.6.18-128.4.1.el5            updates
kernel-doc.noarch                        2.6.18-128.4.1.el5            updates
kernel-headers.i386                      2.6.18-128.4.1.el5            updates
kernel-xen.i686                          2.6.18-128.4.1.el5            updates
kernel-xen-devel.i686                    2.6.18-128.4.1.el5            updates
yum-kernel-module.noarch                 1.1.16-13.el5.centos          base
[root@qmail ~]#

[root@qmail ~]# yum -y update kernel kernel-devel kernel-headers

or just 

[root@qmail ~]# yum -y update

[root@qmail ~]# cat /etc/grub.conf
default=0
timeout=5
title CentOS (2.6.18-128.4.1.el5)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.18-128.4.1.el5 ro root=LABEL=/
        initrd /boot/initrd-2.6.18-128.4.1.el5.img
title CentOS (2.6.18-128.el5)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.18-128.el5 ro root=LABEL=/
        initrd /boot/initrd-2.6.18-128.el5.img
[root@qmail ~]#

System reboot needed after kernel update.

Step [optional]: SSH key based authentication

[Details]


Step: Required software components, including basic PERL modules

  1. httpd, httpd-devel, apr
  2. php, php-imap, php-mysql, php-gd, php-pear, php-zlib, php-mbstring, php-xml,
  3. perl, perl-libwww-perl, perl-Digest-SHA1, perl-Digest-HMAC, perl-Net-DNS, perl-HTML-Tagset, perl-HTML-Parser

perl-Time-HiRes, perl-TimeDate, perl-suidperl, perl-DateManip

  1. gcc, gcc-c++, libtool-ltdl, libtool-ltdl-devel
  2. mysql-server, mysql-devel, postgresql-devel
  3. openssl, openssl-devel, openldap-servers
  4. wget
  5. patch, patchutils
  6. pcre-devel
  7. gdbm-devel
  8. db4, db4-devel
  9. fam fam-devel gamin-devel
  10. net-snmp + net-snmp-utils + net-snmp-libs
  11. mrtg
  12. spamassassin, expect, zlib-devel
yum -y install net-snmp net-snmp-utils net-snmp-libs mrtg \
httpd httpd-devel php php-imap php-mysql php-gd php-pear php-zlib php-mbstring php-xml \
gcc gcc-c++ gdbm-devel pcre-devel libtool-ltdl libtool-ltdl-devel \
mysql-server mysql-devel db4 db4-devel postgresql-devel \
openssl openssl-devel openldap-servers \
perl perl-libwww-perl perl-Digest-SHA1 perl-Digest-HMAC perl-Net-DNS perl-HTML-Tagset perl-HTML-Parser perl-Time-HiRes perl-TimeDate perl-suidperl perl-DateManip \
spamassassin expect zlib-devel \
fam fam-devel gamin-devel patch patchutils

Note: Basic PERL modules required are as follows:

Digest::SHA1
Digest::HMAC
Net::DNS
Time::HiRes
HTML::Tagset
HTML::Parser

From the yum install command above, you can see that all of these listed PERL modules are installed. However, Time::HiRes will not be installed.

Update: CENTOS 6.3 64 bit will install the Time::HiRes perl module.

Check with:

# yum list installed perl* | egrep -i "sha1|hmac|DNS|HiRes|Target|Parser"

If any perl module is not installed, try installing it manually. You can use the following command to install it through perl -MCPAN option:

perl -MCPAN -e "install Time::HiRes" 
... 
All tests successful.
Files=1, Tests=40, 25 wallclock secs (11.49 cusr +  1.32 csys = 12.81 CPU)
  /usr/bin/make test -- OK
Running make install
Installing /usr/lib/perl5/5.8.8/i386-linux-thread-multi/auto/Time/HiRes/HiRes.so
Installing /usr/lib/perl5/5.8.8/i386-linux-thread-multi/auto/Time/HiRes/HiRes.bs
Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
Installing /usr/lib/perl5/5.8.8/i386-linux-thread-multi/Time/HiRes.pm
Installing /usr/share/man/man3/Time::HiRes.3pm
Writing /usr/lib/perl5/5.8.8/i386-linux-thread-multi/auto/Time/HiRes/.packlist
Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
  /usr/bin/make install  -- OK

How to check if these modules are installed?

Use the perldoc -l command for each PERL module you want to check. You should see a “.pm” line for each module that is installed on the system:-

[root@qmail ~]# perldoc -l Time::HiRes Digest::SHA1 Digest::HMAC Net::DNS Time::HiRes HTML::Tagset HTML::Parser

/usr/lib/perl5/5.8.8/i386-linux-thread-multi/Time/HiRes.pm
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/Digest/SHA1.pm
/usr/lib/perl5/vendor_perl/5.8.8/Digest/HMAC.pm
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/Net/DNS.pm
/usr/lib/perl5/5.8.8/i386-linux-thread-multi/Time/HiRes.pm
/usr/lib/perl5/vendor_perl/5.8.8/HTML/Tagset.pm
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/HTML/Parser.pm
[root@qmail ~]#

There is a long list of PERL modules, required for the enhanced functionality of SpamAssassin, Razor, DCC, etc. You can install them after you are done with your base qmail installation . Or you may want to install them before (now). It doesn't matter. There is also an option to update your perl CPAN system module. If you want to, you can execute the following two commands to update. This is an optional step though.

Update: CENTOS 6.3 You may need to have perl-CPAN installed through RPM.


perl -MCPAN -e "install Bundle::CPAN"
perl -MCPAN -e "reload"

And here is the list of PERL modules, as discussed above:

Digest::SHA1
Digest::HMAC
HTML::Tagset
HTML::Parser
Parse::Syslog
Statistics::Distributions
ClamAV::Client
Mail::SpamAssassin
Mail::SPF::Query
IP::Country::Fast
MIME::Base64
Getopt::Long
URI::Escape
Mail::SPF
IO::Zlib
Test::Harness
Test::Simple
Mail::DKIM
Mail::DomainKeys
Crypt::OpenSSL::Bignum
IO::Socket::INET6
IO::Socket::SSL
Mail::SpamAssassin::Plugin::DCC
Mail::SpamAssassin::Plugin::Razor2
Socket6
Date::Manip
DB_File
Archive::Tar
Net::Ident
Time::HiRes
Archive::Tar
File::Copy
Encode::Detect
Razor2::Client::Agent  (This will get installed with the Razor software, later)

Here is a tip for checking this whole list: Save this list in a text file, say /tmp/perl-list.txt on the server. Then run a loop to check existence of each module, such as:

[root@qmail ~]# for i in `cat /tmp/perl-list.txt`; do perldoc -l $i ; done

You will get the output such as:-

[root@qmail ~]# for i in `cat /tmp/perl-list.txt`; do perldoc -l $i ; done
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/Digest/SHA1.pm   
/usr/lib/perl5/vendor_perl/5.8.8/Digest/HMAC.pm                           
/usr/lib/perl5/vendor_perl/5.8.8/HTML/Tagset.pm                           
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/HTML/Parser.pm   
No documentation found for "Parse::Syslog".                               
No documentation found for "Statistics::Distributions".
... . 

I will use a grep filter to just see which modules are not installed:-

[root@qmail ~]# for i in `cat /tmp/perl-list.txt`; do perldoc -l $i ; done | grep "No documentation"
No documentation found for "Parse::Syslog".
No documentation found for "Statistics::Distributions".
No documentation found for "ClamAV::Client".
No documentation found for "Mail::SPF::Query".
No documentation found for "IP::Country::Fast".
No documentation found for "Mail::SPF".
No documentation found for "Mail::DKIM".
No documentation found for "Mail::DomainKeys".
No documentation found for "Crypt::OpenSSL::Bignum".
No documentation found for "Net::Ident".

[root@qmail ~]#

As you can see above, I now have a list of modules I will need to install manually. I will utilize the opportunity now and install them. Again, you can install them before you start with Anti-Spam software.

The following will install without a problem:-

perl -MCPAN -e "install Parse::Syslog"
perl -MCPAN -e "install Statistics::Distributions"
perl -MCPAN -e "install IP::Country::Fast"
perl -MCPAN -e "install Crypt::OpenSSL::Bignum"

The following will not install easily with “perl -MCPAN ....” command. But when you do, it will save you from actually downloading the software. When you issue the “perl -MCPAN -e install ........” command, the module will get downloaded and will be saved in the .cpan/build directory of current user's home directory. Since you will be performing these steps as root, you will find them downloaded under /root/.cpan/build directory.

perl -MCPAN -e "install ClamAV::Client"
perl -MCPAN -e "install Mail::SPF::Query"
perl -MCPAN -e "install Mail::SPF"
perl -MCPAN -e "install Mail::DKIM"
perl -MCPAN -e "install Mail::DomainKeys"
perl -MCPAN -e "install Net::Ident"

At this point, you just need to change into each directory of the module and install it using the actual manual compilation technique.

[root@qmail build]# cd /root/.cpan/build/Net-Ident-1.20/

[root@qmail Net-Ident-1.20]# perl Makefile.PL && make && make install
... 
... 
Installing /usr/lib/perl5/site_perl/5.8.8/Net/Ident.pm
Installing /usr/share/man/man3/Net::Ident.3pm
Writing /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Net/Ident/.packlist
Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
[root@qmail Net-Ident-1.20]#


[root@qmail ~]# cd /root/.cpan/build/Mail-DKIM-0.36/

[root@qmail Mail-DKIM-0.36]# perl Makefile.PL && make && make install
... 
... 
Installing /usr/share/man/man3/Mail::DKIM::SignerPolicy.3pm
Installing /usr/share/man/man3/Mail::DKIM::DkPolicy.3pm
Installing /usr/share/man/man3/Mail::DKIM::Canonicalization::DkimCommon.3pm
Installing /usr/share/man/man3/Mail::DKIM::Policy.3pm
Writing /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Mail/DKIM/.packlist
Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod


[root@qmail build]# cd /root/.cpan/build/Mail-SPF-v2.006/
[root@qmail Mail-SPF-v2.006]# perl Makefile.PL && make && make install 
This module requires Module::Build to install itself.                  
  Install Module::Build now from CPAN? [y] y 
... 
... 
Installing /usr/share/man/man3/Mail::SPF::Mod::Exp.3pm
Installing /usr/share/man/man3/Mail::SPF::Result.3pm
Installing /usr/share/man/man3/Mail::SPF::Term.3pm
Installing /usr/share/man/man3/Mail::SPF::v1::Record.3pm
Installing /usr/share/man/man3/Mail::SPF::Server.3pm
Installing /usr/sbin/spfd
Installing /usr/bin/spfquery
Writing /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Mail/SPF/.packlist


[root@qmail Mail-SPF-v2.006]# cd /root/.cpan/build/Mail-SPF-Query-1.999.1/

Mail-SPF-Query module expects two more modules. Let's install them too:

[root@qmail ~]# perl -MCPAN -e "install Net::CIDR::Lite"

[root@qmail ~]# perl -MCPAN -e "install Sys::Hostname::Long"

[root@qmail Mail-SPF-Query-1.999.1]# perl Makefile.PL && make && make install
Installing /usr/bin/spfd
Installing /usr/bin/spfquery
Writing /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Mail/SPF/Query/.packlist
Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
[root@qmail Mail-SPF-Query-1.999.1]#


[root@qmail Mail-DomainKeys-1.0]# perl Makefile.PL && make && make install

You appear to be directly connected to the Internet.  I have some tests
that try to query live nameservers.

Do you want to enable these tests? [y] y
Warning: prerequisite Crypt::OpenSSL::RSA 0 not found.
Writing Makefile for Mail::DomainKeys
... 
... 
Installing /usr/lib/perl5/site_perl/5.8.8/Mail/DomainKeys/Key/Private.pm
Installing /usr/share/man/man3/Mail::DomainKeys.3pm
Writing /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Mail/DomainKeys/.packlist
Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
[root@qmail Mail-DomainKeys-1.0]#

Install the additional module:


[root@qmail Mail-DomainKeys-1.0]# cd ../Crypt-OpenSSL-RSA-0.25/

[root@qmail Crypt-OpenSSL-RSA-0.25]# perl Makefile.PL && make && make install 
... 
... 
Writing Makefile for Crypt::OpenSSL::RSA                                      
Writing /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Crypt/OpenSSL/RSA/.packlist
Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
[root@qmail Crypt-OpenSSL-RSA-0.25]#

Pit-stop!

From here onwards Qmail installation steps will start. So if you want to take a snapshot of your virtual machine, now is the time.


Downloading and installing Qmail

We will not use NetQmail-1.06, because it is basically qmail-1.03 + “Some patches already applied”. This is what we don't want. We will patch qmail-1.03 with John Simpson's patches.

QMR guide asks us to download the packages in /usr/src/qmail. Whereas LWQ asks us to download it in /usr/local/src . Both guides ultimately place daemontools in /package and the first two (qmail and ucspi-tcp) in /var/qmail/*. I will try to be as close to LWQ recommendations. I will also make a directory named /downloads , and will download all the software I will be downloading during this installation, in this location.

Download Software

mkdir /downloads
cd /downloads

[root@qmail downloads]# wget http://cr.yp.to/software/qmail-1.03.tar.gz
[root@qmail downloads]# wget http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz
[root@qmail downloads]# wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz

cp  /downloads/*.tar.gz   /usr/local/src/


Unpack qmail-1.03.tar.gz and ucspi-tcp-0.88.tar.gz in /usr/local/src/ .

cd /usr/local/src/
tar xzf qmail-1.03.tar.gz 
tar xzf ucspi-tcp-0.88.tar.gz


Copy and unpack the daemontools package to the /package directory.

mkdir /package
chmod 1755  /package

cp /downloads/daemontools-0.76.tar.gz    /package/
cd /package
tar xzf  daemontools-0.76.tar.gz

There should now be directories called /usr/local/src/qmail-1.03, /usr/local/src/ucspi-tcp-0.88, and /package/admin/daemontools-0.76.

Create users and groups

Since qmail's installation program creates the sub-directories as they're needed, you only need to create the qmail "home" directory:


mkdir /var/qmail

# Create users and groups:

groupadd -g 700 nofiles
useradd -u 701 -g nofiles -d /var/qmail/alias -s /sbin/nologin -p '*'  -c 'QMail alias user' alias
useradd -u 702 -g nofiles -d /var/qmail -s /sbin/nologin -p '*'  -c 'QMail daemon user' qmaild
useradd -u 703 -g nofiles -d /var/qmail -s /sbin/nologin -p '*'  -c 'QMail log user' qmaill
useradd -u 704 -g nofiles -d /var/qmail -s /sbin/nologin -p '*'  -c 'QMail password user' qmailp

groupadd -g 701 qmail
useradd -u 705 -g qmail -d /var/qmail -s /sbin/nologin -p '*'  -c 'QMail queue user' qmailq
useradd -u 706 -g qmail -d /var/qmail -s /sbin/nologin -p '*'  -c 'QMail remote user' qmailr
useradd -u 707 -g qmail -d /var/qmail -s /sbin/nologin -p '*'  -c 'QMail send user' qmails

Basically, at this time, we are ready to do the build. Remember we have Qmail-1.03, which we need to patch, ideally with the latest combined patch from John Simpson.

QMR, at this stage creates a lot of directories and sets ownerships, which we are not going to do now. We will be careful, and will try to follow LWQ steps. There are, in particular, two files in Qmail source tree, in which QMR pushes some values. Refer to the following code:

echo 211 > /usr/src/qmail/qmail-1.03/conf-split
echo 255 > /usr/src/qmail/qmail-1.03/conf-spawn

According to the example we are following, these files are actually located in /usr/local/src/qmail-1.03 directory. Let's see these files contents from the default source:-

[root@qmail package]# cat /usr/local/src/qmail-1.03/conf-split
23

This is the queue subdirectory split.
[root@qmail package]# cat /usr/local/src/qmail-1.03/conf-spawn
120
This is a silent concurrency limit. You can't set it above 255. On some  systems you can't set it above 125. qmail will refuse to compile if the limit is too high. 
[root@qmail package]#


The details gathered on these two files from internet :-

conf-split:

The conf-split file specifies the number of subdirectories that the qmail directories for mail-queuing: info, local, mess and remote, are divided into. The default value for this parameter is 23. This is the number of split subdirectories for those queue directories which are hashed. The default for qmail is 23. Appropriate values depend on the volume of mail handled, OS filesystem efficiency, and other factors, but this should always be a prime number. (Ref: http://pyropus.ca/software/queue-repair/docs.html ) Research has shown that you get a more even distribution of hash values, and thus fewer collisions, if you choose your table size to be a prime number. Question: Are there any negative sideeffects of setting conf-split too high? Answer: Yes there are . Scanning todo/ takes longer, if you are using the big-todo patch, because every subdir has to be scanned, instead of just one dir.

Reference: http://www.mail-archive.com/qmail@id.wustl.edu/msg46322.html The default, 23, is prime, and in his only message to the list on the topic of conf-split, DJB suggested a value of 401, also prime, for a queue with 100000 entries. Reference: http://www.ornl.gov/its/archives/mailing-lists/qmail/1997/07/msg00295.html

Bottom-line: For smaller sites / mail-servers/ mail-queues, use the default. For larger sites, you can use larger prime numbers, going all the way to 401.


conf-spawn:

The conf-spawn file specifies the maximum number of simultaneous qmail-local and qmail-remote sessions that can be running on the system. The default value for this parameter is 120.


Conclusion:

We will use the default values in these files, unless John Simpson's combined patch makes changes in them.

Patch qmail source with John Simpson's patch

Time to apply the combined patch to qmail-1.03 . Download John Simpson's latest combined patch from his site: http://qmail.jms1.net/patches/combined-details.shtml

cd /downloads
wget http://qmail.jms1.net/patches/qmail-1.03-jms1.7.10.patch

cd /usr/local/src/qmail-1.03
patch < /downloads/qmail-1.03-jms1.7.10.patch

As you can see below, not a “single” hunk / patch failed!

[root@qmail qmail-1.03]# patch < /downloads/qmail-1.03-jms1.7.10.patch                                   
patching file EXTTODO                                                                                    
patching file EXTTODO-INFO                                                                               
... 
... 
patching file tcp-env.c
patching file timeoutconn.c
patching file timeoutconn.h
[root@qmail qmail-1.03]#

Just for the sake of verification, lets see what the patch has done to the two files: conf-split and conf-spawn. Here they are after patching:

[root@qmail qmail-1.03]# cat conf-split
23

This is the queue subdirectory split.

[root@qmail qmail-1.03]# cat conf-spawn
120

This is a silent concurrency limit. You can't set it above 65000. Many systems have a "hidden limit" of 509, because a single process cannot have more than 1023 handles open at once, and each concurrent delivery uses two handles. If you set it any higher than your system's "hidden limit", qmail will refuse to compile. 
[root@qmail qmail-1.03]#

As you can see, there is just a more detailed comment added in the conf-spawn. Rest no values are changed. Good!

Compile qmail

Once the patching is done, you are in line with the step of LWQ. You can go ahead and compile qmail. As shown below:

make clean
make man
make setup check

[root@qmail qmail-1.03]# make setup check
... 
... 
chmod 755 binm3+df
./compile spfquery.c
spfquery.c: In function ‘main’:
spfquery.c:30: warning: incompatible implicit declaration of built-in function ‘strdup’
spfquery.c:24: warning: return type of ‘main’ is not ‘int’
./load spfquery spf.o ip.o ipme.o ipalloc.o strsalloc.o \
        now.o dns.o env.o datetime.a stralloc.a alloc.a str.a substdio.a \
        case.a error.a fs.a `cat dns.lib` `cat socket.lib` envread.o qregex.o
./compile -DEXTERNAL_TODO  qmail-todo.c
qmail-todo.c: In function ‘main’:
qmail-todo.c:620: warning: return type of ‘main’ is not ‘int’
./load qmail-todo control.o constmap.o trigger.o fmtqfn.o now.o \
        readsubdir.o case.a ndelay.a getln.a sig.a open.a stralloc.a \
        alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
./install
./instcheck
[root@qmail qmail-1.03]# 

Configure basic qmail structures

Alhumdulillah. The compilation is done without a problem. According to LWQ, you can go ahead with using either “./config” or “./config-fast server.domain.com” method. QMR asks you to run “./config-fast server.domain.com” directly.

According to LWQ: If your DNS is configured properly, this script should be all you need at this point:

   ./config

If, for some reason, config can't find your hostname in DNS, you'll have to run the config-fast script:

   ./config-fast the.full.hostname

For example, if your domain is example.com and the hostname of your computer is dolphin, your config-fast line would look like this:

   ./config-fast dolphin.example.com


First, I will try “./config” only :

[root@qmail qmail-1.03]# ./config
Your hostname is qmail.example.com.
hard error
Sorry, I couldn't find your host's canonical name in DNS.
You will have to set up control/me yourself.
[root@qmail qmail-1.03]#

As you can see clearly, above, my DNS was not set properly, so qmail told me to do things manually. Instead of doing things manually, I will just run the “./config-fast ... ” script.

[root@qmail qmail-1.03]# ./config-fast qmail.example.com
Your fully qualified host name is qmail.example.com.
Putting qmail.example.com into control/me...
Putting example.com into control/defaultdomain...
Putting example.com into control/plusdomain...
Putting qmail.example.com into control/locals...
Putting qmail.example.com into control/rcpthosts...
Now qmail will refuse to accept SMTP messages except to qmail.example.com.
Make sure to change rcpthosts if you add hosts to locals or virtualdomains!
[root@qmail qmail-1.03]#

That's it. qmail is now installed on your system and is ready to be run!

################################################################################ 
Important from: http://www.antagonism.org/qmr-faq.shtml

7.11 What is the difference between the locals and rcpthosts files in /var/qmail/control?

The locals file contains domains which reside locally on the machine. This means accounts listed in locals should have shell accounts on the machine. If you use vpopmail, your locals file should be empty but exist. This problem is prevalent in many qmailrocks installs as the instruction set wrongly instructs users to configure qmail using the "config-fast" shell script. Unless the user desires email accounts for his shell accounts the is not the correct method. The following commands correct this error.

If /var/qmail/control/locals exists, run the first command. If not, you may skip to the second command.
# rm -f /var/qmail/control/locals
# touch /var/qmail/control/locals
# chmod 644 /var/qmail/control/locals
# chown root.root /var/qmail/control/locals

The rcpthosts file contains the domains for which qmail-smtpd will accept email. The rcpthosts file should contain the domain names only. Do not put in email addresses, hostnames or IP addresses into this file.
################################################################################## 

Though I have read the note above and implemented on a few live servers. I do not agree with it. The reason is that if I do as advised above, in this note, then mails destined for root, postmaster, etc do not get delivered to the mailbox of postmaster. So we won't act upon this advice. I have only copied this text/note here, for your information.

There is another thing to this note. The config-fast shell script is not provided by QMR. It is mentioned in LWQ. So it had to be from DJB. And at the moment, I consider him (DJB) the authority on Qmail. He put this script for a purpose. And the purpose is being served. Lets move on. By the way, by the time of this writing, the note has apparently moved to another location or changed name. I couldn't find it and I did not spent much time on it either.

QMR suggests to “make cert” at this point. There is no fun in doing so, as there are couple of things we still need to do. More-over, the “make cert” method suggested by QMR is wrong and is seriously questioned by JMS. We will deal with certificates at a later stage.


ucspi-tcp:

ucspi-tcp is DJB's original implementation of UCSPI, the Unix Client-Server Program Interface, using the TCP protocol. In other words, it's a set of programs which make it easy to write and run service programs which accept connections on TCP sockets, as well as client programs which connect to services on TCP sockets. The programs in the ucspi-tcp package take care of the messy networking details, and allow the programmer or system administrator to concentrate on making their service or client work correctly.


ucspi-tcp [LWQ]:

Earlier, you unpacked the qmail, ucspi-tcp, and daemontools tarballs. Now change to the ucspi-tcp directory:

   cd /usr/local/src/ucspi-tcp-0.88

In the Do the build section, if you modified conf-cc and conf-ld, you'll need to make the same changes in this directory. (We did not do any changes to conf-cc and conf-ld while compiling / building qmail-1.03 !)

Then do:

    patch < /usr/local/src/netqmail-1.06/other-patches/ucspi-tcp-0.88.errno.patch
    make
    make setup check

That's it. ucspi-tcp is installed.


Ucspi-tcp [JMS]:

From JMS site (http://qmail.jms1.net/ucspi-tcp/ ):-

ucspi-tcp is DJB's original implementation of UCSPI, the Unix Client-Server Program Interface, using the TCP protocol. In english, it's a set of programs which make it easy to write and run service programs which accept connections on TCP sockets, as well as client programs which connect to services on TCP sockets. The programs in the ucspi-tcp package take care of the messy networking details, and allow the programmer or system administrator to concentrate on making their service or client work correctly.

It's mentioned on this web site because the normal method of running an SMTP or POP3 service is to use the "tcpserver" program, which is part of the ucspi-tcp package. It's also possible to use tcpserver to run other TCP-based services, such as IMAP services. If you're running a qmail server, you should definitely understand how tcpserver works.

The patch:

Like qmail, the programs in the ucspi-tcp package are lacking in some features which many people, myself included, need on their servers. Below is a list of the ucspi-tcp patches I use on my own systems:

ucspi-tcp-0.88.errno.patch The ucspi-tcp package, like all of DJB's other packages, has an issue with the errno variable when compiled using glibc version 2.3 or higher. (CENTOS 5.3 has glibc 2.5 ). The solution is the same as for DJB's other packages as well. Edit the file error.h in the source code. Find this line, near the top of the file: extern int errno; Comment this line out, and add the following line below it:

/* extern int errno; */
#include <errno.h> 

If you would rather not edit the file by hand, the patch file can be used to make the change as well.

ucspi-rss.diff is a patch by Alan Curry which makes the rblsmtpd program work with A records. This is necessary because the owners of "rss" (one of the first anti-spam "blacklists") removed the TXT records from their zone files, because the DNS server they were using to serve the zone (BIND, which they also wrote) had trouble with large zone files, a problem which the "rbldns" program (from DJB's djbdns package) does not share. I have updated the patch. With the original patch, when rblsmtpd retrieves a TXT record, it scans the value for the string "%IP%" and replaces it with the value of TCPREMOTEIP (i.e. the IP address of the client.) My updated version does the same substitution on the value of the RBLSMTPD environment variable when it starts. You can download the original patch from qmail.org, or from my server. You can download the updated patch here: http://qmail.jms1.net/ucspi-tcp/ucspi-rss2.patch

The tcpserver limits patch, by Matija Nalis, gives tcpserver the ability to reject connections when the server's load average is above a certain number, when more than a certain number of connections are received from the same IP address, or when more than a certain number of connections are received from machines in the same class-C block (i.e. the "first three numbers" in their IP addresses are the same. "1.2.3.4" and "1.2.3.100" are in the same class-C block.) The limits are configured by setting the MAXLOAD, MAXCONNIP, and MAXCONNC environment variables before tcpserver runs. If you want tcpserver to send a message to the client before dropping their connection, you can configure this by setting a DIEMSG environment variable. The patch I was using, dated 2006-01-26, does work as advertised, and has saved my own server and several of my clients' servers from being overloaded by over-zealous attackers (i.e. spammers) over the past few months. However, I did notice a few minor cosmetic issues which I thought needed to be fixed, so I updated the patch. My updates are: When MAXCONNIP or MAXCONNC cause a connection to be rejected, tcpserver adds "MAXCONNIP:" or "MAXCONNC:" with the limit at the end of the "deny line in the logs. This makes it easy to debug- the error message tells you which environment variable caused the connection to be rejected. However, when MAXLOAD causes a connection to be rejected, it adds "LOAD:" and the current load average to the log. This doesn't match the environment variable, which "feels funny" to me. (I told you it was a minor cosmetic issue.) For the sake of consistency, I changed the "LOAD:" label to say "MAXLOAD:", so it matches the environment variable name, like the other two messages do. The older patch only has a provision for a single DIEMSG variable, whose value is sent to a client whose connection is being rejected, regardless of which of the three limits the client triggered. I thought it would be nice to be able to set one message which says something like "Server too busy, try again later" and another message which says "Too many connections from your IP address". I added three new environment variables: DIEMSG_MAXLOAD, DIEMSG_MAXCONNIP, and DIEMSG_MAXCONNC, whose values are used instead of the generic DIEMSG message. However, to avoid breaking older scripts, if one of these new variables is not set, the DIEMSG value will be used instead. The original author's web page has a link where you can download the previous versions of the patch. As of the time I'm writing this (2007-12-22) the most recent version of his patch is dated 2006-01-26, and is what I used as the starting point for my own changes. Below is the link to download the patch. I also have the CHANGES.tcpserver-limits-patch and README.tcpserver-limits-patch files available, if you want to read them before downloading the patch.

(I highly recommend you to read the README.tcpserver-limits-patch file.) http://qmail.jms1.net/ucspi-tcp/tcpserver-limits-2007-12-22.patch


Conclusion and actual installation of UCSPI:

We did not do any changes to conf-cc and conf-ld while compiling / building qmail-1.03 . So we don't need to change anything in the ucspi-tcp directory.

I cannot use the patch suggested by LWQ, as I am not using netqmail-1.06 . So I will use JMS method and manually edit the error.h file:

cd /usr/local/src/ucspi-tcp-0.88

vi error.h 
... 
... 
Replace :
extern int errno;

With :
/* extern int errno; */

And add another line after it:
#include <errno.h>

... 
... 
(save exit).


Then, I would download the two other patches mentioned by JMS and apply them to UCSPI source:

cd /downloads/
[root@qmail downloads]# wget http://qmail.jms1.net/ucspi-tcp/ucspi-rss2.patch
[root@qmail downloads]# wget http://qmail.jms1.net/ucspi-tcp/tcpserver-limits-2007-12-22.patch

cd /usr/local/src/ucspi-tcp-0.88

[root@qmail ucspi-tcp-0.88]# patch < /downloads/ucspi-rss2.patch
patching file rblsmtpd.c

[root@qmail ucspi-tcp-0.88]# patch < /downloads/tcpserver-limits-2007-12-22.patch
patching file CHANGES.tcpserver-limits-patch
patching file README.tcpserver-limits-patch
patching file tcpserver.c
[root@qmail ucspi-tcp-0.88]#


Now run “make” and “make setup check”:

[root@qmail ucspi-tcp-0.88]# make
... 
... 
./compile install.c                                                                        
./compile hier.c                                                                           
./compile auto-str.c                                                                       
auto-str.c:9: warning: conflicting types for built-in function ‘puts’                      
./load auto-str unix.a byte.a                                                              
./auto-str auto_home `head -1 conf-home` > auto_home.c                                     
./compile auto_home.c                                                                      
./load install hier.o auto_home.o unix.a byte.a                                            
./compile instcheck.c                                                                      
./load instcheck hier.o auto_home.o unix.a byte.a                                          
[root@qmail ucspi-tcp-0.88]#


[root@qmail ucspi-tcp-0.88]# make setup check
./install
./instcheck
[root@qmail ucspi-tcp-0.88]#

That's it. ucspi-tcp is installed. Alhumdulillah! Good.

Daemontools:

The daemontools package monitors, controls, and logs the execution and output of long-running programs, often called daemons.

Daemontools [LWQ]

Change to the daemontools build directory:

cd /package/admin/daemontools-0.76

Once again, if you modified <conf-cc> and conf-ld during the qmail and ucspi-tcp builds, you'll need to make the same changes in the src directory.

Then do:

    cd src
    patch < /usr/local/src/netqmail-1.06/other-patches/daemontools-0.76.errno.patch
    cd ..
    package/install

Daemontools [QMR]:

QMR wants us to patch daemontools, using the patch copied from the netqmail distribution, which is ok to do.


Conclusion and Installation of Daemontools:

We know that are not using LWQ's netqmail. Also we know that the patch applied to daemontools during QMR installation is in-fact a patch copied from LWQ's distribution. Basically this “errno” patch is exactly the same as it was for ucspi-tcp sotware. We just need to disable a line and introduce another line, exactly as before. So here it goes:

cd /package/admin/daemontools-0.76/src/

vi error.h
... 
... 
Replace :
extern int errno;

With :
/* extern int errno; */

And add another line after it:
#include <errno.h>

... 
... 
(save exit).

Change directory one step back :

cd .. 

OR 

cd /package/admin/daemontools-0.76/

And run:

package/install

OR

./package/install


[root@qmail daemontools-0.76]# package/install
... 
... 
grep sysdep hasmkffo.h >> sysdeps
grep sysdep hasflock.h >> sysdeps
grep sysdep hasshsgr.h >> sysdeps
Copying commands into ./command...
Creating symlink daemontools -> daemontools-0.76...
Making command links in /command...
Making compatibility links in /usr/local/bin...
Creating /service...
Adding svscanboot to inittab...
init should start svscan now.
[root@qmail daemontools-0.76]#

At this point your daemontools installation is complete. You should be able to see the “svscan” process running on your machine. Use "ps -ef | grep svscan" , “ps aux | grep svscan” or "ps waux | grep svscan" to verify that svscan is running.

[root@qmail daemontools-0.76]# ps waux | grep svscan
root     25206  0.0  0.1   2452  1044 ?        Ss   15:06   0:00 /bin/sh /command/svscanboot
root     25208  0.0  0.0   1684   356 ?        S    15:06   0:00 svscan /service
root     25213  0.0  0.0   3912   676 pts/0    S+   15:09   0:00 grep svscan
[root@qmail daemontools-0.76]# 

You will also see the following line added to your /etc/inittab file :

[root@qmail daemontools-0.76]# cat /etc/inittab 
. . . 
. . . 
SV:123456:respawn:/command/svscanboot

[root@qmail daemontools-0.76]# 
Note:

CentOS 6 Specific (http://www.productionmonkeys.net/guides/qmail-server/daemontools)
Starting daemontools with Upstart (http://qmail.jms1.net/daemontools/upstart.shtml)

The installer added a line to /etc/inittab to start svscan automatically, however that is obsolete in CentOS 6.x.
Remove the added line from /etc/inittab:
SV:123456:respawn:/command/svscanboot

Create a new file /etc/init/svscan.conf, with the startup code in it:
cd /etc/init
echo "start on runlevel [12345]" > svscan.conf
echo "respawn" >> svscan.conf
echo "exec /command/svscanboot" >> svscan.conf

Tell init to re-read its configuration files and start svscanboot:

initctl reload-configuration
initctl start svscan

Also check: http://www.kluner.net/2011/04/04/daemontools-on-redhat-enterprise-6-0

[root@mail init]# initctl reload-configuration
[root@mail init]# initctl start svscan
svscan start/running, process 5167
[root@mail init]# ps aux | grep svscan
root      5167  0.0  0.1  11296  1316 ?        Ss   11:44   0:00 /bin/sh /command/svscanboot
root      5169  0.0  0.0   4100   444 ?        S    11:44   0:00 svscan /service
root      5172  0.0  0.0 103236   836 pts/0    S+   11:44   0:00 grep svscan
[root@mail init]#


Alhumdulillah this step is done.


Note: This process check (shown above, just now) is what QMR performs at the end of it's “Part 2 - Installing Qmail Itself”. But as soon as QMR does this, it goes on an “Install spree” (same as shopping spree) and installs all sorts of software until it reaches it's “Part-9” where is decides to have mercy on the person doing the install, and finalize the qmail installation. Why did'nt that guy just start the qmail software first and made sure that it worked before moving on to installing bells and whistles ? It is a mystery to me.

And believe me, I was stupid and dumb enough to keep following it for all these years blindly, for the same reason JMS accuses it for: “to take the easy way out”. Until I read JMS and Life with Qmail “seriously”, I was living in fool's paradise. Anyway. Everyone learns from mistakes and I learned (and still learning) from mine.

Start qmail:

The /var/qmail/rc file [LWQ]:

The /var/qmail/boot directory contains example qmail boot scripts for different configurations. However for our installation, we'll use the following script and save it as /var/qmail/rc :

#!/bin/sh
# Using stdout for logging
# Using control/defaultdelivery from qmail-local to deliver messages by default
exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start "`cat /var/qmail/control/defaultdelivery`"

Note 1: Notice the back ticks! Note 2: QMR does the same, but doesn't inform us anything about creating this script, or it's contents. Also, QMR places ./Maildir (without quotes) in the /var/qmail/control/defaultdelivery file. That is intended, but an extra slash (/) is what is mentioned in LWQ guide. i.e. it should be ./Maildir/ as per LWQ. Normally it doesn't matter. It works both ways.

Save the above code as above /var/qmail/rc, then execute the following:

chmod 755 /var/qmail/rc

Note: LWQ creates a directory (/var/log/qmail) at this point. This will be used in various run scripts created below. Also the qmail log-run scripts will create files in this directory, “directly”. QMR deviated a little from this and created three sub directories inside /var/log/qmail , named qmail-send, qmail-smtpd, qmail-pop3d . JMS acknowledges here ( http://qmail.jms1.net/logfiles.shtml ), that is is not standard, however it is not wrong as well. So we will use the QMR log directories.

mkdir /var/log/qmail # LWQ

mkdir /var/log/qmail/qmail-send # QMR
mkdir /var/log/qmail/qmail-smtpd # QMR
mkdir /var/log/qmail/qmail-pop3d # QMR

QMR, also sets up certain ownership and permission to these log directories. Such as:

chown -R qmaill:root /var/log/qmail
chmod -R 750 /var/log/qmail

If you check the LWQ run script for qmail-send/log, and qmail-smtpd/log, you will notice that setuidgid program (provided with qmail source code itself), is called with an account name of qmaill. The setuidgid program takes care of the correct ownership of the files being written by the child program it calls. So setting the ownership for /var/log/qmail and it's sub directories , as the user qmaill, is okay. The same is verified/confirmed when LWQ also sets up the log directories and sets up ownership of these files as user qmaill . Also see http://cr.yp.to/qmail/faq/admin.html#multilog

At this point you need to decide the default delivery mode for messages that aren't delivered by a .qmail file. Well the most common options are Mailbox or Maildir formats. We are going to use the Maildir format as the default delivery mode.

echo './Maildir/' >/var/qmail/control/defaultdelivery

For more information, see INSTALL.mbox, INSTALL.maildir files in /usr/local/src/qmail-1.03 directory.

Note [from LWQ]: defaultdelivery isn't a standard qmail control file. It's a feature of the above /var/qmail/rc file. The defaultdelivery argument to qmail-start is the contents of a .qmail file that specifies delivery instructions to be followed when no actual .qmail is found. Putting these instructions in a separate control file eliminates the need to quote shell metacharacters in the delivery instructions and avoids messy multi-line command arguments.

System start-up files [from LWQ] :

The qmailctl script:

If you were to manually execute the /var/qmail/rc script, qmail would be partially started. But we want qmail started up automatically every time the system is booted and we want it shut down cleanly when the system is halted. This is accomplished by creating a startup/shutdown script like the following in /var/qmail/bin/qmailctl. This script is available via http://lifewithqmail.org/qmailctl-script-dt70 . Create the script using your editor or by downloading it with your web browser (recommended):

cd /downloads
wget http://lifewithqmail.org/qmailctl-script-dt70
cp qmailctl-script-dt70 /var/qmail/bin/qmailctl 

[root@qmail ~]#  vi /var/qmail/bin/qmailctl
#!/bin/sh

# For Red Hat chkconfig
# chkconfig: - 80 30
# description: the qmail MTA control file

PATH=/var/qmail/bin:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin
export PATH

QMAILDUID=`id -u qmaild`
NOFILESGID=`id -g qmaild`

case "$1" in
  start)
    echo "Starting qmail"
    if svok /service/qmail-send ; then
      svc -u /service/qmail-send /service/qmail-send/log
    else
      echo "qmail-send supervise not running"
    fi
    if svok /service/qmail-smtpd ; then
      svc -u /service/qmail-smtpd /service/qmail-smtpd/log
    else
      echo "qmail-smtpd supervise not running"
    fi
    if [ -d /var/lock/subsys ]; then
      touch /var/lock/subsys/qmail
    fi
    ;;
  stop)
    echo "Stopping qmail..."
    echo "  qmail-smtpd"
    svc -d /service/qmail-smtpd /service/qmail-smtpd/log
    echo "  qmail-send"
    svc -d /service/qmail-send /service/qmail-send/log
    if [ -f /var/lock/subsys/qmail ]; then
      rm /var/lock/subsys/qmail
    fi
    ;;
  stat)
    svstat /service/qmail-send
    svstat /service/qmail-send/log
    svstat /service/qmail-smtpd
    svstat /service/qmail-smtpd/log
    qmail-qstat
    ;;
  doqueue|alrm|flush)
    echo "Flushing timeout table and sending ALRM signal to qmail-send."
    /var/qmail/bin/qmail-tcpok
    svc -a /service/qmail-send
    ;;
  queue)
    qmail-qstat
    qmail-qread
    ;;
  reload|hup)
    echo "Sending HUP signal to qmail-send."
    svc -h /service/qmail-send
    ;;
  pause)
    echo "Pausing qmail-send"
    svc -p /service/qmail-send
    echo "Pausing qmail-smtpd"
    svc -p /service/qmail-smtpd
    ;;
  cont)
    echo "Continuing qmail-send"
    svc -c /service/qmail-send
    echo "Continuing qmail-smtpd"
    svc -c /service/qmail-smtpd
    ;;
  restart)
    echo "Restarting qmail:"
    echo "* Stopping qmail-smtpd."
    svc -d /service/qmail-smtpd /service/qmail-smtpd/log
    echo "* Sending qmail-send SIGTERM and restarting."
    svc -t /service/qmail-send /service/qmail-send/log
    echo "* Restarting qmail-smtpd."
    svc -u /service/qmail-smtpd /service/qmail-smtpd/log
    ;;
  cdb)
    tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
    chmod 644 /etc/tcp.smtp.cdb
    echo "Reloaded /etc/tcp.smtp."
    ;;
  help)
    cat <<HELP
   stop -- stops mail service (smtp connections refused, nothing goes out)
  start -- starts mail service (smtp connection accepted, mail can go out)
  pause -- temporarily stops mail service (connections accepted, nothing leaves)
   cont -- continues paused mail service
   stat -- displays status of mail service
    cdb -- rebuild the tcpserver cdb file for smtp
restart -- stops and restarts smtp, sends qmail-send a TERM & restarts it
doqueue -- schedules queued messages for immediate delivery
 reload -- sends qmail-send HUP, rereading locals and virtualdomains
  queue -- shows status of queue
   alrm -- same as doqueue
  flush -- same as doqueue
    hup -- same as reload
HELP
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|doqueue|flush|reload|stat|pause|cont|cdb|queue|help}"
    exit 1
    ;;
esac

exit 0

Make the qmailctl script executable and link it to a directory in your path:

chmod 755 /var/qmail/bin/qmailctl
ln -s /var/qmail/bin/qmailctl /usr/bin

Note: QMR also uses the same script which is copied from /downloads/qmailrocks/scripts/finalize location to /var/qmail/bin directory, as a result of running the the /downloads/qmailrocks/scripts/finalize/linux/finalize_linux.script script-file, in the start of QMR step 9. QMR also makes this executable , and link it in /usr/bin the same way.

The supervise scripts:

Note: QMR already has these scripts ready in a specific directory (/downloads/qmailrocks/scripts/finalize/freebsd/) . It just copies these files at the same locations where LWQ suggests. This was revealed from studying the script (finalize_linux.script), which QMR runs in part 9.

Now create the supervise directories for the qmail services [LWQ]:

mkdir -p /var/qmail/supervise/qmail-send/log
mkdir -p /var/qmail/supervise/qmail-smtpd/log

Note: QMR also creates these directories, when a script named qmr_install_linux-s1.script is run.


JMS qmail-send run script looks like this:

VQ="/var/qmail"
exec env - PATH="$VQ/bin:/usr/local/bin:/usr/bin:/bin" \
  qmail-start ./Maildir/

This is in-fact an almost the same as the /var/qmail/rc file. Apparently JMS doesn't want to use /var/qmail/rc in his scripts, and would rather (kind of) hard-code the same.

Create the /var/qmail/supervise/qmail-send/run file:

cat > /var/qmail/supervise/qmail-send/run << EOF
#!/bin/sh
exec /var/qmail/rc
EOF

[QMR's send_run file has same contents, for this file.]


Now the qmail-send/log/run file:

The /var/qmail/supervise/qmail-send/log/run file by LWQ, which I will use with some variation (shown later):

#!/bin/sh
exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail

Note: QMR also uses the same contents with a little variation. These variations are permitted / certified by DJB (http://cr.yp.to/daemontools/multilog.html) , and JMS ( http://qmail.jms1.net/scripts/ ). The QMR's send_log script, later copied in system as /var/qmail/supervise/qmail-send/log/run, looks like:

cat /downloads/qmailrocks/scripts/finalize/freebsd/send_log

#!/bin/sh
PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin
export PATH
exec setuidgid qmaill multilog t s100000 n20 /var/log/qmail/qmail-send 2>&1

A little explanation: s1000000 means that the current logfile will be rotated when reached a size of 100KB. And 20 such rotated log files will be retained by qmail / multilog. Older log files will automatically get deleted. We will adopt this variation and use this. I just want to raise the size-limit of the logfile to 50MB and 20 generations of this file. This will result in a total of 1GB of disk consumed by my qmail logs. You can adjust as per your requirements. Note: I think there is no need to "export" the PATH.


JMS provides a script at (http://qmail.jms1.net/scripts/service-any-log-run) location. Which looks like:

VQ="/var/qmail"

exec env - PATH="$VQ/bin:/usr/local/bin:/usr/bin:/bin" \
  multilog t n1024 s1048576 ./main \
    '-*' '+*ver: status:*' =lstatus

JMS calls it “service-any-log-run” because you can use it to log any service you want to, such as qmail-send, qmail-smtpd, etc. He uses the technique of using relative file name instead of absolute file names. That means that if this script it run under qmail-send/log/ directory, it will create a file “main” over there. The cryptic line at the end of the script is basically removal of all log lines except the ones with “ver” and “status” in them. This indicated minimal logging being done. Default is that all lines will be logged. He is keeping 1024 generations of this log file (n1024) , each one being 1MB in size (s1048576).

For detailed explanation of multilog options, look here: http://cr.yp.to/daemontools/multilog.html

Alright, the final version of my /var/qmail/supervise/qmail-send/log/run file looks like:

cat > /var/qmail/supervise/qmail-send/log/run << EOF
#!/bin/sh
PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin
exec setuidgid qmaill multilog t s50000000 n20 /var/log/qmail/qmail-send 2>&1
EOF

Look here for more explanations: http://cr.yp.to/daemontools/multilog.html http://qmail.jms1.net/logfiles.shtml http://qmail.jms1.net/scripts/service-any-log-run

The qmail-smtpd/run file:

Here is the LWQ version of the qmail-smtpd/run file:

#!/bin/sh
QMAILDUID=`id -u qmaild`
NOFILESGID=`id -g qmaild`
MAXSMTPD=`cat /var/qmail/control/concurrencyincoming`
LOCAL=`head -1 /var/qmail/control/me`

if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" -o -z "$LOCAL" ]; then
    echo QMAILDUID, NOFILESGID, MAXSMTPD, or LOCAL is unset in
    echo /var/qmail/supervise/qmail-smtpd/run
    exit 1
fi

if [ ! -f /var/qmail/control/rcpthosts ]; then
    echo "No /var/qmail/control/rcpthosts!"
    echo "Refusing to start SMTP listener because it'll create an open relay"
    exit 1
fi

exec /usr/local/bin/softlimit -m 2000000 \
    /usr/local/bin/tcpserver -v -R -l "$LOCAL" -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \
        -u "$QMAILDUID" -g "$NOFILESGID" 0 smtp /var/qmail/bin/qmail-smtpd 2>&1

The QMR version of qmail-smtpd/run file is below. When the finalize_linux.script script is run in QMR part 9, this file gets copied as /var/qmail/supervise/qmail-smtpd/run file. The differences from LWQ are highlighted:

[root@qmail freebsd]# cat /downloads/qmailrocks/scripts/finalize/freebsd/smtpd_run
#!/bin/sh
QMAILDUID=`id -u vpopmail`
NOFILESGID=`id -g vpopmail`
MAXSMTPD=`cat /var/qmail/control/concurrencyincoming`
LOCAL=`head -1 /var/qmail/control/me`
if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" -o -z "$LOCAL" ]; then
echo QMAILDUID, NOFILESGID, MAXSMTPD, or LOCAL is unset in
echo /var/qmail/supervise/qmail-smtpd/run
exit 1
fi
if [ ! -f /var/qmail/control/rcpthosts ]; then
echo "No /var/qmail/control/rcpthosts!"
echo "Refusing to start SMTP listener because it'll create an open relay"
exit 1
fi
exec /usr/local/bin/softlimit -m 30000000 \
/usr/local/bin/tcpserver -v -R -l "$LOCAL" -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \
-u "$QMAILDUID" -g "$NOFILESGID" 0 smtp \
/var/qmail/bin/qmail-smtpd mail.example.com \
/usr/home/vpopmail/bin/vchkpw /usr/bin/true 2>&1
[root@qmail freebsd]#

Note: [LWQ]: concurrencyincoming isn't a standard qmail control file. It's a feature of the above script. Also, that's -1 (dash one) on the LOCAL line and -l (dash ell) on the tcpserver line.

Note: [LWQ]: The memory limit specified in the softlimit command may need to be raised depending upon your operating system and hardware platform. If attempts to connect to port 25 fail or remote systems are unable to send you mail, or you see a message like:

/usr/local/bin/tcpserver: error while loading shared libraries:
libc.so.6: failed to map segment from shared object: Cannot allocate memory 

, then try raising it to 3000000 or 4000000, or whatever you can afford based on your system resources.


Note: You will need to create the concurrencyincoming control file as used in the smtpd/run scripts above (IF you use above script, that is!):

echo 20 > /var/qmail/control/concurrencyincoming
chmod 644 /var/qmail/control/concurrencyincoming


The strange thing is that why QMR's author is using vpopmail as QMAILUID and NOFILESGID variables?

Answer: The following link ( http://qmail.jms1.net/upgrade-qmr.shtml) from JMS website clearly indicates the problems you may run into, IF you run qmail-smtpd as uid of vpopmail. Here is the explanation from the mentioned web-link:

The qmail-smtpd program handles the server end of an SMTP connection. It was originally designed to run as the userid qmaild. However, the /service/qmail-smtp/run script that qmailrocks installs sets things up so that qmail-smtpd runs as the vpopmail user, which means that a bug in qmail-smtpd (or in any of the programs that it calls, such as qmail-scanner, clamav, or spamassassin) could possibly erase all of your users' mailboxes. Not cool. My scripts set things up so that qmail-smtpd runs as the qmaild user, as djb originally designed it. Why did qmailrocks change from djb's standard? qmailrocks sets things up to use vpopmail's vchkpw program to validate any AUTH commands. And in order for vchkpw to read the files which actually contain the passwords (or the MD5 hashes of the passwords, or the file containing login information to a mysql server with that information) it needs to run as the vpopmail user. At some point in the past, somebody decided that the best way to allow vchkpw to access these files was to run qmail-smtpd as the vpopmail user, and apparently qmailrocks blindly copied that person's "run" script when putting the qmailrocks package together. There are two alternatives to this, both of which are more secure: You can give vchkpw the permissions it needs by making it "setuid", so that no matter which userid starts the program, it will always run as the vpopmail user. To me this option makes more sense than running qmail-smtpd itself as the vpopmail user, since a malicious email crafted to take advantage of some as-yet unknown security hole in clamav, spamassassin, or qmail-scanner, would not be able to access or delete any messages from your users' mailboxes- becasue only vchkpw runs as the vpopmail user (which owns all of the vpopmail mailbox directories) while the other programs continue to run as the qmaild user (or the qscand user, if you run qmail-scanner the same way I do.) The vfixpermissions script will make your vchkpw binary setuid, along with fixing the ownership and permissions of everything else under the vpopmail user's home directory (which is where vpopmail stores everything.) The AUTH_CDB patch, which is part of the newer versions of the combined patch, allows you to create a .cdb file (I use the name "auth.cdb" for this) which contains the valid userids and their encrypted passwords, and make that one file readable to the userid as which qmail-smtpd runs. Either option is preferable to making qmail-smtpd, plus all of the child processes it runs, run as the vpopmail user.

The qmail-smtpd/run file by JMS

The qmail-smtpd/run file by JMS is quite big. Download-able from (http://qmail.jms1.net/scripts/service-qmail-smtpd-run) . It has a lot of options in it, which are explained here: http://qmail.jms1.net/scripts/service-qmail-smtpd-run.shtml

cd /downlaods
wget http://qmail.jms1.net/scripts/service-qmail-smtpd-run

Let's have a look at the script :-)

[root@qmail downloads]# cat service-qmail-smtpd-run 
#!/bin/sh                                           
#                                                   
# service-qmail-smtpd-run (formerly "run.smtp" and "run.smtp.sslserver")
# John Simpson <jms1@jms1.net> 2003-07-05 to 2008-03-24                 
#                                                                       
# Generic daemontools "run" script for qmail "smtp" or "smtpssl" service.
#                                                                        
# Documentation: http://qmail.jms1.net/scripts/service-qmail-smtpd-run.shtml

exec 2>&1
VQ="/var/qmail"
PATH="$VQ/bin:/usr/local/bin:/usr/bin:/bin"
QUSER=qmaild                               
LOCAL=`head -1 $VQ/control/me`             

###############################################################################
#                                                                              
# options for tcpserver/sslserver                                              

IP=unset
PORT=25 
SSL=0   
SSL_CERT="$VQ/control/servercert.pem"
SMTP_CDB="/etc/tcp/smtp.cdb"         
MAX=30                               

# these require the "tcpserver limits" patch for ucspi-tcp, available here:
# http://linux.voyager.hr/ucspi-tcp/                                       

#MAXLOAD=750
#MAXCONNIP=2
#MAXCONNC=5 
#DIEMSG="421 $LOCAL Service temporarily unavailable"

# my newer version of the tcpserver limits patch allows you to specify
# individual DIEMSG values for each policy.                           
# http://qmail.jms1.net/ucspi-tcp/                                    

#DIEMSG_MAXLOAD="421 $LOCAL Server busy, try again later."
#DIEMSG_MAXCONNIP="421 $LOCAL Too many connections from your IP."
#DIEMSG_MAXCONNC="421 $LOCAL Too many connections from your network."

###############################################################################
#                                                                              
# options for programs which run before qmail-smtpd                            

#RBLSMTPD_PROG="rblsmtpd"
#RBL_GOOD=""             
#RBL_BAD="zen.spamhaus.org dnsbl.njabl.org dnsbl.sorbs.net bl.spamcop.net"

#GREYLIST="jgreylist"

#JGREYLIST_DIR="$VQ/jgreylist"
#JGREYLIST_NOREV=1            
#JGREYLIST_BY_IP=0            
#JGREYLIST_HOLDTIME=120       
#JGREYLIST_LOG=1              
#JGREYLIST_LOG_PID=1          
#JGREYLIST_LOG_SMTP=0         
#JGREYLIST_TIMEOUT=60         
#JGREYLIST_LIMIT=0            

#RECORDIO="recordio"

###############################################################################
#                                                                              
# options for qmail-smtpd itself                                               

SMTPD="qmail-smtpd"
#SMTPGREETING="$LOCAL NO UCE"
#GREETDELAY=30               
#DROP_PRE_GREET=1            
FORCE_TLS=0                  
DENY_TLS=0                   
MFCHECK=3                    
#MAXRCPT=100                 
#RELAYREJ=1                  
QMAILSMTPD_LOG_MAIL=1        
QMAILSMTPD_LOG_RCPT=1        
#QMAILSMTPD_HELP_VERSION=1   

###############################################################################
#                                                                              
# options pertaining to the AUTH command.                                      

AUTH=0
REQUIRE_AUTH=0
ALLOW_INSECURE_AUTH=0

# if using the AUTH_CDB method
#AUTH_CDB="$VQ/control/auth.cdb"

# if using the CHECKPW method
CHECKPW=~vpopmail/bin/vchkpw 
TRUE=`which true`            

# to change the environment whenever somebody authenticates
#AUTH_SET_MFCHECK=0                                        
#AUTH_SET_MAXRCPT=0                                        
#AUTH_SET_DATABYTES=0                                      
#AUTH_SET_SPFBEHAVIOR=1                                    
#AUTH_SET_VALIDRCPTTO_LIMIT=10                             
#AUTH_SET_VALIDRCPTTO_LOG=1                                
#AUTH_SET_SPF_LOG=1                                        
#AUTH_SET_RELAYREJ=0                                       
#AUTH_SET_VALIDRCPTTO_CDB=""                               
#AUTH_SET_QMAILSMTPD_LOG_MAIL=1                            
#AUTH_SET_QMAILSMTPD_LOG_RCPT=1                            
#AUTH_SET_QMAILSMTPD_HELP_VERSION=1                        

###############################################################################
#                                                                              
# options pertaining to the "validrcptto.cdb" mechanism.                       
# see http://qmail.jms1.net/patches/validrcptto.cdb.shtml for details.         

VALIDRCPTTO_CDB="$VQ/control/validrcptto.cdb"
VALIDRCPTTO_LIMIT=10                         
VALIDRCPTTO_LOG=2                            

###############################################################################
#                                                                              
# options pertaining to the SPF mechanism.                                     

SPFBEHAVIOR=3
SPF_LOG=1    
SPF_BLOCK_PLUS_ALL=1

###############################################################################
#                                                                              
# options pertaining to the Domainkeys mechanism.                              
# this requires an add-on patch.                                               

#DOMAINKEYS=0
#DKVERIFY=DEfGhIJK
#AUTH_SET_DKSIGN=/etc/domainkeys/%/default

###############################################################################
#                                                                              
# options for programs which run after qmail-smtpd                             

# if you are using simscan...

#QMAILQUEUE="$VQ/bin/simscan"
NOP0FCHECK=1                 
#SIMSCAN_DEBUG=0             
#SIMSCAN_DEBUG_FILES=0       

# if you are using qmail-scanner, un-comment ONE of these lines.

#QMAILQUEUE="$VQ/bin/qmail-scanner-queue"
#QMAILQUEUE="$VQ/bin/qmail-scanner-queue.pl"

# if you're using some other qmail-queue replacement, add your own line here
# with the correct value.                                                   


###############################################################################
###############################################################################
###############################################################################
#                                                                              
# THERE SHOULD BE NO NEED TO CHANGE ANYTHING BELOW THIS LINE. of course, the   
# script is on your system and you're free to edit it however you want, but    
# changing things below this point may cause strange things to happen. make    
# sure you understand what you're doing if you change anything below...        

QDUID=`id -u $QUSER`
QDGID=`id -g $QUSER`

if [ -z "$IP" -o "$IP" = "unset" ]
then                              
        echo "The IP variable is not set in the run script. Cannot start."
        sleep 5                                                           
        exit 1                                                            
fi                                                                        

if [ -z "$QDUID" -o -z "$QDGID" -o -z "$MAX" -o -z "$LOCAL" \
        -o -z "$SSL" -o -z "$AUTH" ]                         
then                                                         
        echo "One of the variables QDUID, QDGID, MAX, LOCAL, SSL, or AUTH"
        echo "is not set in the run script. Cannot start."                
        sleep 5                                                           
        exit 1                                                            
fi                                                                        

if [ ! -f $VQ/control/rcpthosts ]
then                             
        echo Creating emtpy $VQ/control/rcpthosts file to prevent open relay.
        touch $VQ/control/rcpthosts                                          
        chmod 644 $VQ/control/rcpthosts                                      
fi                                                                           

if [ "$SSL" = "1" ]
then               
        if ! which sslserver > /dev/null 2>&1
        then                                 
                echo ERROR: sslserver not found in PATH [$PATH]
                exit 1                                         
        fi                                                     

        if [ ! -f $SSL_CERT ]
        then                 
                echo ERROR: $SSL_CERT does not exist
                exit 1                              
        fi                                          

        export CERTFILE=${SSL_CERT}
        export KEYFILE=""          
        export DHFILE=""           

        SCMD="sslserver -e"
else                       
        if [ -n "$SSL_CERT" ]
        then                 
                export TLS_SERVER_CERT=${SSL_CERT}
        fi                                        

        SCMD="tcpserver"
fi                      

if [ "$IP" = "127.0.0.1" ]
then                      
        export RELAYCLIENT=""
        RBLSMTPD_PROG=""     
        ACMD=""              
elif [ -z "${SMTP_CDB:-}" ]  
then                         
        ACMD=""              
else                         
        if [ ! -f "$SMTP_CDB" ]
        then                   
                echo ERROR: $SMTP_CDB does not exist
                exit 1                              
        fi                                          

        ACMD="-x $SMTP_CDB"
fi                         

if [ "$AUTH" = "1" ]
then                
        if [ -n "$AUTH_CDB" ]
        then                 
                if [ ! -f $AUTH_CDB ]
                then                 
                        echo ERROR: AUTH_CDB file [$AUTH_CDB] does not exist
                        exit 1                                              
                fi                                                          

                export AUTH_CDB
                ARGS=""        
        elif [ -n "$CHECKPW" ] 
        then                   
                if [ ! -f $CHECKPW ]
                then                
                        echo ERROR: $CHECKPW [$CHECKPW] program does not exist
                        exit 1                                                
                fi                                                            

                if [ -z "$LOCAL" ]
                then              
                        echo ERROR: LOCAL is not set in the run script
                        exit 1                                        
                elif [ -z "$TRUE" ]                                   
                then                                                  
                        echo ERROR: TRUE is not set in the run script 
                        exit 1                                        
                elif [ ! -e $TRUE ]                                   
                then                                                  
                        echo ERROR: $TRUE [$TRUE] is not an executable
                        exit 1                                        
                fi                                                    

                ARGS=" $LOCAL $CHECKPW $TRUE"
        else                                 
                echo ERROR: AUTH=1 but no AUTH_CDB or CHECKPW
                exit 1                                       
        fi                                                   
else                                                         
        ARGS=""                                              
        AUTH_CDB=""                                          
fi                                                           

########################################
# make RBL command (if needed)          

RBLCMD=""

if [ -n "$RBLSMTPD_PROG" ]
then                      
        if [ -n "$RBL_GOOD" ]
        then                 
                for name in $RBL_GOOD
                do                   
                        RBLCMD="$RBLCMD -a $name"
                done                             
        fi                                       

        if [ -n "$RBL_BAD" ]
        then                
                for name in $RBL_BAD
                do                  
                        RBLCMD="$RBLCMD -r $name"
                done                             
        fi                                       

        if [ -n "$RBLCMD" ]
        then               
                RBLCMD="$RBLSMTPD_PROG -t0 $RBLCMD"
        fi                                         
fi                                                 

########################################
# make domainkeys command (if needed)   

if [ "$DOMAINKEYS" = "1" ]
then                      
        if [ -f "$VQ/bin/qmail-dk" ]
        then                        
                if [ -n "$QMAILQUEUE" ]
                then                   
                        export DKQUEUE="$QMAILQUEUE"
                fi                                  
                export AUTH_UNSET_DKVERIFY=1        
                export QMAILQUEUE="$VQ/bin/qmail-dk"

                if [ -n "$DKVERIFY" ] ; then export DKVERIFY ; fi
                if [ -n "$DKSIGN"   ] ; then export DKSIGN   ; fi
        else                                                     
                echo ERROR: $VQ/bin/qmail-dk not found, cannot use domainkeys
        fi                                                                   
fi                                                                           

########################################
# handle variables which may not have been set, but need to exist even
# if they contain blank values                                        

if [ -z "$RECORDIO" ]
then                 
        RECORDIO=""  
fi                   

if [ -z "$GREYLIST" ]
then                 
        GREYLIST=""  
fi                   

########################################
# do the deed                           

for n in SSL                                    \
        MAXLOAD                                 \
        MAXCONNIP                               \
        MAXCONNC                                \
        DIEMSG                                  \
        DIEMSG_MAXLOAD                          \
        DIEMSG_MAXCONNIP                        \
        DIEMSG_MAXCONNC                         \
        JGREYLIST_DIR                           \
        JGREYLIST_NOREV                         \
        JGREYLIST_BY_IP                         \
        JGREYLIST_HOLDTIME                      \
        JGREYLIST_LOG                           \
        JGREYLIST_LOG_PID                       \
        JGREYLIST_LOG_SMTP                      \
        JGREYLIST_TIMEOUT                       \
        JGREYLIST_LIMIT                         \
        SMTPGREETING                            \
        GREETDELAY                              \
        DROP_PRE_GREET                          \
        FORCE_TLS                               \
        DENY_TLS                                \
        MFCHECK                                 \
        MAXRCPT                                 \
        RELAYREJ                                \
        QMAILSMTPD_LOG_MAIL                     \
        QMAILSMTPD_LOG_RCPT                     \
        QMAILSMTPD_HELP_VERSION                 \
        REQUIRE_AUTH                            \
        ALLOW_INSECURE_AUTH                     \
        AUTH_CDB                                \
        AUTH_SET_MFCHECK                        \
        AUTH_SET_MAXRCPT                        \
        AUTH_SET_DATABYTES                      \
        AUTH_SET_SPFBEHAVIOR                    \
        AUTH_SET_VALIDRCPTTO_LIMIT              \
        AUTH_SET_VALIDRCPTTO_LOG                \
        AUTH_SET_SPF_LOG                        \
        AUTH_SET_RELAYREJ                       \
        AUTH_SET_VALIDRCPTTO_CDB                \
        AUTH_SET_QMAILSMTPD_LOG_MAIL            \
        AUTH_SET_QMAILSMTPD_LOG_RCPT            \
        AUTH_SET_QMAILSMTPD_HELP_VERSION        \
        VALIDRCPTTO_CDB                         \
        VALIDRCPTTO_LIMIT                       \
        VALIDRCPTTO_LOG                         \
        SPFBEHAVIOR                             \
        SPF_LOG                                 \
        SPF_BLOCK_PLUS_ALL                      \
        DKVERIFY                                \
        AUTH_SET_DKSIGN                         \
        QMAILQUEUE                              \
        NOP0FCHECK                              \
        SIMSCAN_DEBUG                           \
        SIMSCAN_DEBUG_FILES
do
        # note: not 100% sure "eval" works under old-school /bin/sh
        eval "if [ -n \"\$$n\" ];then echo \"$n=\\\"\$$n\\\"\";export $n;fi"
done

CMD="$SCMD -vR -l $LOCAL -c $MAX -u $QDUID -g $QDGID $ACMD $IP $PORT"
CMD="$CMD $RBLCMD $GREYLIST $RECORDIO $SMTPD $ARGS"

echo "command-line: exec $CMD 2>&1"
exec $CMD 2>&1

########################################
# this will only be reached if the exec fails

echo ERROR: command did not run correctly
exit 1
[root@qmail downloads]#

Below is the short summary of the tcpserver options used in the qmail-smtpd/run scripts shown above. Details about the tcpserver command/program can be studied from the following location: http://cr.yp.to/ucspi-tcp/tcpserver.html .

Summary of tcpserver options:

Syntax: tcpserver opts host port prog

Where: opts is a series of getopt-style options; host is one argument; port is one argument; prog consists of one or more arguments. tcpserver waits for connections from TCP clients. For each connection, it runs prog, with descriptor 0 reading from the network and descriptor 1 writing to the network. It also sets up several environment variables.

General options:

-v: Verbose. Print error messages and status messages.

Connection options:

  • -c n: Do not handle more than n simultaneous connections. If there are n simultaneous copies of prog running, defer acceptance of a new connection until one copy finishes. n must be a positive integer. Default: 40.
  • -x cdb: Follow the rules compiled into cdb by tcprules. These rules may specify setting environment variables or rejecting connections from bad sources. You can rerun tcprules to change the rules while tcpserver is running.
  • -g gid: Switch group ID to gid after preparing to receive connections. gid must be a positive integer.
  • -u uid: Switch user ID to uid after preparing to receive connections. uid must be a positive integer.
  • -1: After preparing to receive connections, print the local port number to standard output.

Data-gathering options:

  • -l localname: Do not look up the local host name in DNS; use localname for the environment variable $TCPLOCALHOST. A common choice for localname is 0. To avoid loops, you must use this option for servers on TCP port 53.
  • -R: Do not attempt to obtain $TCPREMOTEINFO from the remote host. To avoid loops, you must use this option for servers on TCP ports 53 and 113.


the softlimit program

A little explanation of the softlimit program (by DJB), from the link: http://cr.yp.to/daemontools/softlimit.html

softlimit runs another program with new resource limits. Syntax: softlimit opts child Where: opts is a series of getopt-style options; child consists of one or more arguments. softlimit sets soft resource limits as specified by opts. It then runs child program.

Options In each of the following options, n may be =, indicating that the soft limit should be set equal to the hard limit.

Options controlling memory use:

  • -m n: Same as -d n -s n -l n -a n.
  • -d n: Limit the data segment per process to n bytes.
  • -s n: Limit the stack segment per process to n bytes.
  • -l n: Limit the locked physical pages per process to n bytes. This option has no effect on some operating systems.
  • -a n: Limit the total of all segments per process to n bytes. This option has no effect on some operating systems.
  • -o n: Limit the number of open file descriptors per process to n. This option has no effect on some operating systems.
  • -p n: Limit the number of processes per uid to n.

Options controlling file sizes:

  • -f n: Limit output file sizes to n bytes.
  • -c n: Limit core file sizes to n bytes.

Efficiency options:

  • -r n: Limit the resident set size to n bytes. This limit is not enforced unless physical memory is full.
  • -t n: Limit the CPU time to n seconds. This limit is not enforced except that the process receives a SIGXCPU signal after n seconds.

Notice that JMS does not use softlimit in his qmail-smtpd/run script. The reason I see is that in modern linux systems the limits can be controlled through /etc/security/limits.conf file. And more importantly most of the limits are now controlled by the kernel itself, in the shape of better resource management. So apparently there is no need to run your programs as a softlimit's child. [Anyone with a better explanation?]


Conclusion for qmail-smtpd/run script:

Copy the downloaded smtpd-run file to /var/qmail/supervise/qmail-smtpd/run .

cp /downloads/service-qmail-smtpd-run /var/qmail/supervise/qmail-smtpd/run

Before we go on and edit the file, I would advise you to check the list/details of patches, on this location (http://qmail.jms1.net/patches/combined-details.shtml), which JMS has included in his combined patch. It is a 22 page document , if you print it on A4 size paper! This wwould definitely help us what to select / enable, and what not.

It mainly contains vpopmail passwd program, Grey Listing checks, Delays, SPF, RBL, AUTH mechanism, DomainKeys QmailScanner, etc.

I have still not installed the grey-listing software, Qmail-Scanner, and domain keys. So I have not enabled them yet in this qmail-smtpd/run script.

Edit this file and adjust according to your needs. (The SMTP_CDB needs to be updated. It should not be /etc/tcp/smtp.cdb . This is updated after encountering an error a little later.)

vi /var/qmail/supervise/qmail-smtpd/run
#(my configuration part of the script looks like this):
exec 2>&1                                                                   
VQ="/var/qmail"                                                             
PATH="$VQ/bin:/usr/local/bin:/usr/bin:/bin"                                 
QUSER=qmaild                                                                
LOCAL=`head -1 $VQ/control/me`                                              
IP=192.168.122.90                                                           
PORT=25                                                                     
SSL=0                                                                       
#SSL_CERT="$VQ/control/servercert.pem"                                       
SMTP_CDB="/etc/tcp/smtp.cdb"                                                
MAX=30                                                                      
MAXLOAD=150                                                                 
MAXCONNIP=2                                                                 
MAXCONNC=5                                                                  
DIEMSG="421 $LOCAL Service temporarily unavailable"                         
DIEMSG_MAXLOAD="421 $LOCAL Server busy, try again later."                   
DIEMSG_MAXCONNIP="421 $LOCAL Too many connections from your IP."            
DIEMSG_MAXCONNC="421 $LOCAL Too many connections from your network."        
RBLSMTPD_PROG="rblsmtpd"                                                    
RBL_GOOD=""                                                                 
RBL_BAD="zen.spamhaus.org bl.spamcop.net"                                   
SMTPD="qmail-smtpd"                                                         
SMTPGREETING="$LOCAL NO UCE"                                                
#GREETDELAY=30                                                               
DROP_PRE_GREET=1                                                            
FORCE_TLS=0                                                                 
DENY_TLS=0                                                                  
MFCHECK=3                                                                   
MAXRCPT=100                                                                 
RELAYREJ=1                                                                  
QMAILSMTPD_LOG_MAIL=1                                                       
QMAILSMTPD_LOG_RCPT=1                                                       
QMAILSMTPD_HELP_VERSION=1                                                   
AUTH=0                                                                      
REQUIRE_AUTH=0                                                              
ALLOW_INSECURE_AUTH=0                                                       
#CHECKPW=~vpopmail/bin/vchkpw                                                
#TRUE=`which true`                                                           
#VALIDRCPTTO_CDB="$VQ/control/validrcptto.cdb"                               
#VALIDRCPTTO_LIMIT=10                                                        
#VALIDRCPTTO_LOG=2                                                           
SPFBEHAVIOR=3                                                               
SPF_LOG=1                                                                   
SPF_BLOCK_PLUS_ALL=1                                
. . . 
. . . 


Note: If you do not select the options correctly in the run file, your qmail will start, but when you try to connect to it, it will show you an error. Such as:

[kamran@kworkbee ~]$ telnet qmail.example.com 25
Trying 192.168.122.90...
Connected to qmail.example.com.
Escape character is '^]'.
421 unable to read controls (#4.3.0)
Connection closed by foreign host.
[kamran@kworkbee ~]$

So, the tip is to enable few things at a time and work gradually to a securer system.


Time to create the qmail-smtpd/log/run file:

The qmail-smtpd/log/run file:-

Now is the time to create the /var/qmail/supervise/qmail-smtpd/log/run file:

cat > /var/qmail/supervise/qmail-smtpd/log/run << EOF
#!/bin/sh
PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin
exec setuidgid qmaill multilog t s50000000 n20 /var/log/qmail/qmail-smtpd 2>&1
EOF

Note: I don't see a need to export the PATH, so I have removed that from the script above.

Make the run files executable [LWQ]:

    chmod 755 /var/qmail/supervise/qmail-send/run
    chmod 755 /var/qmail/supervise/qmail-send/log/run
    chmod 755 /var/qmail/supervise/qmail-smtpd/run
    chmod 755 /var/qmail/supervise/qmail-smtpd/log/run

Then set up the log directories[LWQ]: Note: We have already setup log directories a while ago, with a slight modification. So we will not execute the following three lines.

    mkdir /var/log/qmail
    mkdir -p /var/log/qmail/smtpd
    chown qmaill /var/log/qmail /var/log/qmail/smtpd


Finally, link the supervise directories into /service. However, please note that the qmail system will start automatically shortly after these links are created. So at this point you should make sure that no service is running on port 25, such as sendmail, postfix or exim. If they are running, it is time to stop them:

service sendmail stop
service exim stop
service postfix stop

[root@qmail ~]# netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 :::22                       :::*                        LISTEN      1799/sshd
tcp        0      0 ::ffff:192.168.122.90:22    ::ffff:192.168.122.1:56432  ESTABLISHED 2031/0
[root@qmail ~]#

Good! No SMTP software running. So lets link the qmail supervise directories into /service .

ln -s /var/qmail/supervise/qmail-send   /var/qmail/supervise/qmail-smtpd   /service

Note: The /service directory is created when daemontools is installed.

As mentioned just now, the qmail system would now be running. Lets check:

[root@qmail ~]# qmailctl stat
/service/qmail-send: up (pid 17094) 3 seconds
/service/qmail-send/log: up (pid 17095) 3 seconds
/service/qmail-smtpd: up (pid 17116) 1 seconds
/service/qmail-smtpd/log: up (pid 17098) 3 seconds
messages in queue: 0
messages in queue but not yet preprocessed: 0
[root@qmail ~]#

The qmail-smtpd service seems to be stuck at 1 second. This is not good. Lets try to find the reason:

[root@qmail ~]# tail /var/log/qmail/qmail-smtpd/current
@400000004a8d955234dccc7c ERROR: /etc/tcp/smtp.cdb does not exist
@400000004a8d955336fb5b04 ERROR: /etc/tcp/smtp.cdb does not exist
@400000004a8d9554382e1a5c ERROR: /etc/tcp/smtp.cdb does not exist
@400000004a8d95553982bd7c ERROR: /etc/tcp/smtp.cdb does not exist

Ahan!

Actually the qmail-smtpd/run file by JMS is looking for a the tcprules file named /etc/tcp/smtp.cdb . Whereas LWQ asks us to create a file named /etc/tcp.smtp . (I have still not created the file using the LWQ method as well). This means we have to adjust this value in qmail-smtpd/run script by JMS.

We know that in qmailctl file, we have a section as :-

  cdb)
    tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
    chmod 644 /etc/tcp.smtp.cdb
    echo "Reloaded /etc/tcp.smtp."

This means the compiled tcprules file is /etc/tcp.smtp.cdb . “not” /etc/tcp/smtp.cdb . This may be a typo from JMS or just a different location by his own preference. Lets adjust that (to /etc/tcp.smtp.cdb) in the qmail-smtpd/run file we downloaded from JMS site accordingly:-

SMTP_CDB="/etc/tcp.smtp.cdb"

It is also the right time to create the tcprules file. In LWQ, it is titled as SMTP Access Control.

Allow the local host to inject mail via SMTP:

echo '127.:allow,RELAYCLIENT=""' >>/etc/tcp.smtp

Now execute the following command to compile CDB rules: [LWQ]

qmailctl cdb

Now lets stop qmail and start it again.

qmailctl stop
qmailctl start

# wait for a few seconds here
qmail stat

[root@qmail ~]# qmailctl stat
/service/qmail-send: up (pid 18357) 17 seconds
/service/qmail-send/log: up (pid 18356) 17 seconds
/service/qmail-smtpd: up (pid 18360) 17 seconds
/service/qmail-smtpd/log: up (pid 18361) 17 seconds
messages in queue: 0
messages in queue but not yet preprocessed: 0
[root@qmail ~]#

Alhumdulillah. As you can see, now your qmail-send and qmail-smtpd (and their respective log services) are all up for the same amount of time. This indicates all is well. Check through netstat as well:

[root@qmail ~]# netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 192.168.122.90:25           0.0.0.0:*                   LISTEN      2012/tcpserver
tcp        0      0 :::22                       :::*                        LISTEN      1799/sshd
tcp        0      0 ::ffff:192.168.122.90:22    ::ffff:192.168.122.1:56432  ESTABLISHED 2031/0
[root@qmail ~]#

Plus, you will also see the following in the log files. Just to make sure things are good.

[root@qmail ~]# tail -f /var/log/qmail/qmail-smtpd/current 
. . . 
. . . 
@400000004a8d98fc2ced80c4 SSL="0"
@400000004a8d98fc2cf06adc MAXLOAD="150"
@400000004a8d98fc2cf1f564 MAXCONNIP="2"
@400000004a8d98fc2cf43784 MAXCONNC="5"
@400000004a8d98fc2cf5cdc4 DIEMSG="421 qmail.example.com Service temporarily unavailable"
@400000004a8d98fc2cf8a06c DIEMSG_MAXLOAD="421 qmail.example.com Server busy, try again later."
@400000004a8d98fc2cfa59d4 DIEMSG_MAXCONNIP="421 qmail.example.com Too many connections from your IP."
@400000004a8d98fc2cfca7ac DIEMSG_MAXCONNC="421 qmail.example.com Too many connections from your network."
@400000004a8d98fc2d09135c SMTPGREETING="qmail.example.com NO UCE"
@400000004a8d98fc2d0cd064 DROP_PRE_GREET="1"
@400000004a8d98fc2d0e7a2c FORCE_TLS="0"
@400000004a8d98fc2d10106c DENY_TLS="0"
@400000004a8d98fc2d123f04 MFCHECK="3"
@400000004a8d98fc2d13bdd4 MAXRCPT="100"
@400000004a8d98fc2d16425c RELAYREJ="1"
@400000004a8d98fc2d180f4c QMAILSMTPD_LOG_MAIL="1"
@400000004a8d98fc2d1a3de4 QMAILSMTPD_LOG_RCPT="1"
@400000004a8d98fc2d1c0ad4 QMAILSMTPD_HELP_VERSION="1"
@400000004a8d98fc2d1e5c94 REQUIRE_AUTH="0"
@400000004a8d98fc2d20065c ALLOW_INSECURE_AUTH="0"
@400000004a8d98fc2d37cc4c SPFBEHAVIOR="3"
@400000004a8d98fc2d394f04 SPF_LOG="1"
@400000004a8d98fc2d3bbc1c SPF_BLOCK_PLUS_ALL="1"
@400000004a8d98fc2d40964c NOP0FCHECK="1"
@400000004a8d98fc2d45aefc command-line: exec tcpserver -vR -l qmail.example.com -c 30 -u 702 -g 700 -x /etc/tcp.smtp.cdb 192.168.122.90 25 rblsmtpd -t0  -r zen.spamhaus.org -r bl.spamcop.net   qmail-smtpd  2>&1
@400000004a8d98fc2d6d0d1c tcpserver: status: 0/30

[root@qmail ~]# 

qmail-smtpd seems good!

[root@qmail ~]# tail -f /var/log/qmail/qmail-send/current
. . . 
@400000004a8d949a05aab4dc status: local 0/10 remote 0/20
@400000004a8d94ab0fdfdd9c status: qmail-todo stop processing asap
@400000004a8d94ab0fe000c4 status: exiting
@400000004a8d94b32d8c87b4 status: local 0/10 remote 0/20
@400000004a8d95411e2ad8d4 status: qmail-todo stop processing asap
@400000004a8d95411e2afbfc status: exiting
@400000004a8d95411f7f1664 status: local 0/10 remote 0/20
@400000004a8d98fc29f2ea1c status: qmail-todo stop processing asap
@400000004a8d98fc29f3865c status: exiting
@400000004a8d98fc2c477cc4 status: local 0/10 remote 0/20

qmail-send also seems good.

Note: There is no log entry for these (qmail start / stop /error events) in /var/log/messages , or in /var/log/maillog .

Alhumdulillah.


Note: Linking of the supervise script directories in /service directory and the following line added in the /etc/inittab file ensures that the qmail service will be started at system boot time.

tail /etc/inittab
SV:123456:respawn:/command/svscanboot

<<<<<<< End of day >>>>>>

Time to remove any other SMTP software from your system.

rpm -e sendmail sendmail-cf exim postfix --nodeps

[root@qmail ~]# rpm -e sendmail sendmail-cf exim postfix --nodeps
error: package sendmail is not installed
error: package sendmail-cf is not installed
error: package postfix is not installed
[root@qmail ~]#

Note [LWQ]: If you're using an RPM-based Linux distribution like Red Hat, removing the MTA package might cause problems down the road. Utilities that update the system might try to reinstall Sendmail, or MUA packages might not install because they can't tell an MTA is installed. Mate Wierdl provides a stub package called "fake_mta" that can be installed to prevent these problems. Simply install the RPM available from ftp://ftp.csi.hu/mw/fake_mta-1-10memphis.noarch.rpm .

I could not find the fake_mta on the net. (Purely my fault). So I am skipping it.

[LWQ]: Lastly, replace any existing /usr/lib/sendmail with the qmail version:

mv /usr/lib/sendmail /usr/lib/sendmail.old                  # ignore any errors
mv /usr/sbin/sendmail /usr/sbin/sendmail.old                # ignore any errors
chmod 000 /usr/lib/sendmail.old /usr/sbin/sendmail.old        # ignore any errors
ln -s /var/qmail/bin/sendmail /usr/lib
ln -s /var/qmail/bin/sendmail /usr/sbin

QMR does the same in Part-10.

Note[LWQ]: It's important to create the sendmail links, regardless of the previous MTA, if any. The sendmail command is invoked by many applications for sending mail.

Note: QMR , when it runs the finalize_linux.script in part 9, copies the smtpd_ssl and pop3d run scripts as well to the supervise directory. Also sets up links in the /service directory for them. We are not going to use QMR's smtpd_ssl , at least for now. And about pop3, though it seems very tempting, I would not install qmail's own pop3 daemon, because, I will be using the pop3 and IMAP services of either Courier or DoveCot. So no need to go into hassle of installing qmail-pop3 in the first place.


[LWQ]: Create System Aliases There are three system aliases that should be created on all qmail installations:

  • Alias Purpose
  • postmaster RFC 2821 required, points to the mail adminstrator (you)
  • mailer-daemon de facto standard recipient for some bounces
  • root redirects mail from privileged account to the system administrator
  • abuse de facto standard recipient for abuse complaints


To create these aliases, decide where you want each of them to go (a local user or a remote address) and create and populate the appropriate .qmail files. For example, say local user dave is both the system and mail administrator:

#echo dave > /var/qmail/alias/.qmail-root
#echo dave > /var/qmail/alias/.qmail-postmaster
#ln -s .qmail-postmaster /var/qmail/alias/.qmail-mailer-daemon
#ln -s .qmail-postmaster /var/qmail/alias/.qmail-abuse
#chmod 644 /var/qmail/alias/.qmail-root /var/qmail/alias/.qmail-postmaster

What I want to do is setup these links to point to postmaster@yourdomain.com . I will set them to postmaster@example.com . Note that QMR also creates these aliases.

echo postmaster@example.com  > /var/qmail/alias/.qmail-root
echo postmaster@example.com  > /var/qmail/alias/.qmail-postmaster
ln -s /var/qmail/alias/.qmail-postmaster /var/qmail/alias/.qmail-mailer-daemon
ln -s /var/qmail/alias/.qmail-postmaster /var/qmail/alias/.qmail-abuse
chmod 644 /var/qmail/alias/.qmail-root /var/qmail/alias/.qmail-postmaster

Test the Installation [LWQ]: qmail should now be running. First run qmailctl stat to verify that the services are up and running:

    # qmailctl stat
    /service/qmail-send: up (pid 30303) 187 seconds
    /service/qmail-send/log: up (pid 30304) 187 seconds
    /service/qmail-smtpd: up (pid 30305) 187 seconds
    /service/qmail-smtpd/log: up (pid 30308) 187 seconds
    messages in queue: 0
    messages in queue but not yet preprocessed: 0

All four services should be "up" for more than a second. If they're not, you've probably got a typo in the associated run script or you skipped one or more steps in creating the necessary files, directories, or links. Go back through the installation step-by-step and double check your work. You can also download and run the inst_check script, available from http://lifewithqmail.org/inst_check. For example:

    # sh inst_check
    ! /var/log/qmail has wrong owner, should be qmaill
    ...try: chown qmaill /var/log/qmail
    #
If inst_check finds problems, fix them and re-run it. When everything looks right, inst_check will report:
    Congratulations, your LWQ installation looks good!

So let's do that:

cd /downloads/
wget http://lifewithqmail.org/inst_check
chmod +x inst_check

[root@qmail downloads]# ./inst_check
! /var/qmail/control/concurrencyincoming is missing
...try: echo 20 >/var/qmail/control/concurrencyincoming
! /var/log/qmail has wrong mode, should be 755
...try: chmod 755 /var/log/qmail
! /var/log/qmail/smtpd is missing
...try: mkdir -p /var/log/qmail/smtpd
! Alias for root is missing
...try: echo me >/var/qmail/alias/.qmail-root
! Alias for postmaster is missing
...try: echo me >/var/qmail/alias/.qmail-postmaster
! Alias for mailer-daemon is missing
...try: echo me >/var/qmail/alias/.qmail-mailer-daemon
[root@qmail downloads]#

Wow! So many errors!

Actually I forgot to create the email aliases mentioned above. I created them now. Also created the concurrencyincoming file, and fixed the permissions of /var/log/qmail directory.

echo 20 >/var/qmail/control/concurrencyincoming
chmod 755 /var/log/qmail -R

The last check left is about missing /var/log/qmail/smtpd directory:

[root@qmail downloads]# ./inst_check
! /var/log/qmail/smtpd is missing
...try: mkdir -p /var/log/qmail/smtpd
[root@qmail downloads]#

You can ignore this error, as we are using a different name (/var/log/qmail/qmail-smtpd) for it. As shown below:

[root@qmail downloads]# ls /var/log/qmail/ -l
total 12
drwxr-xr-x 2 qmaill root 4096 Aug 18 15:32 qmail-pop3d
drwxr-xr-x 2 qmaill root 4096 Aug 21 12:11 qmail-send
drwxr-xr-x 2 qmaill root 4096 Aug 21 12:11 qmail-smtpd
[root@qmail downloads]#

However, if you want to fee happy, and desperate to see the congratulations message, you can try to create this directory and run the test script:

[root@qmail downloads]# mkdir /var/log/qmail/smtpd
[root@qmail downloads]# chown qmaill /var/log/qmail/smtpd/

[root@qmail downloads]# ./inst_check
Congratulations, your LWQ installation looks good!
[root@qmail downloads]#

Well, in this example you fooled the script!

Note: A little about QMR's qmr_isnt_check script: QMR runs the qmr_inst_check script in part 11. QMR has modified the default inst_check script from LWQ. The following differences exist. The “diff” is shown below with little summary in simple words explained further below:

[root@qmail downloads]# diff /downloads/qmailrocks/scripts/util/qmr_inst_check ./inst_check 
3,10d2                                                                                      
< # Qmailrocks, 2003-12-05                                                                  
< # I've modified Dave Sill's script slightly to accomodate                                 
< # the variations between his Qmail installation and the                                   
< # Qmailrocks.org installation. The Qmailrocks version                                     
< # of this script takes into account the slightly different                                
< # loggind directory setup and a few permissions differences.                              
< # http://www.qmailrocks.org/downloads/scripts/qmr_inst_check                              
<                                                                                           
15,16c7,8                                                                                   
< CHECKPOP=y                                                                                
< CHECKSEND=y                                                                               
---                                                                                         
> CHECKPOP=n                                                                                
>
191c183
<   echo "...try: echo 30 >$QMHOME/control/concurrencyincoming"
---
>   echo "...try: echo 20 >$QMHOME/control/concurrencyincoming"
197c189
< LOGDIRS="/var/log/qmail /var/log/qmail/qmail-smtpd"
---
> LOGDIRS="/var/log/qmail /var/log/qmail/smtpd"
199,202c191
<   LOGDIRS="$LOGDIRS /var/log/qmail/qmail-pop3d"
< fi
< if [ "$CHECKSEND" = "y" ]; then
<   LOGDIRS="$LOGDIRS /var/log/qmail/qmail-send"
---
>   LOGDIRS="$LOGDIRS /var/log/qmail/pop3d"
213,215c202,204
<   elif [ "`ls -ld $i|awk '{print $1}'`" != "drwxr-x---" ]; then
<     echo "! $i has wrong mode, should be 750"
<     echo "...try: chmod 750 $i"
---
>   elif [ "`ls -ld $i|awk '{print $1}'`" != "drwxr-xr-x" ]; then
>     echo "! $i has wrong mode, should be 755"
>     echo "...try: chmod 755 $i"
313c302
<   echo "Congratulations, your Qmailrocks.org Qmail installation looks good!"
---
>   echo "Congratulations, your LWQ installation looks good!"

Summary of differences between QMR and LWQ's installation check scripts in plain words:

  • QMR's script has CHECKPOP and CHECKSEND enabled as “y”. Whereas LWQ's script uses CHECKPOP=n .
  • QMR sets concurrencyincoming as 30, whereas LWQ sets it as 20.
  • QMR checks LOGDIRS="/var/log/qmail /var/log/qmail/qmail-smtpd", whereas LWQ checks LOGDIRS="/var/log/qmail /var/log/qmail/smtpd" .
  • QMR additionally checks for LOGDIRS="$LOGDIRS /var/log/qmail/qmail-pop3d" .
  • QMR also checks for LOGDIRS="$LOGDIRS /var/log/qmail/qmail-send" if CHECKSEND=y
  • QMR wants permissions of log directories as “750”, whereas LWQ expects them to be “755”. Not an issue.


LWQ: The readproctitle program keeps a log of error messages generated by services managed by svscan. To see these messages, use ps or some other process listing command. For example, you might see something like:

# ps -efl | grep "service errors" | grep -v grep
000 S root      1006  1001  0  76   0    -   334 pipe_w Mar31 ?        00:00:00
readproctitle service errors: ...unable to start qmail-smtpd/run: exec format error
#

In this case, the problem is that there is an error in the first line of the /service/qmail-smtpd/run script--most likely caused by the file being is DOS format (CR-LF line endings instead of Unix's LF-only). It sometimes helps to run a service manually in order to find configuration problems. For example, if your qmail-smtpd/log service isn't running, do:

cd /service/qmail-smtpd/log
svc -d .
./run
if no errors, enter a line of text and press ENTER
if still no errors, enter CTRL-D (end of file)

At this point, you should be able to identify the problem and fix it. Once that's done, return to the service's directory, if necessary, and do:

svc -u .

If there are no problems, your readproctitle will show you dots only, instead of errors:

[root@qmail downloads]# ps -efl | grep "service errors" | grep -v grep
0 S root      2001  1963  0  84   0 -   378 pipe_w 12:11 ?        00:00:00 readproctitle service errors: ................................................................................................................................................................................................................................................................................................................................................................................................................

Once the services are all up with >1 second uptime, follow the instructions in TEST.deliver and TEST.receive to verify that they're working correctly. Note that using these instructions, logging will be accomplished by multilog to /var/log/qmail, not splogger to something like /var/log/maillog.

Note: If you chose maildir mailbox format as the default delivery method, you will need to create a Maildir directory in your home directory and alias's home directory before trying these instructions. See the maildir section to see how to properly create this directory.

If I am to follow these instructions in TEST.deliver and TEST.receive files, I need to have some OS accounts to send mail back and forth. Also I need to have a special directory named Maildir in home directories of those users. This is because vpopmail and mysql are not yet installed. So all testing will be done through OS users.

useradd kamran
useradd feysal

echo 'redhat' | passwd --stdin kamran
echo 'redhat'| passwd --stdin feysal

mkdir /home/kamran/Maildir
mkdir /home/feysal/Maildir
chown kamran:kamran /home/kamran/* -R
chown kamran:kamran /home/feysal/* -R

Try the test:

[root@qmail qmail-1.03]# echo to: kamran | /var/qmail/bin/qmail-inject

Check the log:-

# tail -F  /var/log/qmail/qmail-send/current
@400000004a8e95f405201c64 new msg 65096
@400000004a8e95f4052471c4 info msg 65096: bytes 217 from <root@qmail.example.com> qp 3059 uid 0
@400000004a8e95f4052bf78c starting delivery 1: msg 65096 to local kamran@qmail.example.com
@400000004a8e95f4053970c4 status: local 1/10 remote 0/20
@400000004a8e95f40be3154c delivery 1: deferral: Temporary_error_on_maildir_delivery._(#4.3.0)/
@400000004a8e95f40be36f24 status: local 0/10 remote 0/20

A note from LWQ , explains the possible reason: Note: qmail-local can deliver mail to maildir mailboxes, but it can't create them. Maildir mailboxes should be created with the maildirmake program that comes with qmail. E.g., "maildirmake ~/Maildir". Be sure to run maildirmake as the owner of the maildir, not as root. Your useradd or adduser command might support a "skeleton" directory, e.g. /etc/skel, where you can create a maildir that will be copied for all new users.

A maildir mailbox is a directory containing three subdirectories, new, cur, and tmp. Each message in a maildir mailbox is in a separate file in one of the subdirectories, depending upon its status: new is for unread messages, cur is for messages that have been seen, and tmp is for messages in the process of being delivered.


So I deleted the old directories and created new ones using the following commands:

[root@qmail qmail-1.03]# rm -fr /home/kamran/Maildir
[root@qmail qmail-1.03]# rm -fr /home/feysal/Maildir

[root@qmail qmail-1.03]# su -c "/var/qmail/bin/maildirmake ~/Maildir" kamran
[root@qmail qmail-1.03]# su -c "/var/qmail/bin/maildirmake ~/Maildir" feysal

The following shows that this command has created the Maildir in the user's home directory with desired permssions, as well as directories cur, new and tmp in the ~/Maildir .

[root@qmail qmail-1.03]# ls -l /home/kamran/
total 4
drwx------ 5 kamran kamran 4096 Aug 21 16:29 Maildir


[root@qmail qmail-1.03]# ls -l /home/kamran/Maildir/
total 12
drwx------ 2 kamran kamran 4096 Aug 21 16:29 cur
drwx------ 2 kamran kamran 4096 Aug 21 16:29 new
drwx------ 2 kamran kamran 4096 Aug 21 16:29 tmp
[root@qmail qmail-1.03]#

Try the mail test again:

[root@qmail qmail-1.03]# echo to: kamran | /var/qmail/bin/qmail-inject

This time, it succeeded:

[root@qmail qmail-1.03]# tail -F /var/log/qmail/qmail-send/current
@400000004a8ea2321cf0b6dc new msg 65097
@400000004a8ea2321cf206cc info msg 65097: bytes 217 from <root@qmail.example.com> qp 3155 uid 0
@400000004a8ea2321cf3f2fc starting delivery 7: msg 65097 to local kamran@qmail.example.com
@400000004a8ea2321cfa05ac status: local 1/10 remote 0/20
@400000004a8ea2321dc3d1d4 delivery 7: success: did_1+0+0/
@400000004a8ea2321dc698c4 status: local 0/10 remote 0/20
@400000004a8ea2321dd1a0fc end msg 65097

If you check inside user kamran's Maildir/new directory, you will find a file:

[root@qmail qmail-1.03]# ls ~kamran/Maildir/new/ -lh
total 4.0K
-rw------- 1 kamran kamran 294 Aug 21 16:33 1250861608.3158.qmail.example.com
[root@qmail qmail-1.03]#

This mail file, has the following contents:

[root@qmail qmail-1.03]# cat ~kamran/Maildir/new/1250861608.3158.qmail.example.com
Return-Path: <root@qmail.example.com>
Delivered-To: kamran@qmail.example.com
Received: (qmail 3155 invoked by uid 0); 21 Aug 2009 16:33:28 +0300
Date: 21 Aug 2009 16:33:28 +0300
Message-ID: <20090821133328.3154.qmail@qmail.example.com>
From: root@qmail.example.com
to: kamran@qmail.example.com
[root@qmail qmail-1.03]#

So this seems to be working properly. I can try from another machine, using smtpd protocol and send another mail to the same user. Here is how:

I log on to another machine and try sending the mail:

[kamran@kworkbee ~]$ telnet qmail.example.com 25
Trying 192.168.122.90...
Connected to qmail.example.com.
Escape character is '^]'.
220 qmail.example.com NO UCE ESMTP
ehlo kworkbee.homedomain.com
250-qmail.example.com NO UCE
250-SIZE 0
250-PIPELINING
250 8BITMIME
mail from: kamranazeem@homedomain.com
250 ok
rcpt to: kamran@example.com
553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)
rcpt to: kamran@qmail.example.com
250 ok
data
354 go ahead
Subject: test message
This is a test over SMTP from another machine.
.
250 ok 1250862005 qp 3166
quit
221 qmail.example.com NO UCE
Connection closed by foreign host.
[kamran@kworkbee ~]$

I have the following in my qmail-send log file:

@400000004a8ea3bf06373d6c new msg 65097
@400000004a8ea3bf0637935c info msg 65097: bytes 379 from <kamranazeem@homedomain.com> qp 3166 uid 702
@400000004a8ea3bf0649a844 starting delivery 8: msg 65097 to local kamran@qmail.example.com
@400000004a8ea3bf0649c784 status: local 1/10 remote 0/20
@400000004a8ea3bf071368b4 delivery 8: success: did_1+0+0/
@400000004a8ea3bf07164afc status: local 0/10 remote 0/20
@400000004a8ea3bf071bc16c end msg 65097
@400000004a8ea40502fa17b4 starting delivery 9: msg 65096 to local kamran@qmail.example.com
@400000004a8ea4050309dec4 status: local 1/10 remote 0/20
@400000004a8ea40504f5860c delivery 9: success: did_1+0+0/
@400000004a8ea40504f5d814 status: local 0/10 remote 0/20
@400000004a8ea40504f61e64 end msg 65096

And I should have a new file in the Maildir/new of user kamran:

[root@qmail qmail-1.03]# ls ~kamran/Maildir/new/ -lh
total 12K
-rw------- 1 kamran kamran 294 Aug 21 16:33 1250861608.3158.qmail.example.com
-rw------- 1 kamran kamran 460 Aug 21 16:40 1250862005.3171.qmail.example.com

[root@qmail qmail-1.03]# cat ~kamran/Maildir/new/1250862005.3171.qmail.example.com
Return-Path: <kamranazeem@homedomain.com>
Delivered-To: kamran@qmail.example.com
Received: (qmail 3166 invoked from network); 21 Aug 2009 16:39:48 +0300
Received: from unknown (HELO kworkbee.homedomain.com) (192.168.122.1)
  by qmail.example.com with SMTP; 21 Aug 2009 16:39:48 +0300
Received-SPF: none (qmail.example.com: domain at homedomain.com does not designate permitted sender hosts)
Subject: test message
This is a test over SMTP from another machine.
[root@qmail qmail-1.03]#

Great! So this seems to be working. There are a lot of tests explained in the TEST.deliver file in the Qmail source directory, which you can (should) perform , before moving on.

Todo:

“Make cert” ???

JMS Queue analyzer : http://qmail.jms1.net/scripts/qlanalyze

Personal tools