Synopsis #
Postfix is a mail transfer agent (MTA) available from OpenBSD packages. It can replace the base smtpd(8) daemon.
Use Postfix on OpenBSD for sending and receiving mail, configuring TLS encryption, relaying via a smarthost, setting up virtual domains and users, and integrating spam and antivirus filters.
Features #
- Secure and modular design
- Supports SMTP, SMTPS, and submission ports
- Authentication and encryption with TLS
- Extensive queue management
- Flexible configuration using
main.cfandmaster.cf - Support for aliases, virtual domains, and LDAP integration
- Integration with
dovecot,spamassassin,amavisd, andrspamd
Installing Postfix #
To install Postfix from packages:
doas pkg_add postfix
To prevent conflicts with OpenSMTPD, disable smtpd(8) if it is enabled:
doas rcctl disable smtpd
doas rcctl stop smtpd
Enable and start the Postfix service:
doas /usr/local/sbin/postfix-enable
doas newaliases
doas rcctl enable postfix
doas rcctl start postfix
Run newaliases before starting Postfix and whenever /etc/mail/aliases changes. This builds the database Postfix uses to look up aliases.
The main configuration directory is:
/etc/postfix/
Configuration #
Postfix uses two main configuration files:
/etc/postfix/main.cf— Primary configuration/etc/postfix/master.cf— Service definitions and process control
After making changes, reload the configuration:
doas postfix reload
Check syntax and configuration:
doas postfix check
Minimal Configuration #
A basic setup for local delivery and outgoing mail using DNS:
myhostname = mail.example.org
myorigin = example.org
mydestination = example.org, $myhostname, localhost
relayhost =
inet_interfaces = loopback-only
inet_protocols = all
This configuration:
- Sets the mail hostname
- Relays outgoing messages using DNS
- Accepts mail only from the local machine
To enable delivery to local users, ensure mailbox_command or mailbox_transport is set appropriately, for example:
home_mailbox = Maildir/
Ensure that each user has a ~/Maildir/ directory.
Accepting Internet Mail #
To accept mail from remote systems:
inet_interfaces = all
myhostname = mail.example.org
mydestination = example.org, mail.example.org, localhost.localdomain, localhost
To restrict incoming mail to a specific domain:
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination
Set the MX record for example.org to mail.example.org, with matching address records. Restart Postfix after changing inet_interfaces; a reload does not apply that setting.
TLS Encryption #
To enable TLS for incoming and outgoing mail:
smtpd_tls_cert_file = /etc/ssl/example.org.crt
smtpd_tls_key_file = /etc/ssl/private/example.org.key
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtp_tls_note_starttls_offer = yes
Ensure proper permissions:
doas chown root:_postfix /etc/ssl/private/example.org.key
doas chmod 640 /etc/ssl/private/example.org.key
To force all clients to use encryption:
smtpd_tls_security_level = encrypt
Outgoing Mail via Smarthost #
For outbound password authentication, install the sasl2 flavor of Postfix using the package selector and confirm SASL support with postconf -A. To relay through a provider:
relayhost = [smtp.example.net]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
Create /etc/postfix/sasl_passwd:
[smtp.example.net]:587 user@example.net:password123
Convert and secure the file:
doas postmap /etc/postfix/sasl_passwd
doas chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
doas sh -c 'chown root:_postfix /etc/postfix/sasl_passwd*'
Reload Postfix:
doas postfix reload
Virtual Domains and Users #
As an alternative to local-domain delivery, map a virtual alias domain to existing local accounts. Remove that domain from mydestination before using virtual_alias_domains:
Define /etc/postfix/virtual
#
admin@example.org adminuser@mail.example.org
sales@example.org salesuser@mail.example.org
info@example.org infoaccount@mail.example.org
Create and map the file:
doas postmap /etc/postfix/virtual
Update main.cf:
virtual_alias_domains = example.org
virtual_alias_maps = hash:/etc/postfix/virtual
Reload Postfix:
doas postfix reload
Filtering Mail #
Postfix supports a variety of content filters via content inspection and milter integration.
Basic Header and Body Checks #
To block specific subjects or bodies, use:
/etc/postfix/header_checks/etc/postfix/body_checks
Enable in main.cf:
header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks
Integration with SpamAssassin and ClamAV #
Install amavisd:
doas pkg_add amavisd-new spamassassin clamav
Configure and start Amavis and its scanning dependencies according to their package READMEs first. Verify that Amavis accepts connections on loopback port 10024 and returns scanned mail to port 10025. The following fragments only connect Postfix to that existing service; enabling them without it defers delivery.
Configure main.cf:
content_filter = smtp-amavis:[127.0.0.1]:10024
Edit /etc/postfix/master.cf to include:
smtp-amavis unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
Administrative Commands #
Check the queue:
doas mailq
Flush the queue:
doas postfix flush
View logs:
doas tail -f /var/log/maillog
Examine configuration:
doas postconf -n
Testing #
Send a test message:
mail -s "Test Postfix" user@example.org < /dev/null
Check if Postfix is listening:
netstat -an | grep 25
Verify TLS:
openssl s_client -starttls smtp -connect mail.example.org:25
Summary of Key Configuration Files #
| File | Purpose |
|---|---|
/etc/postfix/main.cf | Main configuration |
/etc/postfix/master.cf | Daemon/service process configuration |
/etc/postfix/virtual | Virtual address mapping |
/etc/postfix/sasl_passwd | SMTP authentication credentials |
/var/log/maillog | Postfix logging output |
/etc/postfix/header_checks | Regex for filtering message headers |
/etc/postfix/body_checks | Regex for filtering message bodies |
doas postfix reload
Validate and reload after ordinary configuration changes; restart when changing settings such as inet_interfaces.
Alternatives #
Postfix is suitable for most use cases, but lighter alternatives such as smtpd(8) (OpenSMTPD) may be preferred for systems requiring simplicity and tight OpenBSD integration.