Mail server setup with Qmail

16 11 2008

What is Qmail?

Qmail is an Internet Mail Transfer Agent (MTA) for UNIX-like operating systems. It’s a drop-in replacement for the Sendmail system provided with UNIX operating systems. Qmail uses the Simple Mail Transfer Protocol (SMTP) to exchange messages with MTA’s on other systems.

Why Qmail?

Your operating system might already have an MTA, probably Postfix or Sendmail, so if you’re reading this document you’re probably looking for something different. Some of the advantages of Qmail over vendor-provided MTA’s include:

  • Security – Qmail was designed for high security. Sendmail has a long history of serious security problems. When Sendmail was written, the internet was a much friendlier place. Everyone knew everyone else, and there was little need to design and code for high security. Today’s Internet is a much more hostile environment for network servers. Sendmail’s author, Eric Allman, and the current maintainer, Claus Assman, have done a good job of tightening up the program, but nothing short of a redesign can achieve “true” security.
  • Performance – Qmail parallelizes mail delivery, performing up to 20 deliveries simultaneously, by default.
  • Reliability – Once Qmail accepts a message, it guarantees that it won’t be lost. Qmail also supports a new mailbox format that works reliably even over NFS without locking.
  • Simplicity – Qmail is smaller than any other equivalently-featured MTA.

The Qmail web page, has a comprehensive list of Qmail’s features.

Comparison with other MTA’s

A book could be written about this topic, but it would be tedious reading. Here’s a quick comparison of Qmail with some of the most common UNIX MTA’s.

MTA Maturity Security Features Performance Sendmailish Modular
Qmail medium high high high addons yes
Sendmail high low high low x no
Postfix medium high high high yes yes
Exim medium low high medium yes no
Courier low medium high medium optional yes

NOTE: Sendmailish means the MTA behaves like Sendmail in some ways that would make a switch from Sendmail to the alternative MTA more user-transparent, such as the use of .forward files, /etc/aliases, and delivery to /var/spool/mail.

Preparation

Before 2007-11-30, Qmail’s restrictive licensing regarding the distribution of pre-built packages meant that it was usually installed from a source code distribution. This may change in the future, especially if daemontools and ucspi-tcp are placed in the public domain. For now, though, source code is still the preferred distribution method for Qmail.

Before installing Qmail on a system, especially if this is your first Qmail installation, there are a few things you need to think about.

  • If possible, install Qmail on a staging environment. This will give you a chance to make mistakes without losing important mail or interrupting mail service to your users.
  • If you don’t have a spare, and your system is already handling mail using sendmail, smail, or some other MTA, you can install and test most pieces of Qmail without interfering with the existing service.
  • When migrating a system from some other MTA to Qmail–even if you’ve got some Qmail experience under your belt–it’s a good idea to formulate a plan.

Note: The Qmail bin directory must reside on a file-system that allows the use of executable and setuid() files. Some OS distributions automatically mount /var with the nosuid or noexec options enabled. On such systems, either these options should be disabled or /var/qmail/bin should reside on another filesystem without these options enabled.

Download the soure

OK, so you’ve got a system meeting the requirements ready for installing Qmail. The first step is to download the source code for Qmail and any other add-ons. You’ll need qmail, of course, and you should probably also get ucspi-tcp and daemontools:

Note: If any of the links fail, it’s probably because the package has been updated. In that case, you should go to http://cr.yp.to/software.html and follow the links to download the current version. It’s possible that upgraded versions aren’t compatible with the following instructions, so be sure to read the release notes in the “Upgrading from previous versions…” sections.

Unpack the distribution

To continue from this point onwards, you need a working C compiler and the tarballs. Next, copy or move the tarballs to the directory you want to do the work in. /usr/local/src is a good choice for qmail and ucspi-tcp. daemontools should be built under /package.

At this time you probably want to become root, if you’re not already.

    su
    umask 022
    mkdir -p /usr/local/src
    mv netqmail-1.06.tar.gz ucspi-tcp-0.88.tar.gz /usr/local/src
    mkdir -p /package
    mv daemontools-0.76.tar.gz /package
    chmod 1755 /package

Now you can unpack the packages.

    cd /usr/local/src
    gunzip netqmail-1.06.tar.gz
    tar xpf netqmail-1.06.tar
    gunzip ucspi-tcp-0.88.tar.gz
    tar xpf ucspi-tcp-0.88.tar
    rm *.tar      # optional, unless space is very tight
    cd /package
    gunzip daemontools-0.76.tar.gz
    tar xpf daemontools-0.76.tar
    rm *.tar      # optional, again

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

Create Directories

Since Qmail’s installation program creates the subdirectories as they’re needed, you only need to create the Qmail “home” directory:

    mkdir /var/qmail

And on to the next section.

Create users and groups

The easiest way to create the necessary users and groups is to create a little script file to do it for you. In the source directory you’ll find a file called INSTALL.ids. It contains the command lines for many platforms, so copying the file to another name and editing that is quick and easy.

    cd /usr/local/src/netqmail-1.06
    cp INSTALL.ids IDS

Then, using your favorite editor, remove all of the file except the lines you want. For example, here’s what IDS would look like for Linux after editing:

    groupadd nofiles
    useradd qmaild -g nofiles -d /var/qmail -s /usr/sbin/nologin
    useradd alias -g nofiles -d /var/qmail/alias -s /usr/sbin/nologin
    useradd qmaill -g nofiles -d /var/qmail -s /usr/sbin/nologin
    useradd qmailp -g nofiles -d /var/qmail -s /usr/sbin/nologin
    groupadd qmail
    useradd qmailq -g qmail -d /var/qmail -s /usr/sbin/nologin
    useradd qmailr -g qmail -d /var/qmail -s /usr/sbin/nologin
    useradd qmails -g qmail -d /var/qmail -s /usr/sbin/nologin

Then to run it, either use chmod to make it executable or run it with sh:

    chmod 700 IDS
    ./IDS

Let’s build Qmail

Now you can start building Qmail. Change to the /usr/local/src/netqmail-1.05/netqmail-1.05 directory and let’s get started:

    cd /usr/local/src/netqmail-1.06

Now type the following:

    make setup check

After the build is complete, you’ll need to do your post installation configuration. A couple of scripts are provided to make this job a lot easier.

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 foobar, your config-fast line would look like this:

    ./config-fast foobar.example.com

Install ucspi-tcp

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

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.

Install daemontools

Change to the daemontools build directory:

    cd /package/admin/daemontools-0.76

Then do:

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

Start Qmail

The /var/qmail/boot directory contains example qmail boot scripts for different configurations: /var/spool/mail vs. $HOME/Mailbox, using procmail or dot-forward, and various combinations of these. Feel free to examine these, but for our installation, we’ll use the following script:

/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: This script uses backquotes (`), not single quotes ('). For best results, copy and paste the scripts in this guide instead of retyping them.

Use your editor to create the above /var/qmail/rc, then execute these commands:

    chmod 755 /var/qmail/rc
    mkdir /var/log/qmail

At this point you need to decide the default delivery mode for messages that aren’t delivered by a .qmail file. The following table outlines some common choices.

Mailbox format Name Location defaultdelivery Comments
mbox Mailbox $HOME ./Mailbox most common, works with most MUA’s
maildir Maildir $HOME ./Maildir/ more reliable, less MUA support
mbox username /var/spool/mail See INSTALL.vsm traditional UNIX mailbox

To select your default mailbox type, just enter the defaultdelivery value from the table into /var/qmail/control/defaultdelivery. E.g., to select the standard Qmail Mailbox delivery, do:

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

System startup files

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:

#!/bin/sh

# description: the qmail MTA

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

Create the script using your editor.

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

The supervise scripts

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:

#!/bin/sh
exec /var/qmail/rc

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

#!/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:

#!/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 5000000 \
    /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: 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.

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:

#!/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 /service directory is created when daemontools is installed.

NOTE: The Qmail system will start automatically shortly after these links are created. If you don’t want it running yet, do:

    qmailctl stop

SMTP access controll

Allow the local host to inject mail via SMTP:

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

Verify that nothing is listening to the SMTP port (25). Culprits could be the old MTA, inetd, or xinetd. The following command should produce no output (unless the qmail-smtpd service is running):

    netstat -a | grep smtp

If something is running, make sure it’s not Qmail by doing:

    qmailctl stop

The repeat the netstat check:

    netstat -a | grep smtp

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

Start Qmail

If you stopped qmail above after creating the links in /service, you should restart it now:

    qmailctl start

Test the installation

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://www.filedropper.com/qmailinstcheck . 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 Qmail installation looks good!

Configuration

All of Qmail’s system configuration files, (with the extension .qmail) files in ~alias, reside in /var/qmail/control. The qmail-control man page contains a table like the following:

Control Default Used by Purpose
badmailfrom none qmail-smtpd blacklisted From addresses
bouncefrom MAILER-DAEMON qmail-send username of bounce sender
bouncehost me qmail-send hostname of bounce sender
concurrencyincoming none /service/qmail-smtpd/run max simultaneous incoming SMTP connections
concurrencylocal 10 qmail-send max simultaneous local deliveries
concurrencyremote 20 qmail-send max simultaneous remote deliveries
defaultdelivery none /var/qmail/rc default .qmail file
defaultdomain me qmail-inject default domain name
defaulthost me qmail-inject default host name
databytes 0 qmail-smtpd max number of bytes in message (0=no limit)
doublebouncehost me qmail-send host name of double bounce sender
doublebounceto postmaster qmail-send user to receive double bounces
envnoathost me qmail-send default domain for addresses without “@”
helohost me qmail-remote host name used in SMTP HELO command
idhost me qmail-inject host name for Message-ID’s
localiphost me qmail-smtpd name substituted for local IP address
locals me qmail-send domains that we deliver locally
me FQDN of system various default for many control files
morercpthosts none qmail-smtpd secondary rcpthosts database
percenthack none qmail-send domains that can use “%”-style relaying
plusdomain me qmail-inject domain substituted for trailing “+”
qmqpservers none qmail-qmqpc IP addresses of QMQP servers
queuelifetime 604800 qmail-send seconds a message can remain in queue
rcpthosts none qmail-smtpd domains that we accept mail for
smtpgreeting me qmail-smtpd SMTP greeting message
smtproutes none qmail-remote artificial SMTP routes
timeoutconnect 60 qmail-remote how long, in seconds, to wait for SMTP connection
timeoutremote 1200 qmail-remote how long, in seconds, to wait for remote server
timeoutsmtpd 1200 qmail-smtpd how long, in seconds, to wait for SMTP client
virtualdomains none qmail-send virtual domains and users

For more information about a particular control file, see the man page for the module listed under “Used by”.

I think you have successfully setup up your Qmail SMTP server. I’m hoping to meet you again with another couple of HOWTOs on “Qmail configuration – smarthosts, multiple domains, relaying, etc.” and “Running a POP server with Qmail”

Cheers!


Actions

Information

5 responses

19 11 2008
rain7246

Buying domain names is a very common activity on the internet and a necessity for establishing an identity on the web. However, many people still don’t understand what a domain is, how it is used and how to properly maintain it.

19 11 2008
saguide

Thanks for the comment. The idea of ’saguide’ is to build a collection of tutorials and articles for systems administrators. So I’m not trying to cover the basic stuff like installations, definitions, etc, because I believe a sys-admin should have that prior knowledge.

24 04 2009
Biswajit Das

I am not Understand please me Details. If you give me all details then I am gratefull to you. On My email ID.

24 04 2009
Biswajit Das

Please Give me all Details. Pert by Part i am new to linux. If possible Please give details at my Email ID. Thank you

5 05 2009
saguide

I guess you are trying to setup a QMail server. Am I correct? What is the Linux distribution you are using? Perhaps that would help me to guide you through out the process.

Leave a comment