Home / Alt manpages / trivial-rewrite(8postfix)

  • trivial-rewrite(8postfix)
  • Postfix admin command
  • linux

Trace Postfix Address Rewriting and Routing with trivial-rewrite

You will finish with a reliable way to inspect the Postfix daemon that rewrites addresses and resolves them to a delivery route. The key result is a clear boundary: trivial-rewrite is a master-managed service, while postconf is the practical interface for checking the settings that control it.

These examples use Postfix 3.8.6, installed here as package version 3.8.6-1ubuntu0.1. Allow about fifteen minutes. You need a shell and access to the Postfix configuration. Reading values is normally unprivileged; changing main.cf and reloading Postfix usually requires elevated privileges.

Scope: this guide inspects and makes one deliberately small routing change. It does not send mail, edit lookup tables, or replace a production route without a rollback value.

1. Check the daemon's role

Do not start by running trivial-rewrite as if it were a command-line address converter. Its synopsis accepts generic Postfix daemon options, but the daemon speaks an internal client protocol and is normally started by master. Its three request types are rewrite, resolve and verify.

rewrite standardises an address in a local or remote context. resolve turns a sender and address into a transport, next hop, recipient and flags. verify resolves an address for address verification. These are service operations, not a stable interactive interface.

Confirm how this host has the service registered:

$ postconf -M rewrite/unix
rewrite    unix  -       -       y       -       -       trivial-rewrite

The exact spacing can vary. The useful facts are the unix service type and trivial-rewrite server name. Check the installed version as a checkpoint:

$ postconf mail_version
mail_version = 3.8.6

If the service is absent or has been deliberately customised, stop here and inspect master.cf before assuming the standard process layout.

2. Record the active rewriting defaults

Use postconf -h when you want values without parameter names. This read-only command does not need sudo on a normally readable configuration:

$ postconf -h myhostname myorigin append_at_myorigin append_dot_mydomain
server.example.com
/etc/mailname
yes
no

These values explain a common surprise. Locally submitted addresses without a domain receive @$myorigin when append_at_myorigin is enabled. On Postfix 3.8, the displayed append_dot_mydomain default is no; older Postfix releases used a different compatibility default. Do not infer the value from a blog post: check this host.

Record the other rewrite switches before interpreting an address:

$ postconf -h allow_percent_hack swap_bangpath remote_header_rewrite_domain
yes
yes

user%domain can therefore become user@domain, and site!user can become user@site. The remote rewrite context uses remote_header_rewrite_domain for incomplete addresses. An empty value means remote message headers are not rewritten at all, which prevents a poorly formed remote header from automatically acquiring the local domain.

Checkpoint

Save the output or write down the values that matter to the incident. A later postfix reload can make a changed setting active, so the previous value is your recovery reference.

3. Inspect the route controls

Address rewriting is only part of the result. Routing controls choose the delivery agent and next hop after Postfix classifies the destination. Inspect them together:

$ postconf -h local_transport virtual_transport relay_transport default_transport relayhost transport_maps
local:$myhostname
virtual
relay
smtp

On this host, local final delivery uses local:$myhostname, virtual mailbox delivery uses virtual, relay domains use relay, and otherwise the default transport is smtp. An empty relayhost means there is no global next-hop override. An empty transport_maps means no optional address-to-transport lookup is configured.

Classification order matters. Postfix considers destinations matching mydestination, local or proxy interfaces, virtual alias and mailbox domains, and relay domains before falling back to default_transport. A transport map or relay host can then alter the route. If a message goes somewhere unexpected, inspect those inputs rather than blaming address rewriting alone.

For a concise configuration snapshot, use:

$ postconf -n | grep -E '^(myhostname|myorigin|mydestination|virtual_|relay_|default_transport|relayhost|transport_maps|recipient_delimiter|append_|allow_percent_hack|swap_bangpath) ='

No output from grep is not proof that a parameter is unset: postconf -n reports only non-default settings. Query a specific parameter with postconf -h parameter when the default matters.

4. Change one route only when you have a rollback

Warning

Changing relayhost, a transport map, or a delivery transport can redirect mail, break delivery, or disclose messages to an unintended server. Do this in a maintenance window with an approved next hop. Do not paste credentials into main.cf or this shell history.

For a controlled example, first record the current value, then set a placeholder relay host only if that host is real and authorised in your environment:

$ OLD_RELAYHOST=$(postconf -h relayhost)
$ printf 'old relayhost: [%s]\n' "$OLD_RELAYHOST"
$ sudo postconf -e 'relayhost = [smtp.example.net]:587'
$ postconf -h relayhost
[smtp.example.net]:587

The brackets make the destination a literal host name rather than a domain looked up through MX records. Port 587 is only an example; it does not configure authentication or TLS by itself.

Undo the example by restoring the recorded value. If it was empty, remove the override with an empty assignment:

$ sudo postconf -e 'relayhost ='
$ postconf -h relayhost

Do not reload until the value is correct. postconf -e edits the Postfix configuration; it does not make every running daemon reread it immediately.

5. Reload and verify the running service

After reviewing the diff in main.cf, ask Postfix to pick up the change:

$ sudo postfix check
$ sudo postfix reload
postfix/postfix-script: refreshing the Postfix mail system

The diagnostic text varies by package and logging setup. A successful command exit status is the first checkpoint. Then verify the stored setting and check that the master-managed service is present:

$ postconf -h relayhost
[smtp.example.net]:587
$ pgrep -a -f '[/]postfix/sbin/master|trivial-rewrite'
3211957 /usr/lib/postfix/sbin/master -w
3909688 trivial-rewrite -n rewrite -t unix -u -c

Process IDs and command-line detail vary. The important check is that Postfix has a master process and can start the rewrite service. Logs for transactions and failures go through the configured system logging path, using syslogd or postlogd as described by the manpage.

6. Separate rewrite failures from delivery failures

Use this short decision path when an address behaves unexpectedly:

  1. Check the rewrite context. Local submission can append myorigin; remote header rewriting can intentionally use a different domain or remain disabled.
  2. Check compatibility controls such as resolve_numeric_domain, resolve_null_domain and allow_min_user. Their defaults are restrictive on this installation.
  3. Check domain classification, transport_maps, relayhost and the transport parameters.
  4. Check the Postfix log for the actual transport and next hop selected.

Address verification uses its own override parameters, including address_verify_relayhost and the address verification transport settings. A probe can therefore follow a different route from ordinary delivery. Treat that as an intentional boundary when investigating verification results.

Done means

  • You treated it as a daemon, not a tool: trivial-rewrite is master-managed, not an interactive converter.
  • You checked the baseline: the installed Postfix version and the active rewrite defaults.
  • You inspected routing first: classification and route controls, before changing a next hop.
  • You recorded a rollback value before any configuration edit.
  • You reloaded deliberately: ran postfix check, reloaded, and verified the resulting value.
  • You can tell the failures apart: address rewriting, route selection and delivery-agent problems.