User Tools

This is an old revision of the document!


Configuration: postfix

We need to configure Postfix properly, and link it to the SQLite database we created so that it will read domains and accounts from there.

Postfix configuration files are located under /etc/postfix and can be summarized as:

  • main.cf: contains all the oeprative directives of Postfix
  • master.cf: contains the services started by Postfix
  • sql/*.cf: the specific SQLite link files. You need to create this folder.

The concept of virtual delivery comes from the legacy idea that the mail server delivers mail to local users on the local server. Of course, this has not been true for the last (too many) decades, but the concept still stand and Postfix talks about virtual delivery to differentiate from delivery mail to local server users.

Please note that Postfix configuration is deeply connected to Dovecot, Spamassassin, OpenDKIM and OpenDMARC. The following configuration assumes you have already configured them all. So before you start Postfix you will need to set them up as well. See the relevant pages.

Before configuring Postfix, it is recomended to read this page.

Postfix support all kinds of SQL databases, including SQLite. To integrate it, you need to create a few cf files and specify associated directives in the main.cf.

Create the sql folder:

mkdir /etc/postfix/sql

Drop all the following files in the sql folder.

File: /etc/postfix/sql/virtual_mailbox_domains.cf which fetch the list of domains:

virtual_mailbox_domains.cf
dbpath = /home/vmail/database/vmail.sqlite3
query  = SELECT domain FROM domain WHERE domain = '%s' AND backupmx = '0' AND active = '1';

File: /etc/postfix/sql/virtual_mailbox_maps.cf which fetch the list of mailboxes:

virtual_mailbox_maps.cf
dbpath = /home/vmail/database/vmail.sqlite3
query  = SELECT maildir FROM mailbox WHERE local_part='%u' AND domain='%d' AND active='1';

File: /etc/postfix/sql/virtual_alias_maps.cf which fetch the list of accounts and aliases:

virtual_alias_maps.cf
dbpath = /home/vmail/database/vmail.sqlite3
query  = SELECT goto FROM alias WHERE address='%s' AND active='1';

To ensure the above files are used by postfix, the following lines need to be added to the main.cf config file:

# A list of all virtual domains serviced by this instance of postfix.
virtual_mailbox_domains = sqlite:/etc/postfix/sql/virtual_mailbox_domains.cf
# Look up the mailbox location based on the email address received.
virtual_mailbox_maps = sqlite:/etc/postfix/sql/virtual_mailbox_maps.cf
# Any aliases that are supported by this system
virtual_alias_maps = sqlite:/etc/postfix/sql/virtual_alias_maps.cf

The example files at the bottom of this page will include those lines as well.

main.cf: configuration

Setting up Postfix properly is not an easy task. I will guide you trough my experience and will try to describe the main stuff you need to setup here.

I will list and try to describe all the settings in the example file below here:

  • compatibility_level: refer to the syntax used in the configuration and the minimum Postfix version.
  • soft_bounce: if yes, local generated emails that bounce will not be discarded. This is useful during testing of the server, until everything is properly setup. You should set it to no afterward.
  • queue_directory, command_directory, daemon_directory, data_directory, sendmail_path, newaliases_path, mailq_path: do not edit, these are postfix standard paths.
  • mail_owner: the user used my postfix to run. Do not change it. Don't, really.
  • setgid_group: do not edit, like above
  • myhostname: set this to the domain part of your FQDN. If you host more than one domain, pick the main one.
  • mydomain: set this to the domain part of your FQDN. If you host more than one domain, pick the main one (yes, the same as above).
  • myorigin: set for local generated mail. Set it to your main domain.
  • inet_interfaces: on which interfaces postfix should listen on. All is the usual default.
  • mydestination: which email destination domains should be delivered to this server. This does not include the virtual domains. On modern servers, leave it to localhost.localdomain.
  • local_recipient_maps: leave this commented, you do not want to deliver emails to local users of the server.
  • unknown_lo#relay_domainscal_recipient_reject_code: 550 will cause messages to be discarded, while 450 will have upstream servers try again to send the mail, when the destination user does not exist. Since you will use the SQLite virtual maps, it's safe to use 550 here.
  • mynetworks_style: leave it as host. This means that trusted hosts will only be the server itself
  • relay_domains: for which domains this server will relay mail. Leave it blank or don't set it at all!
  • in_flow_delay: throttle incoming mails to 1 per second under heavy loads. It's a good idea to set it to at least 1 (maximum is 10).
  • home_mailbox: name of folder where to store incoming messages. This will then be picked up by Dovecot later on for IMAP access.
  • smtpd_banner: define how Postfix will reply to other servers connecting to it. It's a good choice not to reply with software version or postfix.
  • html_directory, readme_directory: leave to no, you don't want to expose postfix documentation
  • inet_protocols: which protocol to use. ipv4 is the typical one. You can feel lucky and enable also IPv6.
  • meta_directory, shlib_directory: don't touch them
  • virtual_mailbox_domains, virtual_mailbox_maps, virtual_alias_maps: see the SQL link section above
  • virtual_mailbox_base: where postfix will store the incoming emails
  • local_transport: set to virtual, since you want virtual delivery
  • biff: enable or disable the use of biff to notify local users of incoming email. There are no local users as already stated, so disable it.
  • message_size_limit: set maximum email message size. 0 to disable any size check.
  • disable_vrfy_command: prevent email harvesting via VRFY command. Set to yes.
  • local_recipient_maps: allow local delivery for your users. Set to your virtual map
  • virtual_transport: which transport to use for virtual delivery. Set as below to use dovecot delivery.
  • virtual_uid_maps, virtual_gid_maps: UID and GID to use for virtual maps. Match your vmail user.

Also check the SASL and TLS related rows, as enabling encryption layer and authentication is mandatory from a security point of view. For the TLS settings, smtpd_tls_auth_only should be set to yes to prevent unencrypted transfer of passwords.

The spam filtering rows require you to have setup spamassassin too.

For more details on all the possible options, see Postfix documentation.

This is the overall file. Do not copy it blindly, double check everything:

main.cf
compatibility_level = 3.9
soft_bounce = yes
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
myhostname = mydomain.com
mydomain = mydomain.com
myorigin = $mydomain
inet_interfaces = all
mydestination = localhost.localdomain
unknown_local_recipient_reject_code = 550
mynetworks_style = host
in_flow_delay = 1s
home_mailbox = .maildir/
smtpd_banner = $myhostname ESMTP NO UCE
sendmail_path = /usr/sbin/sendmail
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
setgid_group = postdrop
html_directory = no
readme_directory = no
inet_protocols = ipv4
meta_directory = /etc/postfix
shlib_directory = /usr/lib64/postfix/${mail_version}
virtual_mailbox_domains = sqlite:/etc/postfix/sql/virtual_mailbox_domains.cf
virtual_mailbox_maps = sqlite:/etc/postfix/sql/virtual_mailbox_maps.cf
virtual_alias_maps = sqlite:/etc/postfix/sql/virtual_alias_maps.cf
virtual_mailbox_base = /home/vmail/storage
local_transport = virtual
biff = no
message_size_limit = 0
disable_vrfy_command = yes
local_recipient_maps = $alias_maps $virtual_mailbox_maps
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
# SASL - The following rows for SASL authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
broken_sasl_auth_clients = no
smtpd_sasl_authenticated_header = yes
# Setup TLS - use Let's Encrypt certificates
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.mydomain.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.mydomain.com/privkey.pem
smtpd_tls_loglevel = 0
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
# Some ANTISPAM
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, permit
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unknown_sender_domain, reject_non_fqdn_sender, permit
smtpd_recipient_restrictions = reject_unauth_pipelining, reject_unknown_recipient_domain, permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_non_fqdn_recipient,  check_policy_service unix:private/policy-spf, permit
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated
#, reject_rbl_client zen.spamhaus.org, reject_rbl_client bl.spamcop.net
body_checks = regexp:/etc/postfix/body_checks
# DKIM, SPF, DMARC connection
smtpd_milters = unix:/var/run/opendkim/opendkim.sock,unix:/var/run/opendmarc/opendmarc.sock
non_smtpd_milters = unix:/var/run/opendkim/opendkim.sock,unix:/var/run/opendmarc/opendmarc.sock
# Some lmits and timeouts (adapt as needed)
#policy-spf_time_limit = 3600s
#default_process_limit = 200
#smtpd_timeout = 60s
#smtputf8_enable = no
#smtp_data_done_timeout = 1800
#maximal_queue_lifetime = 60m
#bounce_queue_lifetime = 60m
#smtp_connect_timeout  = 15s
#smtp_helo_timeout = 60s
# Logging defaults
syslog_facility = mail
syslog_name = postfix

#smtpd_relay_before_recipient_restrictions = no

The following file implements some basic checks to discard spam or worse. It's needed if you specified body_checks above.

File /etc/postfix/body_checks:

body_checks
/Listed in Razor2/ DISCARD
/RBL: Received via a relay in Spamhaus XBL/ DISCARD
/Delivered to internal network by a host with no rDNS/ DISCARD
/Listed in Pyzor/ DISCARD
/URIBL_BLACK/ DISCARD
/Content-Type only seen in 419 spam/ DISCARD
/BODY: Mentions millions of/ DISCARD
/BODY: Dear Beneficiary/ DISCARD
/Advance Fee fraud/ DISCARD
/FILL_THIS_FORM_FRAUD_PHISH/ DISCARD
/RBL: Received via a relay in PSBL/ DISCARD
/Delivered to internal network by a host with no rDNS/ DISCARD
/Forged mail pretending to/ DISCARD
/Message-Id is not valid, according to RFC 2822/ DISCARD
/RCVD_IN_PSBL/ DISCARD

master.cf: configuration

The master.cf contains a list of the services (and ports) managed by Postfix on startup.

master.cf
#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=spamassassin

submission inet n       -       n       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_security_level=may
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
pickup    fifo  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache


policy-spf  unix  -       n       n       -       -       spawn
     user=nobody argv=/usr/bin/policyd-spf

spamassassin unix -     n       n       -       -       pipe
        user=spamd argv=/usr/bin/spamc -f -e
                /usr/sbin/sendmail -oi -f ${sender} ${recipient}


spamassassin unix -     n       n       -       -       pipe
        user=spamd argv=/usr/bin/spamc -f -e
                /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Aliases

Before starting postfix you need to generate the aliases database:

newaliases

that's it.

This website uses technical cookies only. No information is shared with anybody or used in any way but provide the website in your browser.

More information