Skip to content

Nuface Blog

隨意隨手記 Casual Notes

Menu
  • Home
  • About
  • Services
  • Blog
  • Contact
  • Privacy Policy
  • Login
Menu

Postfix 3.10: Building a Modern SMTP Core with Docker, MySQL, SNI, Amavis & Milter

Posted on 2025-11-202025-11-21 by Rico

Mail Server Series — Part 4

In the previous chapters of this series, we completed:

  • Part 1 – Overall architecture overview
  • Part 2 – Network, DNS, and SSL (Let’s Encrypt)
  • Part 3 – MariaDB & PostfixAdmin (virtual domains & users)

Now we move on to the heart of the mail system: Postfix.

This chapter focuses on how we build a fully-featured Postfix 3.10.4 SMTP service from source code, package it into a Docker image, integrate it with MySQL, enable multi-domain SNI, connect it with Dovecot for delivery, and route messages through Amavis and Piler.


🚀 1. Why Build Postfix Yourself?

Postfix does not provide an official Docker image. Installing from apt usually gives you:

  • Outdated versions (Ubuntu 24.04 ships Postfix 3.7.x)
  • Missing features (MySQL, LMDB, SNI maps)
  • Limited flexibility inside containers
  • Missing PCRE2 support (latest regex engine)
  • Difficulties enabling advanced modules

Therefore, this project uses:

👉 Postfix 3.10.4 built from source
👉 Fully packaged into a custom Docker image

With full support for:

✔ MySQL maps
✔ LMDB (for TLS SNI)
✔ PCRE2 regex
✔ SASL authentication
✔ TLS & multi-domain SNI
✔ PostfixAdmin schema
✔ Amavis (Anti-Spam / Anti-Virus)
✔ Piler milter (X-Envelope-To extraction)


🧱 2. Building the Postfix Docker Image (Multi-Stage)

Directory:

/opt/docker/mail/postfix/

2.1 Builder Stage

FROM ubuntu:24.04 AS builder

RUN apt-get update && apt-get install -y \
  build-essential libssl-dev libsasl2-dev libmariadb-dev \
  liblmdb-dev libpcre2-dev ...

WORKDIR /usr/src
RUN curl -LO https://archive.postfix.org/official/postfix-3.10.4.tar.gz
RUN tar xzf postfix-3.10.4.tar.gz

WORKDIR /usr/src/postfix-3.10.4
RUN make -f Makefile.init makefiles \
    CCARGS="-DUSE_TLS -DUSE_SASL_AUTH -DHAS_MYSQL -DHAS_LMDB -DHAS_PCRE2" \
    AUXLIBS="-lssl -lcrypto -lsasl2 -lpcre2-8"

2.2 Runtime Stage

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y \
  libssl3 libsasl2-2 libmariadb3 liblmdb0 libpcre2-8-0 ...

COPY --from=builder /tmp/postfix-stage/ /

ENTRYPOINT ["/usr/local/sbin/docker-entrypoint.sh"]

🎯 This produces a clean, stable, and fully extensible Postfix 3.10 Docker image.


🐳 3. Starting the Postfix Container

docker run -dit --name postfix \
  --restart=always \
  --network intranet-net \
  -p 25:25 -p 587:587 \
  -e TZ=Asia/Taipei \
  -v $PWD/config:/etc/postfix \
  -v $PWD/log:/var/log/postfix \
  -v /opt/docker/wwwapp/data/etc-letsencrypt:/etc/letsencrypt \
  nuface/postfix-3.10.4:1.0

Ports:

  • 25 – incoming messages from the Internet
  • 587 – submission for authenticated users

📑 4. Postfix main.cf – Detailed Breakdown

Below is the logical overview.


4.1 Basic Settings

myhostname = it.demo.tw
mydestination = $myhostname, localhost
inet_interfaces = all

Important:
Never add your virtual domains to mydestination
otherwise all user mail becomes “local delivery”.


4.2 TLS / SNI Configuration

smtpd_tls_chain_files =
  /etc/letsencrypt/live/it.demo.tw/privkey.pem,
  /etc/letsencrypt/live/it.demo.tw/fullchain.pem

Enable SNI:

smtpd_tls_server_sni_maps = lmdb:/etc/postfix/tls_sni

Example:

it.demo.tw  /etc/letsencrypt/live/it.demo.tw/privkey.pem  /fullchain.pem
nuface.tw   /etc/letsencrypt/live/nuface.tw/privkey.pem   /fullchain.pem

4.3 SASL (Dovecot Authentication)

smtpd_sasl_type = dovecot
smtpd_sasl_path = inet:dovecot:12345
smtpd_sasl_auth_enable = yes

Provides secure login for submission (Thunderbird/Outlook/Roundcube).


4.4 MySQL Virtual Mail System (PostfixAdmin compatible)

virtual_mailbox_domains = mysql:/etc/postfix/sql/virtual_domains.cf
virtual_mailbox_maps    = mysql:/etc/postfix/sql/virtual_mailboxes.cf
virtual_alias_maps      = mysql:/etc/postfix/sql/virtual_aliases.cf ...
relay_domains           = mysql:/etc/postfix/sql/relay_domains.cf

These SQL maps directly match the PostfixAdmin database schema.


4.5 Delivering Emails using Dovecot LMTP

virtual_transport = lmtp:inet:dovecot:24

Benefits:

  • Full quota support
  • Error reporting to the sender
  • More reliable than local delivery

4.6 Milter – Sending Envelope RCPT to Piler

smtpd_milters = inet:pilermilter:33333
non_smtpd_milters = inet:pilermilter:33333

The milter adds:

X-Envelope-From:
X-Envelope-To:

This enables per-user access control in Piler.


🔧 5. master.cf – SMTP Processing Pipeline

This is where the actual message flow is defined.


5.1 Inbound (Port 25 → Amavis)

smtp inet ... content_filter=smtp-amavis:[amavis]:10024

Postfix → Amavis → Scan → Back to Postfix.


5.2 Amavis Return Path (10025)

10025 runs a reduced security smtpd instance:

  • No extra checks
  • No double filtering
  • No duplicate DKIM signing
  • Straight to delivery

5.3 Outbound Sign & Relay (10027)

Used for outgoing mail from Submission (587):

Postfix → Amavis → DKIM Sign → 10027 → Internet


5.4 Submission (587)

smtpd_tls_security_level=encrypt
smtpd_sasl_auth_enable=yes
milter_macro_daemon_name=ORIGINATING

Strict security for end-user mail clients.


✉ 6. Transport Maps (Sending to Piler Archive)

archive.local    smtp:[172.18.0.1]:2525

Used together with:

always_bcc = piler@archive.local

All emails → archived automatically.


🗄 7. SQL Map Files

You created:

  • virtual_domains.cf
  • virtual_mailboxes.cf
  • virtual_aliases*.cf
  • sender_login_maps.cf
  • relay_domains.cf

All pointing to:

maildb → postfix

PostfixAdmin writes → Postfix reads → Dovecot delivers
A complete, unified virtual mail system.


🧪 8. Testing the System

8.1 Check Postfix version

postconf mail_version

8.2 Test SNI

openssl s_client -connect mail.it.demo.tw:25 -starttls smtp -servername it.demo.tw

8.3 Test MySQL maps

postmap -q [email protected] mysql:/etc/postfix/sql/virtual_mailboxes.cf

8.4 Test LMTP delivery

sendmail [email protected]

8.5 Test port 587 submission

openssl s_client -connect it.demo.tw:587 -starttls smtp

8.6 Check Piler milter headers

X-Envelope-To:
X-Envelope-From:

🏁 9. Conclusion: Your SMTP Core Is Now Complete

At this stage, your mail system supports:

✔ Multi-domain hosting
✔ Virtual users
✔ Secure TLS + SNI
✔ SPF/DKIM/DMARC ready
✔ Amavis spam & virus filtering
✔ LMTP delivery
✔ Full mail archiving via Piler
✔ SQL-based configuration

Postfix is now fully operational with all enterprise-grade features.

Recent Posts

  • Postfix + Let’s Encrypt + BIND9 + DANE Fully Automated TLSA Update Guide
  • Postfix + Let’s Encrypt + BIND9 + DANE TLSA 指紋自動更新完整教學
  • Deploying DANE in Postfix
  • 如何在 Postfix 中部署 DANE
  • DANE: DNSSEC-Based TLS Protection

Recent Comments

  1. Building a Complete Enterprise-Grade Mail System (Overview) - Nuface Blog on High Availability Architecture, Failover, GeoDNS, Monitoring, and Email Abuse Automation (SOAR)
  2. Building a Complete Enterprise-Grade Mail System (Overview) - Nuface Blog on MariaDB + PostfixAdmin: The Core of Virtual Domain & Mailbox Management
  3. Building a Complete Enterprise-Grade Mail System (Overview) - Nuface Blog on Daily Operations, Monitoring, and Performance Tuning for an Enterprise Mail System
  4. Building a Complete Enterprise-Grade Mail System (Overview) - Nuface Blog on Final Chapter: Complete Troubleshooting Guide & Frequently Asked Questions (FAQ)
  5. Building a Complete Enterprise-Grade Mail System (Overview) - Nuface Blog on Network Architecture, DNS Configuration, TLS Design, and Postfix/Dovecot SNI Explained

Archives

  • December 2025
  • November 2025
  • October 2025

Categories

  • AI
  • Apache
  • Cybersecurity
  • Database
  • DNS
  • Docker
  • Fail2Ban
  • FileSystem
  • Firewall
  • Linux
  • LLM
  • Mail
  • N8N
  • OpenLdap
  • OPNsense
  • PHP
  • QoS
  • Samba
  • Switch
  • Virtualization
  • VPN
  • WordPress
© 2025 Nuface Blog | Powered by Superbs Personal Blog theme