Andrew Mercer
on this page

Postfix is not one program — it's a collection of small, single-purpose daemons supervised by a master process, communicating with each other over local sockets, each doing one part of the mail-handling pipeline. Understanding this internal shape makes the rest of Postfix's configuration (and every log line it produces) much easier to reason about.

The daemon pipeline

A rough sketch of what happens to a message after smtpd accepts it:

        (network)                (network)
            │                        │
     ┌──────▼──────┐          ┌──────▼──────┐
     │   smtpd     │          │   smtp      │  ← outbound delivery
     │ (receives)  │          │ (sends)     │
     └──────┬──────┘          └──────▲──────┘
            │                        │
     ┌──────▼──────┐          ┌──────┴──────┐
     │  cleanup    │          │    qmgr     │  ← queue manager,
     │ (header/    │───────►  │  decides    │     decides routing
     │  body checks│          │  what goes  │
     └─────────────┘          │  where next │
                              └──────┬──────┘
                                     │
                        ┌────────────┼────────────┐
                        ▼            ▼             ▼
                     local(8)    virtual(8)     pipe(8)/other
                  (system users) (virtual mbox) (autoreply, etc.)
  • smtpd — listens on the network, speaks the SMTP protocol to incoming connections, applies smtpd_*_restrictions policy, and hands accepted mail to cleanup.
  • cleanup — normalizes and rewrites the message, applies header_checks/body_checks/mime_header_checks, and enqueues it.
  • qmgr (the queue manager) — the central scheduler. Decides which delivery agent handles a queued message and when to retry deferred ones.
  • smtp — the outbound delivery agent; connects to remote MTAs (or a relayhost) to hand mail onward.
  • local — delivers to real Unix system mailboxes.
  • virtual — delivers to virtual mailboxes (non-system users), per virtual_mailbox_* settings.
  • pipe — hands a message off to an external program (used for autoresponders, mailing list software, etc. — see the administration doc).

All of this is orchestrated by a single always-running master process, configured via master.cf, which starts the other daemons on demand and enforces process limits.

The queue directories

Every message physically exists as a file under /var/spool/postfix/ at some point, moving between subdirectories as its status changes:

Directory Meaning
maildrop Newly submitted local mail (e.g. from the sendmail/mail command), before pickup processes it
incoming Freshly received, not yet fully queued
active Currently being processed for delivery by qmgr
deferred Delivery failed temporarily; waiting to retry
hold Held indefinitely (via postsuper -h) — won't be delivered until released
corrupt Malformed queue files Postfix couldn't parse

postqueue -p (or the older mailq) lists everything sitting in the queue; postsuper manages queue contents directly (delete, hold, release, requeue) — see the administration doc for concrete examples.

The two configuration files

  • main.cf — the vast majority of Postfix configuration: hostnames, domains, network trust, restrictions, lookup tables, TLS settings. Almost everything referenced elsewhere in this guide lives here.
  • master.cf — defines which daemons run, on which sockets/ports, and with what per-service overrides. You'll typically only touch this to add a custom service (like the autoreply pipe service in the administration doc) or to enable/disable a listener (e.g. adding a submission listener on port 587).

Lookup tables: the pattern behind hash:, mysql:, proxy:

An enormous number of Postfix settings — virtual_alias_maps, alias_maps, smtp_sasl_password_maps, virtual_mailbox_maps, etc. — take a lookup table reference rather than a literal value, in the form type:path:

  • hash:/path/to/file — a flat text file of key value pairs, compiled into a fast on-disk hash database with postmap (for most maps) or postalias (specifically for /etc/aliases). You must re-run the appropriate command every time you edit the source file, or Postfix keeps using the stale compiled .db — this is the single most common "why isn't my change taking effect" mistake, and shows up repeatedly across the personal notes distilled into this guide as the database ... is older than source file warning.
  • btree:/path — similar to hash:, a different on-disk format with different performance characteristics; interchangeable in most configs.
  • mysql:/path/to/query.cf (or pgsql:, ldap:) — instead of a static file, the lookup is a live query against a database, defined in a small .cf file specifying the connection and SQL query template. This is the mechanism behind the MySQL-backed virtual mailbox setup (see the virtual domains doc) — it's how one Postfix instance can serve mailboxes/domains for many tenants without a config-file edit + postmap for every change.
  • proxy:mysql:/path — the same MySQL query, but routed through Postfix's proxymap service, which pools/caches database connections so that every smtpd process doesn't open its own direct MySQL connection.

Core identity settings (the ones everything else builds on)

Setting Meaning
myhostname This machine's fully-qualified hostname, as announced in EHLO/HELO and used to build Received: headers
mydomain The domain part, usually derived from myhostname
myorigin The domain appended to unqualified local addresses when mail originates here (e.g. what turns root into [email protected])
mydestination Domains this host delivers locally (to system/Unix accounts)
mynetworks IP ranges treated as "trusted" — allowed to relay through this server without authentication
inet_interfaces Which network interfaces Postfix listens on (all, loopback-only, a specific address, etc.)
relay_domains Domains this host will relay mail for (as opposed to deliver locally) — distinct from mydestination

Every other document in this Postfix guide is really just different combinations and extensions of these fundamentals for a specific goal: relaying outbound (relayhost doc), hosting many domains (virtual domains doc), encrypting sessions (TLS doc), and so on.