Configuring Postfix with SSL Certificates for Multiple Virtual Domains


1 views

When running a Postfix mail server hosting multiple independent virtual domains (e.g., xxx.com and yyy.com) on a single instance, SSL certificate management becomes critical. Users expect to connect to their domain-specific mail servers (mail.xxx.com, mail.yyy.com), but all requests ultimately hit the same Postfix service.

You have three main approaches for SSL configuration:

# Option 1: Single certificate with Subject Alternative Names (SAN)
smtpd_tls_cert_file = /etc/ssl/certs/mail_multidomain.crt
smtpd_tls_key_file = /etc/ssl/private/mail_multidomain.key

# Option 2: Wildcard certificate (if domains share common root)
smtpd_tls_cert_file = /etc/ssl/certs/wildcard_domain.crt
smtpd_tls_key_file = /etc/ssl/private/wildcard_domain.key

# Option 3: SNI-based configuration (Postfix 2.3+)
smtpd_tls_cert_file = /etc/ssl/certs/%0.crt
smtpd_tls_key_file = /etc/ssl/private/%0.key

For completely separate domains, a multi-domain SAN certificate is the cleanest approach. Here's how to generate one using Let's Encrypt:

certbot certonly --standalone \
-d mail.xxx.com \
-d mail.yyy.com \
--preferred-challenges http

Then configure Postfix:

smtpd_tls_cert_file = /etc/letsencrypt/live/mail.xxx.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.xxx.com/privkey.pem

For larger deployments with many domains, Server Name Indication (SNI) allows dynamic certificate selection:

# Main configuration
smtpd_tls_cert_file = /etc/ssl/certs/default.crt
smtpd_tls_key_file = /etc/ssl/private/default.key

# SNI map file (/etc/postfix/sni_map)
mail.xxx.com /etc/ssl/certs/xxx.crt /etc/ssl/private/xxx.key
mail.yyy.com /etc/ssl/certs/yyy.crt /etc/ssl/private/yyy.key

# Postfix configuration
smtpd_tls_chain_files = ${default?} ${sni?}

Verify your configuration with:

openssl s_client -connect mail.xxx.com:25 -starttls smtp -servername mail.xxx.com
openssl s_client -connect mail.yyy.com:25 -starttls smtp -servername mail.yyy.com

Check for the correct certificate being presented in each case.

When using SAN certificates, be aware that:

  • The entire certificate chain is sent during TLS handshake
  • More domains in SAN means larger certificate size
  • Certificate revocation affects all domains

When running a Postfix server hosting multiple independent virtual domains (e.g., xxx.com and yyy.com), we face a certificate management challenge. Users typically configure their email clients using domain-specific mail server addresses (mail.xxx.com, mail.yyy.com), but all requests ultimately hit the same Postfix instance.

The optimal solutions depend on your budget and infrastructure constraints:

  • Multi-Domain (SAN) Certificate: A single certificate covering all mail.* domains
  • Wildcard Certificate: *.mydomain.com pattern (not suitable for completely separate domains)
  • Let's Encrypt with DNS Challenges: Free automated certificates for all domains

For most production environments, a multi-domain certificate (Subject Alternative Name) is the cleanest solution:

# Postfix main.cf configuration snippet
smtpd_tls_cert_file = /etc/ssl/certs/mail_multidomain.pem
smtpd_tls_key_file = /etc/ssl/private/mail_multidomain.key

For cost-effective management of multiple domains:

# Certbot command for multiple domains
certbot certonly --standalone \
  -d mail.xxx.com \
  -d mail.yyy.com \
  --preferred-challenges http \
  --agree-tos \
  --email admin@example.com

Postfix supports Server Name Indication for multiple certificates:

# In master.cf
submission inet n - - - - smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_cert_file=/etc/letsencrypt/live/mail.xxx.com/fullchain.pem
  -o smtpd_tls_key_file=/etc/letsencrypt/live/mail.xxx.com/privkey.pem
  -o smtpd_tls_exclude_ciphers=aNULL

# Duplicate for other domains with different cert paths

Ensure proper MX and PTR records for each domain:

; xxx.com zone file
mail.xxx.com.    IN    A    192.0.2.1
xxx.com.         IN    MX    10 mail.xxx.com.

; yyy.com zone file
mail.yyy.com.    IN    A    192.0.2.1
yyy.com.         IN    MX    10 mail.yyy.com.

Verify using openssl s_client:

openssl s_client -connect mail.xxx.com:587 -starttls smtp -servername mail.xxx.com
openssl s_client -connect mail.yyy.com:587 -starttls smtp -servername mail.yyy.com