Wednesday, November 13, 2013

How to install qmail from srouce

For people who is serious about qmail.....

qmail is an Internet MTA for Unix and Unix-like operating systems. It is a drop-in replacement for Sendmail which means the uers of a system will not even notice a switch from Sendmail to qmail. It is secure, reliable and efficient compare to other MTAs such as sendmail, postfix, ..etc.

This guide shows how to install qmail on a CentOS 6.x box. Because of qmail's restrictive licensing regarding the distribution of prebuilt packages, qmail is usually installed from a source-code distribution. Also, configuring and installing from source code will also give you a greater understanding of how qmail works.

This content of this blog is mainly borrowed from "life with qmail", but with platform specialization.

Mailbox:
Choosing a Mailbox format and location is one of the most important decisions you will make during the installation. You have 4 choices:
  1. mbox mailboxes under /var/spool/mail or some other central spool directory
  2. mbox mailboxes under the user's home directory
  3. maildir mailboxes under the user's home directory
  4. maildir mailboxes in a central spool directory (not commonly used)
Choose mbox if you are migrating a system using mboxes to qmail, so that you don't need to convert existing mailboxes. But if you choose mbox, all messages are stored in a single file, it requires careful locking to prevent simutanelous updating. maildir mailbox format specifically to address the weaknesses of the mbox format. A maildir contains 3 sub-directories:
  • tmp - messages in the process of being delivered
  • new - messages that have been delivered but not yet seen by the recipient
  • cur - messages that have been seen by the recipient
If you choose Maildir, Be sure to create Maildir mailboxes in advance or deliveries will be deferred. qmail will not automatically create Maildirs at the time of delivery. Empty Maildirs can be created using the maildirmake (/var/qmail/bin/maildirmake) command, which must be run as the owner of the mailbox, not root. Also, create a .qmail file in ~/ with "./Maildir/" content for emails deliver to local user.

File location:
By default, everything will be installed under /var/qmail. It is better to keep it that way, but if you really want to make qmail conform to some preferred directory structure, you can still put the master directory in /var/qmail but relocate the subdirectories using symbolic links.

System requirement:
  • 10 megabytes of free space in the build area
  • <10 megabytes for the binaries, documentation, and configuration files
  • Sufficient disk space for the queue on an appropriate local file system
  • Unix/Linux OS
  • Access to a DNS resolver
  • Adequate network connectivity
  • A complete development environment including a C compiler, linker, header files, make or gmake, libraries, and so on
  • The gunzip utility from the gzip package

Installation:

Verify your environment:
# cc
cc: no input files

If you have sendmail and postfix
# rpm -qa | grep sendmail
# rpm -qa | grep postfix
# yum remove sendmail
# yum remove postfix

Get tarballs from http://cr.yp.to/
You need at least qmail, ucspi-tcp and daemontools.

Move the tarballs to standard src dir:
# mv qmail-1.03.tar.gz /usr/local/src
# mv ucspi-tcp-0.88.tar.gz /usr/local/src
# mv daemontools-0.76.tar.gz /usr/local/src

Unpack the tarballs:
# cd /usr/local/src
# tar -xzvf qmail-1.03.tar.gz
# tar -xzvf ucspi-tcp-0.88.tar.gz
# tar -xzvf daemontools-0.76.tar.gz

Create master dir:
# cd qmail-1.03/
# mkdir /var/qmail

Create users and groups:
# groupadd nofiles
# useradd -g nofiles -d /var/qmail/alias alias -s /nonexistent
# useradd -g nofiles -d /var/qmail qmaild -s /nonexistent
# useradd -g nofiles -d /var/qmail qmaill -s /nonexistent
# useradd -g nofiles -d /var/qmail qmailp -s /nonexistent
# groupadd qmail
# useradd -g qmail -d /var/qmail qmailq -s /nonexistent
# useradd -g qmail -d /var/qmail qmailr -s /nonexistent
# useradd -g qmail -d /var/qmail qmails -s /nonexistent

Install qmail:
# make setup check

If you are getting errors like "/usr/bin/ld: errno: TLS definition in /lib64/libc.so.6 section .tbss mismatches non-TLS reference in substdio.a(substdo.o)", do the following:
# echo gcc -O2 -include /usr/include/errno.h > conf-cc
# echo cc -m64 -O2 -include /usr/include/errno.h >> conf-cc
# echo cc -m64 >conf-ld

if your system is not x86_64, use -m32 instead

After the build is complete, you need to create the basic configuration files under /var/qmail/control
# ./config

If config can't find your host name in DNS not /etc/hosts you can instead run the config-fast script:
# ./config-fast the.full.hostname

You can run this config command later to update control/me, control/defaultdomain and control/plusdomain files in /var/qmail

Install ucspi-tcp:
# cd ../ucspi-tcp-0.88/

if you modified conf-cc and conf-ld for qmail, you will need to do it again:
# echo gcc -O2 -include /usr/include/errno.h > conf-cc
# echo cc -m64 -O2 -include /usr/include/errno.h >> conf-cc
# echo cc -m64 >conf-ld
# make
# make setup check

It is installed under /usr/local/bin

Install daemontool:
# cd daemontools-0.76

again, update conf-cc and conf-ld
# echo gcc -O2 -include /usr/include/errno.h > conf-cc
# echo cc -m64 -O2 -include /usr/include/errno.h >> conf-cc
# echo cc -m64 >conf-ld
# ./package/install

Now create the /service directory:
# mkdir /service

Set up svscan to run on the /service directory each time the system is booted.
# vi /etc/inittab
change
SV:123456:respawn:/command/svscanboot
to
SV:123456:respawn:/command/svscanboot </dev/null >/var/log/svscan 2>&1

then tell init to reread /etc/inittab
# kill -HUP 1

Create the following /var/qmail/rc:
# vi /var/qmail/rc
add
#!/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'"

# chmod 755 /var/qmail/rc


At this point you need to decide the default delivery mode for messages that aren't delivered by a .qmail file. I use Maildir
# echo ./Maildir/ > /var/qmail/control/defaultdelivery


Create system start-up files:
The qmailctl script:
# vi /var/qmail/bin/qmailctl
Get the script from:
http://lifewithqmail.org/qmailctl-script-dt70

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

Now create the supervise directories for the qmail services:
# mkdir -p /var/qmail/supervise/qmail-send/log
# mkdir -p /var/qmail/supervise/qmail-smtpd/log

Create the /var/qmail/supervise/qmail-send/run file:
# vi /var/qmail/supervise/qmail-send/run
add
#!/bin/sh
exec /var/qmail/rc

Create the /var/qmail/supervise/qmail-send/log/run file:
# vi /var/qmail/supervise/qmail-send/log/run
add
#!/bin/sh
exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail

Create the /var/qmail/supervise/qmail-smtpd/run file:
# vi /var/qmail/supervise/qmail-smtpd/run
add
#!/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


Note: In my case, I had to set the softlimit to 8000000, otherwise I will be getting error in /var/log/qmail/smtpd/current:

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

and in "ps -ef | grep tcpserver" result, you will see
[tcpserver] <defunct>

Create the concurrencyincoming control file:

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

Create the /var/qmail/supervise/qmail-smtpd/log/run file:
# vi /var/qmail/supervise/qmail-smtpd/log/run
#!/bin/sh
exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail/smtpd

Make the run files executable:

# 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:
# mkdir -p /var/log/qmail/smtpd
# chown qmaill /var/log/qmail /var/log/qmail/smtpd

Finally, link the supervise directories into /service:
# ln -s /var/qmail/supervise/qmail-send /var/qmail/supervise/qmail-smtpd /service

The qmail system will start automatically shortly after these links are created.

Set up SMTP access control:

Allow the local host to inject mail via SMTP:
# echo '127.:allow,RELAYCLIENT=""' >> /etc/tcp.smtp
# qmailctl cdb

Replace any existing /usr/lib/sendmail with the qmail version:
# ln -s /var/qmail/bin/sendmail /usr/lib
# ln -s /var/qmail/bin/sendmail /usr/sbin

Create aliases for root, postmaster, and mailer-daemon
# echo \&tony@xxx.com > /var/qmail/alias/.qmail-root
# echo \&tony@xxx.com > /var/qmail/alias/.qmail-postmaster
# echo \&tony@xxx.com > /var/qmail/alias/.qmail-mailer-daemon
# chmod 644 /var/qmail/alias/.qmail-root /var/qmail/alias/.qmail-postmaster  /var/qmail/alias/.qmail-mailer-daemon

Start or restart qmail:
# qmailctl restart

Test the Installation:
# qmailctl stat
/service/qmail-send: up (pid 8861) 37 seconds
/service/qmail-send/log: up (pid 8866) 37 seconds
/service/qmail-smtpd: up (pid 9052) 1 seconds
/service/qmail-smtpd/log: up (pid 8865) 37 seconds
messages in queue: 0
messages in queue but not yet preprocessed: 0

# echo to: tony@xxx.com | /var/qmail/bin/qmail-inject

You should see something in /var/log/qmail/current:
@4000000052829c1236cfa39c new msg 661831
@4000000052829c1236d01cb4 info msg 661831: bytes 231 from <lxu@nxdomain.opendns.com> qp 12332 uid 500
@4000000052829c130042f694 starting delivery 17: msg 661831 to remote tony@xxxx.com
@4000000052829c13004319bc status: local 0/10 remote 1/20
@4000000052829c132f738f64 delivery 17: success: 74.12a.14a.26_accepted_message./Remote_host_said:_250_2.0.0_OK_1384291337_ds9si19749996obc.138_-_gsmtp/
@4000000052829c132f756424 status: local 0/10 remote 0/20
@4000000052829c132f760834 end msg 661831

Also check your mailbox, you should see an empty email (might find it in your spam folder).

No comments: