Home / Alt manpages / postfix-add-policy(8)

  • postfix-add-policy(8)
  • Admin command
  • linux

Add a Postfix Policy Service with postfix-add-policy

postfix-add-policy bolts a spawn-based policy service onto Postfix without you hand-editing master.cf line by line. You will add one named SMTP policy service to /etc/postfix/master.cf, then verify and reload the configuration. Allow about 15 minutes, plus time to test the policy server itself. This guide describes the installed Ubuntu package, Postfix 3.8.6-1ubuntu0.1, and its postfix-add-policy implementation. It changes a live configuration file, so schedule the reload and keep an administrator session available.

  • You need: root privileges, a policy-server program already installed, a dedicated account that can run it, and a working Postfix installation.
  • The helper only adds a spawn service entry. It does not install postgrey or another policy server, connect the service to an SMTP restriction, or prove the server speaks the policy protocol.

1. Check the helper and its actual argument boundary

First confirm the package and executable without changing Postfix:

$ command -v postfix-add-policy
/usr/sbin/postfix-add-policy
$ dpkg-query -W -f='${Package} ${Version}\n' postfix
postfix 3.8.6-1ubuntu0.1
$ postfix-add-policy
To add a new policy service to your master.cf:
    % sudo postfix-policy-add {policy service name} {user} {file (full path)}

The no-argument call prints usage and leaves the configuration alone. The manual synopsis shows policy name, username and argv values, but this installed script accepts exactly three arguments after the command. A fourth argument makes it print the usage text instead of making a change. Pass the policy program and its complete argument string as the third argument, quoted as one shell word.

Checkpoint

Do not continue until command -v finds the expected executable and the package version is recorded. Do not use MAIL_CONFIG to select a test directory: the installed helper is hard-coded to /etc/postfix, despite the manpage documenting that environment variable.

2. Choose a service name, account and program

Pick a short service name that is not already present in master.cf. Use a real, least-privileged account and an absolute path to the policy server. Replace every placeholder in this example:

$ POLICY_NAME='policy-check'
$ POLICY_USER='postfix'
$ POLICY_PROGRAM='/usr/local/sbin/my-policy-server'
$ sudo test -x "$POLICY_PROGRAM" && echo executable
executable
$ sudo grep -nF -- "$POLICY_NAME" /etc/postfix/master.cf || echo name-free
name-free
  • Use the account the server package documents. Do not use an account that can modify unrelated mail or system data merely because it is convenient.
  • Check the program's own documentation for required arguments and configuration files.
  • Name collisions are substring matches. The helper tests a service name by substring matching, so choose a name that does not appear inside an unrelated existing line.

Checkpoint

The executable check must pass, the service name must be absent, and you must know what the policy server will do when Postfix starts it. If the program is not installed, stop here: adding a dead service entry only creates a later mail-flow failure.

3. Back up master.cf before the change

The helper creates a timestamped copy before replacing /etc/postfix/master.cf. Make a separate, clearly named backup as well so you can identify the known-good file without guessing which timestamp belongs to this change:

$ sudo cp --preserve=all /etc/postfix/master.cf \
    "/etc/postfix/master.cf.before-policy-$(date +%Y%m%d%H%M%S)"
$ sudo ls -l /etc/postfix/master.cf /etc/postfix/master.cf.before-policy-*

The command above writes a new backup and does not alter the active file. The $(date ...) part is evaluated by your shell, so the resulting name contains the backup time. If you work from a change-management system, record that exact file name there.

Warning

Do not edit master.cf in place while the helper is running, and do not delete either backup until the service has been tested. A replacement of the active file is reversible, but losing the only known-good copy makes recovery harder.

4. Add the policy service

Run the helper with elevated privileges. The third argument is one shell word, even if the policy server needs additional arguments of its own:

$ sudo postfix-add-policy "$POLICY_NAME" "$POLICY_USER" "$POLICY_PROGRAM"

On success the helper normally prints nothing. It appends a header and an entry with this shape:

policy-check unix    -       n       n       -       0     spawn
      user=postfix argv=/usr/local/sbin/my-policy-server

Your service name, account and command will differ. The generated entry uses Postfix's spawn service, does not chroot the child, and sets the maximum process count field to zero as shown by the helper. The command is not enabled for any SMTP stage by this operation.

  • Name already used: the helper reports that and leaves the file unchanged.
  • Usage printed instead: check the argument count.
  • Permission or file error: do not keep retrying blindly; inspect the file and the backup first.

Checkpoint

Verify the exact generated lines before reloading:

$ sudo grep -nA1 -B2 -- "$POLICY_NAME" /etc/postfix/master.cf
... # the surrounding lines are host-specific
policy-check unix    -       n       n       -       0     spawn
      user=postfix argv=/usr/local/sbin/my-policy-server

5. Validate and reload Postfix

Ask Postfix to parse its configuration before asking it to start using the new service:

$ sudo postfix check
$ sudo postconf -M "$POLICY_NAME"
policy-check unix - n n - 0 spawn
$ sudo grep -nF -- "user=$POLICY_USER" /etc/postfix/master.cf
... # the matching generated line is shown

The postconf output is a parsed view, so it is useful for catching a malformed entry. Exact whitespace may vary, but the service name, type, flags and spawn command should match your intended values. If either command fails, stop and restore the backup rather than reloading a configuration you have not understood.

Warning

Reloading affects a live mail service. Existing connections normally continue, but new service lookups use the reloaded configuration. Reload only after checking the policy program and its permissions:

$ sudo postfix reload
postfix/postfix-script: refreshing the Postfix mail system
$ sudo postconf -h myhostname
mail.example.org

The reload message and hostname are examples of normal output, not a promise about every package build. A reload does not test an SMTP policy decision. Use the policy server's own logs and a controlled mail test, following that server's documentation.

6. Recover if the service is wrong

If you have not reloaded, restore the active file from the backup and inspect the difference:

$ sudo diff -u "/etc/postfix/master.cf.before-policy-TIMESTAMP" /etc/postfix/master.cf
$ sudo cp --preserve=all "/etc/postfix/master.cf.before-policy-TIMESTAMP" /etc/postfix/master.cf
$ sudo postfix check
$ sudo postfix reload

Replace TIMESTAMP with the exact backup suffix. The helper also leaves a timestamped copy such as /etc/postfix/master.cf.1760000000; select it only after checking its contents and modification time. Do not remove a working backup as part of an automated rollback.

If the service has already been reloaded and mail is failing, restore the last known-good file, run postfix check, reload, and then inspect the policy server and Postfix logs. You can remove the helper's generated line manually, but restoring a verified, complete file is less likely to leave a partial edit behind.

Done means

  • Known: the installed Postfix version and hard-coded configuration path.
  • Verified: the policy program exists, is executable, and has a suitable service account.
  • Recorded: a separate pre-change backup of master.cf.
  • Checked: the generated spawn entry has the intended name, user and command.
  • Parsed clean: postfix check, postconf -M and postconf -P agree on the service.
  • Reloaded only after review, with a tested rollback path still available.