FreeBSD.software
Home/Guides/Postfix on FreeBSD: Mail Transfer Agent Review
review·2026-04-09·10 min read

Postfix on FreeBSD: Mail Transfer Agent Review

In-depth review of Postfix on FreeBSD: installation, virtual domains, TLS encryption, DKIM signing, anti-spam integration, and comparison with Sendmail and OpenSMTPD.

Postfix on FreeBSD: Mail Transfer Agent Review

Postfix is the most widely deployed open-source mail transfer agent (MTA) in production today. It handles email delivery for organizations ranging from single-server setups to infrastructure processing millions of messages per day. Wietse Venema designed Postfix as a secure, fast replacement for Sendmail, and two decades later it remains the MTA that most sysadmins reach for when they need reliable email delivery. On FreeBSD, Postfix integrates cleanly with the base system's mail infrastructure, benefits from the security-conscious defaults that FreeBSD provides, and pairs well with Dovecot for IMAP/POP3 access. This review covers Postfix's architecture, FreeBSD-specific installation and configuration, virtual domain hosting, TLS encryption, DKIM signing, anti-spam strategies, and how it compares with Sendmail and OpenSMTPD.

What Postfix Does

Postfix is an MTA -- it accepts email via SMTP, routes it to the correct destination, and delivers it either locally or to another mail server. It does not provide mailbox access (that is Dovecot or Courier's job) or webmail (that is Roundcube or SOGo). Postfix handles the transport layer of email.

Core capabilities:

  • SMTP server -- accepts incoming email from other mail servers and from authenticated local users.
  • SMTP client -- delivers outgoing email to remote mail servers, handling MX lookups, retries, and bounce generation.
  • Virtual domain hosting -- serve email for multiple domains from a single Postfix instance, with per-domain mailbox mappings.
  • TLS encryption -- encrypt SMTP connections with other servers (opportunistic or mandatory) and with authenticated clients (STARTTLS on submission port 587).
  • SASL authentication -- authenticate users submitting email via Dovecot SASL, Cyrus SASL, or other mechanisms.
  • Content filtering -- integrate with milters (Amavis, SpamAssassin, ClamAV, OpenDKIM) for spam filtering, virus scanning, and DKIM signing.
  • Access controls -- restrict relaying, reject connections from known spam sources, enforce rate limits, and apply recipient verification.
  • Queue management -- a sophisticated queue system with deferred, active, hold, and incoming queues that handles transient delivery failures gracefully.

Postfix's architecture is modular: separate processes handle receiving, queuing, delivery, and cleanup. Each process runs with minimal privileges. A compromise of one component does not grant access to the entire mail system.

Installation on FreeBSD

Postfix is available as a binary package and through the ports tree.

Binary Package Installation

sh
pkg install postfix

This installs Postfix under /usr/local/sbin/ with configuration at /usr/local/etc/postfix/. The package includes TLS support via OpenSSL and SASL support via the Cyrus SASL library.

Disable Sendmail

FreeBSD ships Sendmail in the base system. Disable it before enabling Postfix:

sh
sysrc sendmail_enable="NONE" sysrc sendmail_submit_enable="NO" sysrc sendmail_outbound_enable="NO" sysrc sendmail_msp_queue_enable="NO"

Stop any running Sendmail processes:

sh
service sendmail stop

Configure the system to use Postfix as the default mailer:

sh
cat >> /etc/mail/mailer.conf << 'EOF' sendmail /usr/local/sbin/sendmail send-mail /usr/local/sbin/sendmail mailq /usr/local/sbin/sendmail newaliases /usr/local/sbin/sendmail EOF

Enable and Start Postfix

sh
sysrc postfix_enable="YES" service postfix start

Verify Installation

sh
postconf mail_version postfix check

The postfix check command reports configuration errors and file permission issues. Fix any warnings before putting the server into production.

Core Configuration

Postfix configuration lives in two files: /usr/local/etc/postfix/main.cf (parameters) and /usr/local/etc/postfix/master.cf (service definitions).

Basic main.cf

sh
cat > /usr/local/etc/postfix/main.cf << 'EOF' # Identity myhostname = mail.example.com mydomain = example.com myorigin = $mydomain # Network inet_interfaces = all inet_protocols = ipv4 mydestination = $myhostname, localhost.$mydomain, localhost mynetworks = 127.0.0.0/8 # Mailbox home_maildir = Maildir/ mailbox_size_limit = 0 message_size_limit = 52428800 # TLS (incoming) smtpd_tls_cert_file = /usr/local/etc/letsencrypt/live/mail.example.com/fullchain.pem smtpd_tls_key_file = /usr/local/etc/letsencrypt/live/mail.example.com/privkey.pem smtpd_tls_security_level = may smtpd_tls_protocols = >=TLSv1.2 smtpd_tls_mandatory_protocols = >=TLSv1.2 # TLS (outgoing) smtp_tls_security_level = may smtp_tls_protocols = >=TLSv1.2 smtp_tls_loglevel = 1 # SASL Authentication smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes # Restrictions smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_rbl_client zen.spamhaus.org, reject_rbl_client bl.spamcop.net # Milter (DKIM, SpamAssassin) smtpd_milters = unix:/var/run/opendkim/opendkim.sock non_smtpd_milters = $smtpd_milters milter_default_action = accept # Aliases alias_maps = hash:/usr/local/etc/postfix/aliases alias_database = hash:/usr/local/etc/postfix/aliases EOF

Submission Port (587) for Authenticated Users

Edit /usr/local/etc/postfix/master.cf to enable the submission port:

sh
submission inet n - n - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_tls_auth_only=yes -o smtpd_reject_unlisted_recipient=no -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING

This ensures that mail clients connect on port 587 with mandatory TLS and SASL authentication. Port 25 remains for server-to-server email.

Virtual Domain Hosting

For hosting email for multiple domains, use Postfix's virtual domain support.

Virtual Alias Domains

sh
# In main.cf virtual_alias_domains = example.com, example.org, example.net virtual_alias_maps = hash:/usr/local/etc/postfix/virtual

Create the virtual alias map:

sh
cat > /usr/local/etc/postfix/virtual << 'EOF' info@example.com john sales@example.com john, jane admin@example.org root @example.net catchall@example.com EOF postmap /usr/local/etc/postfix/virtual

Virtual Mailbox Domains (with Dovecot)

For larger deployments with per-user mailboxes stored outside the system user accounts:

sh
# In main.cf virtual_mailbox_domains = hash:/usr/local/etc/postfix/virtual_domains virtual_mailbox_base = /var/mail/vhosts virtual_mailbox_maps = hash:/usr/local/etc/postfix/virtual_mailboxes virtual_minimum_uid = 1000 virtual_uid_maps = static:1000 virtual_gid_maps = static:1000 virtual_transport = lmtp:unix:private/dovecot-lmtp

This configuration delivers email to Dovecot via LMTP, which handles mailbox storage, Sieve filtering, and quota enforcement.

TLS Configuration

TLS is non-negotiable for modern email. Without it, email travels in cleartext between servers, and ISPs will flag your server as untrusted.

Obtaining Certificates

Use Let's Encrypt with the certbot standalone plugin or DNS challenge:

sh
pkg install py311-certbot certbot certonly --standalone -d mail.example.com

Or if you are running Caddy or another web server, use the webroot method.

TLS Session Cache

Improve TLS performance with session caching:

sh
smtpd_tls_session_cache_database = btree:/var/db/postfix/smtpd_scache smtp_tls_session_cache_database = btree:/var/db/postfix/smtp_scache smtpd_tls_session_cache_timeout = 3600s

MTA-STS

Publish an MTA-STS policy to tell other mail servers that your domain requires TLS:

Create a _mta-sts.example.com DNS TXT record and host a policy file at https://mta-sts.example.com/.well-known/mta-sts.txt.

DKIM Signing

DomainKeys Identified Mail (DKIM) signs outgoing messages with a cryptographic key, allowing recipients to verify the message originated from your domain.

Install OpenDKIM

sh
pkg install opendkim

Generate DKIM Key

sh
mkdir -p /usr/local/etc/opendkim/keys/example.com opendkim-genkey -b 2048 -d example.com -s mail -D /usr/local/etc/opendkim/keys/example.com chown opendkim:opendkim /usr/local/etc/opendkim/keys/example.com/mail.private

Configure OpenDKIM

sh
cat > /usr/local/etc/opendkim.conf << 'EOF' Syslog yes SyslogSuccess yes Mode sv Canonicalization relaxed/simple Domain example.com Selector mail KeyFile /usr/local/etc/opendkim/keys/example.com/mail.private Socket local:/var/run/opendkim/opendkim.sock PidFile /var/run/opendkim/opendkim.pid UserID opendkim:opendkim UMask 007 EOF

Enable and start:

sh
sysrc milteropendkim_enable="YES" service milter-opendkim start

Publish the DNS Record

Display the DNS record to add:

sh
cat /usr/local/etc/opendkim/keys/example.com/mail.txt

Add this TXT record to your domain's DNS. It enables receiving servers to verify your DKIM signatures.

Anti-Spam Configuration

RBL (Real-time Blackhole Lists)

The smtpd_recipient_restrictions in the configuration above already includes Spamhaus and SpamCop RBLs. These reject connections from known spam sources at the SMTP level, before any message content is processed.

SpamAssassin Integration

Install SpamAssassin and the Amavis content filter:

sh
pkg install amavisd-new spamassassin sysrc amavisd_enable="YES" sysrc spamd_enable="YES" service sa-spamd start service amavisd start

Add to main.cf:

sh
content_filter = smtp-amavis:[127.0.0.1]:10024

Add to master.cf:

sh
smtp-amavis unix - - n - 2 smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes 127.0.0.1:10025 inet n - n - - smtpd -o content_filter= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8

SPF Verification

sh
pkg install postfix-policyd-spf-python

Add to main.cf:

sh
policy-spf_time_limit = 3600s smtpd_recipient_restrictions = ... check_policy_service unix:private/policy-spf

Postfix vs Sendmail

Sendmail ships in FreeBSD's base system, making it the default MTA. However, Postfix is superior for nearly every use case:

  • Configuration -- Sendmail's sendmail.cf is notoriously difficult to read and modify. Its M4 macro system adds a layer of complexity. Postfix's main.cf uses simple parameter = value syntax.
  • Security -- Postfix was designed from the ground up with security in mind. Each component runs with minimal privileges. Sendmail has a longer history of security vulnerabilities due to its monolithic architecture.
  • Performance -- Postfix handles higher message volumes with lower resource consumption. Its queue management is more efficient under load.
  • Virtual domains -- Postfix's virtual domain support is straightforward. Sendmail's virtusertable works but is cumbersome for large deployments.

The only reason to keep Sendmail is if you have existing, working Sendmail configurations that you cannot justify the time to migrate. For new deployments, always choose Postfix.

Postfix vs OpenSMTPD

OpenSMTPD is developed by the OpenBSD project and is available on FreeBSD. The comparison:

  • Simplicity -- OpenSMTPD's configuration is more concise and readable than Postfix for simple setups. A basic mail server can be configured in under 10 lines.
  • Feature set -- Postfix has a deeper feature set: more access control options, better milter support, more lookup table types, and more granular queue management.
  • Ecosystem -- Postfix has more documentation, more tutorials, and more community support. Finding answers to Postfix questions is easier.
  • Milter support -- Postfix has mature milter support for DKIM, SpamAssassin, and ClamAV. OpenSMTPD's filter system is different and has fewer third-party integrations.

For a small personal mail server, OpenSMTPD is a viable alternative. For a multi-domain mail server with DKIM, SPF, DMARC, and SpamAssassin integration, Postfix is the more practical choice due to its ecosystem.

Queue Management

Monitor the Postfix queue:

sh
mailq postqueue -p

Flush the queue (retry deferred messages):

sh
postqueue -f

Delete all messages in the deferred queue:

sh
postsuper -d ALL deferred

View a specific message:

sh
postcat -q QUEUE_ID

Put a message on hold:

sh
postsuper -h QUEUE_ID

Monitoring and Logging

Postfix logs to syslog, typically at /var/log/maillog on FreeBSD:

sh
tail -f /var/log/maillog

Key patterns to watch:

  • status=sent -- successful delivery.
  • status=deferred -- temporary failure, will retry.
  • status=bounced -- permanent failure, bounce generated.
  • reject: -- message rejected by access controls.

For Prometheus monitoring, use postfix_exporter:

sh
pkg install postfix_exporter sysrc postfix_exporter_enable="YES" service postfix_exporter start

Verdict

Postfix is the standard MTA for FreeBSD servers that need to handle email. Its security architecture, configuration clarity, virtual domain support, and milter ecosystem make it the right choice for anything from a single-domain personal server to a multi-tenant email platform. The combination of Postfix, Dovecot, OpenDKIM, and SpamAssassin on FreeBSD provides a complete, self-hosted email stack that competes with commercial email infrastructure.

Sendmail should be replaced on any FreeBSD system that handles non-trivial email. OpenSMTPD is a worthy alternative for simple setups, but Postfix's deeper feature set and larger community make it the safer choice for production email.


Frequently Asked Questions

Can I run Postfix in a FreeBSD jail?

Yes. Postfix runs in jails without modification. Ensure the jail has a dedicated IP address, proper DNS records (MX, A, PTR, SPF, DKIM, DMARC), and access to ports 25, 587, and 993 (for Dovecot).

How do I set up DMARC?

DMARC is a DNS record, not a Postfix configuration. Add a TXT record at _dmarc.example.com with your DMARC policy. For receiving DMARC reports, install opendmarc and configure it as a milter alongside OpenDKIM.

How many emails per second can Postfix handle on FreeBSD?

On a 4-core FreeBSD server with SSD storage, Postfix can process 500-1000 messages per second for local delivery and 100-300 messages per second for remote delivery (limited by DNS lookups and remote server response times).

Should I use Dovecot SASL or Cyrus SASL?

If you are using Dovecot for IMAP (which you should), use Dovecot SASL. It shares the same user database and authentication mechanism, reducing configuration complexity. Cyrus SASL is an additional dependency with its own configuration.

How do I handle bounce messages?

Postfix generates bounce messages automatically for permanently undeliverable mail. Configure bounce_size_limit to control how much of the original message is included. For mailing lists, set VERP to enable per-recipient bounce tracking.

What DNS records do I need for email?

At minimum: an A record for the mail server, an MX record pointing to it, a PTR record (reverse DNS) matching the A record, an SPF TXT record, a DKIM TXT record, and a DMARC TXT record. Missing any of these will cause delivery issues to major providers (Gmail, Outlook, Yahoo).

Get more FreeBSD guides

Weekly tutorials, security advisories, and package updates. No spam.