Postfix Lookup Table Overview


Overview

This document covers the following topics:

The Postfix lookup table model

Postfix uses lookup tables to store and look up information for access control, address rewriting and even for content filtering. All Postfix lookup tables are specified as "type:table", where "type" is one of the database types described under "Postfix lookup table types" at the end of this document, and where "table" is the lookup table name. The Postfix documentation uses the terms "database" and "lookup table" for the same thing.

Examples of lookup tables that appear often in the Postfix documentation:

/etc/postfix/main.cf:
    alias_maps = hash:/etc/postfix/aliases            (local aliasing)
    header_checks = regexp:/etc/postfix/header_checks (content filtering)
    transport_maps = hash:/etc/postfix/transport      (routing table)
    virtual_alias_maps = hash:/etc/postfix/virtual    (address rewriting)

All Postfix lookup tables store information as (key, value) pairs. This interface may seem simplistic at first, but it turns out to be very powerful. The (key, value) query interface completely hides the complexities of LDAP or SQL from Postfix. This is a good example of connecting complex systems with simple interfaces.

Benefits of the Postfix (key, value) query interface:

Postfix lists versus tables

Most Postfix lookup tables are used to look up information. Examples are address rewriting (the lookup string is the old address, and the result is the new address) or access control (the lookup string is the client, sender or recipient, and the result is an action such as "reject").

With some tables, however, Postfix needs to know only if the lookup key exists. The lookup result itself is not used. Examples are the local_recipient_maps that determine what local recipients Postfix accepts in mail from the network, the mydestination parameter that specifies what domains Postfix delivers locally, or the mynetworks parameter that specifies the IP addresses of trusted clients or client networks. Technically, these are lists, not tables. Despite the difference, Postfix lists are described here because they use the same underlying infrastructure as Postfix lookup tables.

Preparing Postfix for LDAP or SQL lookups

LDAP and SQL are complex systems. Trying to set up both Postfix and LDAP or SQL at the same time is definitely not a good idea. You can save yourself a lot of time by implementing Postfix first with local files such as Berkeley DB. Local files have few surprises, and are easy to debug with the postmap(1) command:

% postmap -q [email protected] hash:/etc/postfix/virtual 

Once you have local files working properly you can follow the instructions in ldap_table(5), mysql_table(5), pgsql_table(5) or sqlite_table(5) and replace local file lookups with LDAP or SQL lookups. When you do this, you should use the postmap(1) command again, to verify that database lookups still produce the exact same results as local file lookup:

% postmap -q [email protected] ldap:/etc/postfix/virtual.cf 

Be sure to exercise all the partial address or parent domain queries that are documented under "table search order" in the relevant manual page: access(5), canonical(5), virtual(5), transport(5), or under the relevant configuration parameter: mynetworks, relay_domains, parent_domain_matches_subdomains.

Maintaining Postfix lookup table files

When you make changes to a database while the mail system is running, it would be desirable if Postfix avoids reading information while that information is being changed. It would also be nice if you can change a database without having to execute "postfix reload", in order to force Postfix to use the new information. Each time you do "postfix reload" Postfix loses a lot of performance.

Updating Berkeley DB files safely

Although Postfix uses file locking to avoid access conflicts while updating Berkeley DB or other local database files, you still have a problem when the update fails because the disk is full or because something else happens. This is because commands such as postmap(1) or postalias(1) overwrite existing files. If the update fails in the middle then you have no usable database, and Postfix will stop working. This is not an issue with the CDB database type available with Postfix 2.2 and later: CDB creates a new file, and renames the file upon successful completion.

With multi-file databases such as DBM, there is no simple solution. With Berkeley DB and other "one file" databases, it is possible to add some extra robustness by using "mv" to REPLACE an existing database file instead of overwriting it:

# postmap access.in && mv access.in.db access.db

This converts the input file "access.in" into the output file "access.in.db", and replaces the file "access.db" only when the postmap(1) command was successful. Of course typing such commands becomes boring quickly, and this is why people use "make" instead, as shown below. User input is shown in bold font.

# cat Makefile
all: aliases.db access.db virtual.db ...etcetera...

# Note 1: commands are specified after a TAB character.
# Note 2: use postalias(1) for local aliases, postmap(1) for the rest.
aliases.db: aliases.in
	postalias aliases.in
	mv aliases.in.db aliases.db

access.db: access.in
	postmap access.in
	mv access.in.db access.db

virtual.db: virtual.in
	postmap virtual.in
	mv virtual.in.db virtual.db

...etcetera...
# vi access.in
...editing session not shown...
# make
postmap access.in
mv access.in.db access.db
#

The "make" command updates only the files that have changed. In case of error, the "make" command will stop and will not invoke the "mv" command, so that Postfix will keep using the existing database file as if nothing happened.

Postfix lookup table types

To find out what database types your Postfix system supports, use the "postconf -m" command. Here is a list of database types that are often supported:

btree
A sorted, balanced tree structure. This is available only on systems with support for Berkeley DB databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "btree:table" is the database file name without the ".db" suffix.
cdb
A read-optimized structure with no support for incremental updates. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "cdb:table" is the database file name without the ".cdb" suffix. This feature is available with Postfix 2.2 and later.
cidr
A table that associates values with Classless Inter-Domain Routing (CIDR) patterns. The table format is described in cidr_table(5).
dbm
An indexed file type based on hashing. This is available only on systems with support for DBM databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "dbm:table" is the database file name without the ".dir" or ".pag" suffix.
environ
The UNIX process environment array. The lookup key is the variable name. The lookup table name in "environ:table" is ignored.
hash
An indexed file type based on hashing. This is available only on systems with support for Berkeley DB databases. Database files are created with the postmap(1) or postalias(1) command. The database name as used in "hash:table" is the database file name without the ".db" suffix.
internal
A non-shared, in-memory hash table. Its content are lost when a process terminates.
ldap (read-only)
Perform lookups using the LDAP protocol. Configuration details are given in the ldap_table(5).
memcache (read-write)
Perform memcache database lookups or updates. Configuration details are given in memcache_table(5).
mysql (read-only)
Perform MySQL database lookups. Configuration details are given in mysql_table(5).
netinfo (read-only)
Perform Netinfo database lookups.
nis (read-only)
Perform NIS database lookups.
nisplus (read-only)
Perform NIS+ database lookups. Configuration details are given in nisplus_table(5).
pcre (read-only)
A lookup table based on Perl Compatible Regular Expressions. The file format is described in pcre_table(5). The lookup table name as used in "pcre:table" is the name of the regular expression file.
pgsql (read-only)
Perform PostgreSQL database lookups. Configuration details are given in pgsql_table(5).
proxy (read-only)
Access information via the Postfix proxymap(8) service. The lookup table name syntax is "proxy:type:table".
regexp (read-only)
A lookup table based on regular expressions. The file format is described in regexp_table(5). The lookup table name as used in "regexp:table" is the name of the regular expression file.
sdbm
An indexed file type based on hashing. This is available only on systems with support for SDBM databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "sdbm:table" is the database file name without the ".dir" or ".pag" suffix.
sqlite (read-only)
Perform SQLite database lookups. Configuration details are given in sqlite_table(5).
static (read-only)
Always returns its lookup table name as lookup result. For example, the lookup table "static:foobar" always returns the string "foobar" as lookup result.
tcp
Access information through a TCP/IP server. The protocol is described in tcp_table(5). The lookup table name is "tcp:host:port" where "host" specifies a symbolic hostname or a numeric IP address, and "port" specifies a symbolic service name or a numeric port number.
texthash (read-only)
This produces similar results as hash: files, except that you don't have to run the postmap(1) command before you can use the file, and that texthash: does not detect changes after the file is read. The lookup table name is "texthash:filename", where the file name is taken literally; no suffix is appended.
unix (read-only)
A limited way to query the UNIX authentication database. The following tables are implemented:
unix:passwd.byname
The table is the UNIX password database. The key is a login name. The result is a password file entry in passwd(5) format.
unix:group.byname
The table is the UNIX group database. The key is a group name. The result is a group file entry in group(5) format.

Other lookup table types may be available depending on how Postfix was built. With some Postfix distributions the list is dynamically extensible as support for lookup tables is dynamically linked into Postfix.