Book Image

Qmail Quickstarter: Install, Set Up and Run your own Email Server

Book Image

Qmail Quickstarter: Install, Set Up and Run your own Email Server

Overview of this book

This book starts with setting up a qmail server and takes you through virtualization, filtering, and other advanced features like hosting multiple domains, mailing lists, and SSL Encryption. Finally, it discusses the log files and how to make qmail work faster. Qmail is a secure, reliable, efficient, simple message transfer agent. It is designed for typical Internet-connected UNIX hosts. Qmail is the second most common SMTP server on the Internet, and has by far the fastest growth of any SMTP server. Qmail's straight-paper-path philosophy guarantees that a message, once accepted into the system, will never be lost. Qmail also optionally supports maildir, a new, super-reliable user mailbox format.
Table of Contents (13 chapters)

The Minimum Qmail System


Qmail comes with a set of minimal install instructions, in a file named INSTALL. It contains eighteen relatively basic steps for compiling qmail on most systems and for getting it running. These are somewhat simple, but can be trimmed even further if you're not trying to replace an existing mail server.

Compiling and Installing

Compiling qmail is generally very easy. Before compiling qmail, first obtain the prerequisites:

  • A Unix-style operating system (such as Linux, BSD, Solaris, etc.)

  • A working C compiler (preferably executable using cc, as that requires less configuration before compiling) and the standard C development system

  • A case-sensitive filesystem

Having a case-sensitive filesystem is important because during installation, qmail uses several files that are different only in the capitalization of their name. For example, INSTALL is a text file describing basic installation procedures, while install is a script for putting files in the correct places with the correct permissions. The qmail distribution can be modified to work around that problem, but that is a little outside the purview of this book.

With those prerequisites, installing a bare-bones version of qmail is a straightforward five-step process as follows:

  1. 1. Prepare the system: add one directory (/var/qmail), seven users (qmaild, qmaill, qmailp, qmailq, qmailr, qmails, and alias), and two groups (qmail and nofiles).

  2. 2. Run make setup install to compile and install all the necessary binaries.

  3. 3. Run the config (or config-fast) script to create the basic configuration files.

  4. 4. Create the necessary, minimum account aliases.

  5. 5. Tell qmail where to deliver mail by default.

Simple, isn't it? Let's go into a bit more detail here.

Preparing the System

On most UNIX systems it should be relatively easy to add users and groups, using tools like useradd, adduser, mkuser, or something similar. For example, on many Linux distributions, the commands for preparing the system are as follows:

mkdir /var/qmail
groupadd nofiles
useradd -d /var/qmail/alias -s /bin/false -g nofiles alias
useradd -d /var/qmail -s /bin/false -g nofiles qmaild
useradd -d /var/qmail -s /bin/false -g nofiles qmaill
useradd -d /var/qmail -s /bin/false -g nofiles qmailp
groupadd qmail
useradd -d /var/qmail -s /bin/false -g qmail qmailq
useradd -d /var/qmail -s /bin/false -g qmail qmailr
useradd -d /var/qmail -s /bin/false -g qmail qmails

The users are required as part of qmail's security setup; almost every major portion of qmail runs as a different user. The reason for this is simple—it allows qmail to use standard UNIX user protections to enforce separation between its components, which communicate via tightly-controlled interfaces (namely, pipes and environment variables). This user separation is the backbone of qmail's security model—a model that has done exceedingly well and has been adopted by other security-conscious programs (e.g. OpenSSH). To complete the protection that these users provide, it's a good idea to ensure that each of these users cannot be used by anyone to log into the system. On most modern systems, this is achieved by not giving the user a working shell (e.g. /bin/false).

Compiling and Installing the Necessary Binaries

The second step is the compilation step. Generally, this is the simplest of the steps, provided that the necessary tools (a compiler and the make utility) are available. Qmail will compile on most systems without further configuration, by simply executing the command make setup check. The exceptions are modern Linux systems that use a more recent version of glibc than version 2.3.1. On these systems, it is necessary to edit the conf-cc file that comes with qmail before compiling, so that it looks like the following:

gcc -include /usr/include/errno.h

If your compiler cannot be run using the cc command, edit the conf-cc file to contain the correct command to compile files.

Creating the Basic Configuration Files

The third step simply adds the most minimal configuration information that qmail requires for functioning—the Fully Qualified Domain Name (FQDN) of the host computer. The term "fully-qualified" means that the FQDN not only contains the host name, but also the full domain name. For example, to set up a computer named mail as part of example.com's computer network, the FQDN would be mail.example.com. To configure qmail for this computer, the minimal configuration command would then be:

./config-fast mail.example.com

The alternative command, ./config, does the same thing that ./config-fast does, however, it obtains the FQDN by looking up the computer's IP address in DNS. If the system is already set to go with the IP address it will always have, this is a convenient way to avoid extra typing. However, if the system's network configuration is not in its final state, using ./config will probably produce an incorrect set of configuration files. Running either command overwrites any existing configuration files.

Creating the Necessary Minimum Account Aliases

The fourth step adds the accounts that are required by the various email standards documents (in particular, RFC 822). The following accounts are required:

The last one, [email protected], needn't necessarily exist. However, qmail does not deliver mail to the real root user, and the address is commonly assumed to refer to the administrator of the machine (for example, by scripts and monitoring programs) when the administrator needs to be notified of something. Thus, creating an alias for root is generally a good idea.

Aliases are defined by creating files in the home directory of the alias user. If the alias user has been created according to the above instructions, that directory is /var/qmail/alias. The general way of referring to this directory is ~alias/. The alias-defining files in this directory must have very specific names, all beginning with .qmail and ending with the name of the alias. For example, the postmaster alias is established by creating a file named .qmail-postmaster in the directory ~alias/. The mailer-daemon alias is established by creating a file named .qmail-mailer-daemon, and so forth. Capitalization for account names is always converted to lowercase for delivery, so don't use capital letters in .qmail filenames.

The content of these files specifies exactly what should happen to email that is sent to one of these aliases. In general, the syntax is identical to the generic dot-qmail (.qmail) file syntax, which is discussed later in this book, but the exception is the bare minimum: an empty file. If an alias is established with an empty file, it will be delivered as specified by the default delivery mechanism (for more details refer to the Default Mail Delivery section).

The simplest option is to put an account name in those files, which tells qmail to forward all mail sent to these aliases to the account specified. For example, if all email addressed to [email protected] should be delivered to an account named steve, put steve into the ~alias/.qmail-root file.

It is important to note that these files should have very specific permissions—they should be readable by any user, but only writable by the root user. This may not be the default when these files are created. To set the permissions to what they need to be, run a command that looks something like the following:

chown root ~alias/.qmail-root
chmod 644 ~alias/.qmail-root

Default Mail Delivery

The fifth and final step is to tell qmail how to deliver mail by default. Default means how qmail delivers all mail unless told to do something else by a .qmail file. Generally, this is done by selecting a startup script from the /var/qmail/boot directory and copying it to the file /var/qmail/rc.

In the /var/qmail/boot directory, there are several files, each of which can start up qmail with a different default delivery method. The ones that come with qmail are:

  • home: Delivers email to the file Mailbox in the user's home directory.

  • home+df: Supports Sendmail-style .forward files, and otherwise is the same as home.

  • proc: Hands the email to procmail for delivery.

  • proc+df: Supports Sendmail-style .forward files, and otherwise is the same as proc.

  • binm1: Hands the email to BSD 4.4's binmail program (mail.local) for delivery.

  • binm1+df: Supports Sendmail-style .forward files, and otherwise is the same as binm1.

  • binm2: Hands the email to SVR4's binmail program (/bin/mail -r) for delivery.

  • binm2+df: Supports Sendmail-style .forward files, and otherwise is the same as binm2.

  • binm3: Hands the email to the V7 binmail program (/bin/mail -f) for delivery.

  • binm3+df: Supports Sendmail-style .forward files, and otherwise is the same as binm3.

Unless you are migrating from an older mail server and have a reason to want the compatibility features, the file to use is either home or proc. The simplest is home.

Basic Configuration

Once all five steps are completed, a working, bare-bones installation of qmail is ready in /var/qmail. However, in many situations, a barebones installation is insufficient.

The basic questions to answer when configuring an email server on a new system include:

  • What should be done with mail when it is received?

  • Which mail should be accepted?

The most common and simplest answers to the first question generally fall into one of the following two categories: either mail should be relayed to a smarter mail server or the mail should be delivered locally.

The second question can often become far more complicated due to spam and viruses and the like, but the most basic answer is generally a list of domain names for which this email server is responsible.

As you can tell already, various answers to these questions can result in wildly different behaviors. For example, if no mail should be accepted from the network, no mail should be delivered locally, and all mail should be forwarded to a specific mail server, then this is considered mini-qmail. In such a situation, many of the more complex features of qmail can be eliminated. In different circumstances, the qmail server may need to accept any and all email and forward it to a central mail server (for example, a mail proxy or a caching forwarder). Or it may need to accept email for a specific domain and deliver it to system-defined users (the standard setup). Or it may need to accept email for a set of domains and deliver it locally via some virtual-domain configuration. There could be any number of additional complications, twists, and turns.

The most basic answers to these questions are specified to qmail via configuration files. Which mail should be accepted is generally specified by files in the /var/qmail/control directory, and what to do with mail that has been accepted is generally specified in a combination of files in the control directory and the rc file (which was set up in Default Mail Delivery section of the installation procedure). Note though, that the rc file is a shell script. Much of qmail configuration is in the form of scripts controlling how qmail and its related binaries are run.

The most basic, most important control files for qmail are: me, rcpthosts, locals, smtproutes, and defaultdomain. The files are not necessarily created by default or by the ./config scripts; but they control qmail's most important functionality. They control, respectively, the name of the server, which domains' mail to accept, which domains are to be considered local once mail addressed to them is accepted for delivery, where to send outbound mail, and which domain to append to bare

usernames to transform them into real email addresses. The defaultdomain and me files are simple one-line files. In the case of me, this line is considered the name of the server. In the case of defaultdomain, this line is considered the name to append (for example, example.com) to a bare username (for example, user) to construct a valid email address (for example, [email protected]) when necessary. The rcpthosts and locals files are simply lists of domains, one domain per line in the file. The most complex of the four, smtproutes, is also rather simple. Each line of the file consists of three fields separated by colons. The first field is the domain that needs to be routed this way and the second field is the domain name or IP address (in square brackets) of the server to which matching email must be sent. The third field is the port on the server to connect to, which if not present, defaults to port 25. For example:

somewhere.com:[1.2.3.4]

This line in the file informs qmail that any email sent to an address ending in @somewhere.com must be forwarded to the IP address 1.2.3.4. The files smtproutes, rcpthosts, and locals can all use prefix-wildcards. A prefix-wildcard is a line that begins with a period, followed by the suffix that must match following the period. For example:

.somewhere.com:mail.isp.com

This line in the smtproutes file will match email addresses ending in @here.somewhere.com, @there.somewhere.com, @anywhere.somewhere.com, and so forth, where there is an arbitrary string and a period preceding somewhere.com. Note that it doesn't match the bare @somewhere.com. Emails addressed to matching domains are forwarded to mail.isp.com.

Finally there is the special case, where there is nothing to the left of the first colon as shown in the following example:

:mail.isp.com:1000

This line in the smtproutes file will send all email to the mail.isp.com server listening on port 1000. In the smtproutes file, the first match is the one that is used, and this line will match anything. As such, it's usually at the end of the file.

There are many more files that qmail looks for in the /var/qmail/control directory. Explanations of how they work and what they do can be found in the qmail man pages, however, they are generally for more involved configuration tasks and non-basic qmail installations.

Default delivery instructions are part of simple execution.

Simple Execution

There are two primary architectural segments of qmail involved in setting up a standard SMTP email server. The first is the set of programs that work together to perform mail deliveries, either locally or remotely, and the second is the set of programs that work together to accept messages via the SMTP protocol.

qmail-start

The programs that work together to perform mail deliveries are: qmail-send, qmail-lspawn, qmail-rspawn, and qmail-clean, as well as any program that they spawn to complete their tasks (like qmail-remote, qmail-local, procmail, etc.). Most of these have corresponding users. In particular, qmail-send and qmail-clean operate as the qmails user, and qmail-rspawn (and qmail-remote) operate as qmailr. The qmail-lspawn program runs as root, because it must be able to deliver mail to each user as that user. In any case, all of these programs are spawned by the command qmail-start. This command takes two optional arguments—a default delivery command and a logging command. To understand exactly how this works, take a look at the most basic of the scripts in the /var/qmail/boot directory, home:

#!/bin/sh
# Using splogger to send the log through syslog.
# Using qmail-local to deliver messages to ~/Mailbox by default.
exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start ./Mailbox splogger qmail

The first part of this script is fairly straightforward: using the env command to remove all environment variables before executing qmail-start, it then sets the PATH environment variable to make sure that the qmail bin directory is the first place searched for qmail's binaries. The second part, executing qmail-start with arguments, requires a little more explanation.

When qmail makes an email delivery, every delivery is made from the perspective of a program running as the receiving user, in the receiving user's home directory. Delivery instructions are treated as if they came from a dot-qmail file, with one delivery instruction per line. From that point onwards, file names are treated as mbox-formated mailboxes, directory names (indicated by ending a file name with a forward-slash (/)) are treated as Maildir-formatted mailboxes, and commands (indicated by starting the line with a pipe symbol (|)) are all located and executed from within the addressed user's home directory. Thus, using a relative file name, such as ./Mailbox, specifies a file named Mailbox within the current directory at the time of delivery i.e. the addressed user's home directory.

In this case, the default delivery method is very simple, deliver mail to an mbox-formatted file named Mailbox in the user's home directory. However, the argument specifying the default delivery method can be more complex. Take, for example, the home+df file in /var/qmail/boot:

#!/bin/sh
# Using splogger to send the log through syslog.
# Using dot-forward to support sendmail-style ~/.forward files.
# Using qmail-local to deliver messages to ~/Mailbox by default.
exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start '|dot-forward .forward
./Mailbox' splogger qmail

Note that because of the rules of shell-script quoting, the first argument to qmail-start in this case is the full text between the single quotes, or:

|dot-forward .forward
./Mailbox

Note that the single argument is, in fact, two lines. Just as if these lines were in the user's .qmail file, this causes the dot-forward command to run first, and if it returns with a code that indicates that the mail has been delivered via instructions in a .forward file, the delivery is considered complete. On the other hand, if it returns with a code that indicates that the user did not have a .forward file in his or her home directory, qmail will instead deliver mail to the Mailbox file, just as it would have if the home file's delivery instructions were used.

The text after the mail-delivery specification causes qmail-send to send all logging information to the program specified. In this case, the splogger program will be run with the argument qmail. The splogger program takes the output from qmail-send, prefixes it with "qmail", and logs it via the standard syslog mechanism. If neither the splogger command nor any other command is provided as an argument to qmail-send, qmail-send will send its logging information to standard output (or rather, file descriptor one).

To run this program by hand, simply run your chosen rc file, as follows:

/bin/sh /var/qmail/rc &

The ampersand at the end ensures that the program executes in the background.

qmail-smtpd

The set of programs that provide SMTP service—receiving SMTP connections (and thus, email) from the network—is organized around qmail-smtpd. Rather than including basic networking features in the qmail SMTP daemon executable, qmail-smtpd, qmail pushes that responsibility to a helper program such as tcpserver, inetd, xinetd, or tcpsvd, among others. This design decision makes for many useful opportunities. For example, the qmail SMTP service can be tested from the command-line without needing extra software by simply running /var/qmail/bin/qmail-smtpd. (Note that the DATA phase of the SMTP conversation requires CRLFs rather than simply LFs. The correct line endings can be generated by pressing Ctrl V and then pressing Enter twice.)

Getting qmail-smtpd to listen to the network requires extra software. Many systems come with either inetd or xinetd and they can be configured to run qmail-smtpd very easily. For example, an inetd.conf entry for qmail-smtpd might look like this (all one line):

smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env tcp-env
/var/qmail/bin/qmail-smtpd

The current best practice for running qmail-smtpd is to use the tcpserver program, also written by the author of qmail, Dr. Bernstein, which is distributed as part of the ucspi-tcp package (http://cr.yp.to/ucspi-tcp.html). It can be used as follows:

tcpserver -u `id -u qmaild` -g `id -g qmaild` \
0 smtp /var/qmail/bin/qmail-smtpd &

This command can be run manually, added to your system's startup commands, or executed using Bernstein's daemontools (http://cr.yp.to/daemontools.html) package. If added to your system's startup commands, the ampersand (&) is critical. The arguments to tcpserver are straightforward—first, the user and group IDs, then 0 to specify that it will listen to all network interfaces, then smtp to specify that it will use the SMTP port (25), and finally, the command to be run when a connection is made to that network port.

Standard qmail-smtpd does not take any run-time arguments; however, its behavior can be modified at run time by using environment variables. In particular, qmail-smtpd pays attention to the following environment variables:

Environment Variable

Description

TCPLOCALHOST

The DNS hostname corresponding to the local interface in the connection.

TCPLOCALIP

The local IP address in the connection.

TCPLOCALPORT

The local port number (usually 25 when used with qmail-smtpd).

TCPREMOTEHOST

The DNS hostname of the remote system.

TCPREMOTEINFO

The username responsible for the connection (usually determined using the ident protocol).

TCPREMOTEIP

The IP address of the remote system.

TCPREMOTEPORT

The port number used by the remote system.

DATABYTES

The maximum number of bytes allowed in a message.

RELAYCLIENT

The existence of this variable (even if it contains an empty string) allows the sender to relay any email message. The content of this variable is appended to each recipient address.

Most of these variables (the ones that begin with TCP) are set by the program that handles the network operations. The tcpserver and tcpsvd programs set these variables. For programs that do not set these variables (for example, inetd and xinetd), tcp-env will set them. The environment variable you will most commonly need to set yourself is RELAYCLIENT. If this variable is present in the environment, qmail-smtpd accepts any mail for delivery even if the destination addresses are not in the control/rcpthosts file. For example, an ISP that relays email from all of its customers generally adds the RELAYCLIENT variable to qmail-smtpd's environment, if the connecting client is in its network.

While tcpserver, tcpsvd, and tcp-env will set specific environment variables, any other variable (such as RELAYCLIENT) will generally need to be set using a more generic method. Environment variables can be set in many ways, like using the standard env utility, the shell's export/setenv features, and tcprules files.