Getting started

Default configuration

This role provides a hopefully reasonable Postfix configuration for a SMTP server on the public Internet. It does not configure Postfix directly; instead, the configuration variables are passed to the debops.postfix Ansible role which combines them with the other configuration specified by other Ansible roles and generates the final Postfix configuration files. You should check the debops.postfix documentation for explanation of how the configuration is structured and what are the supported parameters.

Postfix "capabilities"

To allow easier management of different configuration options, they are enabled conditionally by "capabilities", a list of keywords either autogenerated by the role conditionally, or set by the user in the Ansible inventory. The list is inclusive; if you want to disable a particular autogenerated feature, you can override the postconf__autodetect_capabilities variable through Ansible inventory.

Supported Postfix capabilities and their effects:

auth

Autodetected. Enabled, if role finds out Ansible local facts defined by the debops.dovecot or debops.saslauthd Ansible roles, which indicates that the SASL Auth facilities are available on the host.

This capability will enable SMTP authentication support via either Dovecot or Cyrus SASL library, preferred in that order. The submission and smtps Postfix services will be enabled, with corresponding firewall configuration that allows access from any host, by default.

authcleanup

When enabled, the submission and smtps Postfix services will check the headers of incoming mail messages and apply filtering rules specified by the /etc/postfix/auth_header_checks.pcre lookup table. This can be used to sanitize authenticated mail messages before they are sent to the external SMTP servers.

deprecated

When enabled, the role will configure Postfix features and services that are considered as deprecated.

overhead

Enabled by default. Add a custom header to every message that passes through this system.

public-mx-required

Autodetected. Enabled if a host has a public IPv4 or IPv6 address, with assumption that the host will receive mail messages from public Internet servers.

This capability will enable sender checks which will verify that a given sender domain MX host has a public IP address. Otherwise, mail messages directed to this MX won't be deliverable, therefore it's better to reject the messages early.

unauth-sender

Autodetected. Enabled by default when auth capability is enabled.

With this capability, Postfix will check the sender e-mail addresses against a list of its own domains. If any messages are sent from these domains unauthenticated, they will be rejected.

With auhenticated mail, Postfix will check the sender address against the mail user database defined in the smtpd_sender_login_maps lookup tables. If the sender address does not belong to the authenticated user, mail will be rejected. This requires configuration of an user database, for example using the debops.postldap role.

Example inventory

To apply the Postfix configuration provided by the debops.postconf role on a host, it needs to be present in the [debops_service_postconf] Ansible inventory group. You also need to enable debops.postfix support, as well as any other additional roles that can be autodetected by debops.postconf role.

[debops_service_postfix]
hostname

[debops_service_postconf]
hostname

[debops_service_saslauthd]
hostname

[debops_service_dovecot]
hostname

Example playbook

If you are using this role without DebOps, here's an example Ansible playbook that uses the debops.postconf role:

---

- name: Manage Postfix configuration
  collections: [ 'debops.debops', 'debops.roles01',
                 'debops.roles02', 'debops.roles03' ]
  hosts: [ 'debops_service_postconf' ]
  become: True

  environment: '{{ inventory__environment | d({})
                   | combine(inventory__group_environment | d({}))
                   | combine(inventory__host_environment  | d({})) }}'

  vars:

    secret__directories:
      - '{{ postfix__secret__directories }}'

    ferm__dependent_rules:
      - '{{ postfix__ferm__dependent_rules }}'

    postfix__dependent_packages:
      - '{{ postconf__postfix__dependent_packages }}'

    postfix__dependent_maincf:
      - role: 'postconf'
        config: '{{ postconf__postfix__dependent_maincf }}'
        state: '{{ postconf__deploy_state }}'

    postfix__dependent_mastercf:
      - role: 'postconf'
        config: '{{ postconf__postfix__dependent_mastercf }}'
        state: '{{ postconf__deploy_state }}'

    postfix__dependent_lookup_tables:
      - '{{ postconf__postfix__dependent_lookup_tables }}'

  pre_tasks:

    - name: Prepare postconf environment
      ansible.builtin.import_role:
        name: 'postconf'
        tasks_from: 'main_env'
      tags: [ 'role::postconf', 'role::postfix', 'role::ferm' ]

    - name: Prepare postfix environment
      ansible.builtin.import_role:
        name: 'postfix'
        tasks_from: 'main_env'
      tags: [ 'role::postfix', 'role::secret', 'role::ferm' ]

  roles:

    - role: secret
      tags: [ 'role::secret', 'role::postfix' ]

    - role: ferm
      tags: [ 'role::ferm', 'skip::ferm' ]

    - role: postfix
      tags: [ 'role::postfix', 'skip::postfix' ]

    - role: postconf
      tags: [ 'role::postconf', 'skip::postconf' ]