postfix config from scratch.

April 27th, 2014 by exhuma.twn

There are many postfix tutorials out there. I’ve always wondered what the hell I was copy/pasting onto my system and decided to start (nearly) from scratch. I took one of those tutorials (don’t remember which one) as inspiration, but based the final result on the official docs. I kept what I liked, changed some settings I did not like so much, and threw out a few other things which I deemed useless.

The main problem with those tutorials is that they show you a final result without telling you how they ended up with the result, sometimes it looks like an amalgam of other tutorials ending up in a huge “frankenconfig”. I don’t like deploying something where I don’t know what it’s doing…

The final result is a config which is stripped down to my most basic needs.

The first iteration will be an extremely simple config:

  • No database will be used to store mail config. This however is something I will certainly implement.
  • Only simple spam handling using blocklists.
  • No antivirus.
  • No webmail access.
  • No POP access.
  • No IMAP access.
  • Not relay mails for other hosts (only local delivery)j.

For now, I only require e-mail aliasing. That is, I only want to handle e-mails destined for my domains, but I only want to “forward” them to other destinations. Local delivery (and access to those mails) may or may not be implemented later. It will be set up on an Ubuntu Precise Pangolin Server and should get you started for a basic mail server.

Here’s the main config:


The template contains 3 “variables”. Those variables need to be replaced by your values before deploying this!

The fully qualified hostname of your server
The group-id of the local system group for files stored on the local disk.
The user-id of the local system user for files stored on the local disk.

The most interesting part of the config is at the end of the config after the “Virtual Mail” header. This part defines which e-mail addresses the MTA is handling and how. Will the mails be stored locally? Will they be “aliased” to another e-mail?

The config should be documented well-enough.

    # Debian specific:  Specifying a file name will cause the first
    # line of that file to be used as the name.  The Debian default
    # is /etc/mailname.
    myorigin = /etc/mailname

    smtpd_banner = $myhostname ESMTP $mail_name
    biff = no

    # appending .domain is the MUA's job.
    append_dot_mydomain = no

    # Uncomment the next line to generate "delayed mail" warnings
    delay_warning_time = 4h

    readme_directory = no

    # TLS parameters
    smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
    smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

    # See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
    # information on enabling SSL in the smtp client.

    myhostname = {{fqdn}}
    alias_maps = hash:/etc/aliases
    alias_database = hash:/etc/aliases
    mydestination = {{fqdn}}, $myorigin
    relayhost =
    mynetworks = [::ffff:]/104 [::1]/128
    mailbox_size_limit = 51200000
    recipient_delimiter = +
    inet_interfaces = all
    inet_protocols = all

    # how long to keep message on queue before return as failed.
    maximal_queue_lifetime = 7d
    # how many address can be used in one message.
    # effective stopper to mass spammers, accidental copy in whole address list
    # but may restrict intentional mail shots.
    smtpd_recipient_limit = 16
    # how many error before back off.
    smtpd_soft_error_limit = 3
    # how many max errors before blocking it.
    smtpd_hard_error_limit = 12
    # Requirements for the HELO statement
    smtpd_helo_restrictions = permit_mynetworks, warn_if_reject
        reject_non_fqdn_hostname, reject_invalid_hostname, permit
    # Requirements for the sender details
    smtpd_sender_restrictions = permit_mynetworks, warn_if_reject
        reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining,
    # Requirements for the connecting server
    smtpd_client_restrictions = reject_rbl_client,
    # Requirement for the recipient address
    smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks,
        reject_non_fqdn_recipient, reject_unknown_recipient_domain,
        reject_unauth_destination, permit
    smtpd_data_restrictions = reject_unauth_pipelining
    # require proper helo at connections
    smtpd_helo_required = yes
    # waste spammers time before rejecting them
    smtpd_delay_reject = yes
    disable_vrfy_command = yes

    # ----------------------------------------------------------------------------
    #   Virtual Mail
    # ----------------------------------------------------------------------------

    # basic security (user ID mapping)
    virtual_minimum_uid = 100
    virtual_gid_maps = static:{{vgid}}
    virtual_uid_maps = static:{{vuid}}

    # base folder
    virtual_mailbox_base = /var/spool/mail/virtual

    # Domains for which we only ALIAS (mail will not be stored on the local disk).
    virtual_alias_domains = hash:/etc/postfix/valias_domains

    # Domains for which we deliver mail LOCALLY (mail will be stored on local
    # disk).
    virtual_mailbox_domains = hash:/etc/postfix/vdomains

    # Aliases. Maps one e-mail to another.
    # delivered (i.e. stored on the local disk), the end-point of the alias (the
    # "right-hand side") must be on a domain which is delivered LOCALLY (see
    # below).
    virtual_alias_maps = hash:/etc/postfix/valiases

    # Mappings for locally delivered mail (maps to files/folders which are stored
    # below the base folder `virtual_mailbox_base`)
    virtual_mailbox_maps = hash:/etc/postfix/vmailbox

Examples for the hash files (for an explanation what they do, see above):

---- valias_domains -- This is a "list", so the left-hand-side
---- is usually the same as the right-hand-side.

domain1.tld    domain1.tld
domain2.tld    domain2.tld

---- vdomains -- This is another list.

domain3.tld    domain3.tld

---- valiases -- This is a "map". Think "key/value". So,
---- forcibly the LHS differs from the RHS

user@domain1.tld          john.doe@external.domain.tld
user2@domain2.tld         user@domain1.tld

---- vmailbox -- This is another "map"
# the trailing slash defines a Maildir format.
user3@domain3.tld         folder/subfolder/user3/

# Not having a trailing slash makes it an Mbox file.
user4@domain3.tld         folder/subfolder/user4

Posted in Linux | No Comments »


Recent Posts