Minimalistic Postfix mail server with TLS and relay support
8.7K
Lightweight Postfix mail relay with built-in DKIM signing, TLS support, and flexible delivery modes.
linux/amd64 and linux/arm64docker run -d --name postfix \
-e DOMAIN=example.com \
-e MAILNAME=mail.example.com \
-p 25:25 -p 587:587 \
-v dkim_keys:/etc/ssl/dkim \
01it/postfix:latest
On first startup, the container will:
Check logs for the DKIM public key:
docker logs postfix 2>&1 | grep -A2 "DKIM PUBLIC KEY"
Mail is delivered directly to recipient MX servers over port 25. This is the default when RELAY_HOST is not set.
Requirements:
Mail is forwarded through an external SMTP provider. Activated by setting RELAY_HOST.
environment:
- RELAY_HOST=[smtp.example.com]:587
- SMTP_USERNAME=your-username
- SMTP_PASSWORD=your-password
By default, only clients inside MY_NETWORKS may send mail. To let external
clients submit over port 587, provision SASL accounts with SMTP_AUTH_USERS:
environment:
- SMTP_AUTH_USERS=alice:s3cret,bob:hunter2
ports:
- "587:587"
Clients authenticate over STARTTLS with the bare username (e.g. alice) and
password. Accounts are re-provisioned from the environment on every start, so
update the variable and recreate the container to change credentials.
| Variable | Default | Description |
|---|---|---|
DOMAIN | example.com | Domain for DKIM signing and certificate generation |
MAILNAME | mail.example.com | Postfix hostname (myhostname) |
MY_NETWORKS | 127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 | Trusted networks allowed to relay |
MY_DESTINATION_DOMAINS | — | Additional local destination domains |
SMTP_AUTH_USERS | — | Submission (587) login accounts, user1:pass1,user2:pass2 |
| Variable | Default | Description |
|---|---|---|
DKIM_SELECTOR | mail | DKIM selector (used in DNS record name) |
DKIM_KEY_DIR | /etc/ssl/dkim | Directory for DKIM key storage |
DKIM_EXTRA_DOMAINS | — | Comma-separated extra domains to DKIM-sign (same key) |
| Variable | Default | Description |
|---|---|---|
RELAY_HOST | — | External SMTP relay (e.g., [smtp.gmail.com]:587) |
SMTP_USERNAME | — | Relay authentication username |
SMTP_PASSWORD | — | Relay authentication password |
FALLBACK_RELAY_HOST | — | Fallback relay when primary delivery fails (e.g., [backup-smtp.example.com]:587) |
FALLBACK_SMTP_USERNAME | — | Fallback relay authentication username |
FALLBACK_SMTP_PASSWORD | — | Fallback relay authentication password |
| Variable | Default | Description |
|---|---|---|
LETSENCRYPT_EMAIL | — | Enables Let's Encrypt; email for account registration |
LETSENCRYPT_EXTRA_DOMAINS | — | Comma-separated extra domains for the certificate (SANs) |
SSL_COUNTRY | US | Self-signed certificate country |
SSL_STATE | State | Self-signed certificate state |
SSL_LOCALITY | City | Self-signed certificate locality |
SSL_ORGANIZATION | Organization | Self-signed certificate organization |
SSL_ORGANIZATIONAL_UNIT | IT | Self-signed certificate OU |
Any Postfix directive can be set via POSTFIX_ prefix:
environment:
- POSTFIX_message_size_limit=52428800
- POSTFIX_smtp_helo_name=mail.example.com
For reliable mail delivery, configure these DNS records for your domain:
Your server's IP must have a PTR record matching MAILNAME. Set this at your hosting provider.
203.0.113.1 → mail.example.com
Authorizes your server to send mail for your domain.
example.com. IN TXT "v=spf1 mx ip4:203.0.113.1 -all"
The container prints the DKIM public key on first startup. Add it as a TXT record:
mail._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=<PUBLIC_KEY>"
Replace mail with your DKIM_SELECTOR if different.
Controls how receivers handle authentication failures.
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:[email protected]"
For production use, real TLS certificates improve deliverability. Set LETSENCRYPT_EMAIL to enable:
environment:
- [email protected]
- DOMAIN=example.com
ports:
- "80:80" # Required for HTTP-01 challenge
- "25:25"
- "587:587"
volumes:
- letsencrypt:/etc/letsencrypt
Certificates are issued with acme.sh (HTTP-01, standalone), so port 80 must be accessible from the internet during issuance. Mount the letsencrypt volume to persist the acme.sh account and certificates across restarts. If issuance fails, the container falls back to self-signed certificates.
| Volume | Path | Description |
|---|---|---|
postfix_data | /var/spool/postfix | Mail queue and spool data |
postfix_certs | /etc/ssl/postfix | Self-signed TLS certificates |
dkim_keys | /etc/ssl/dkim | DKIM private/public key pair |
letsencrypt | /etc/letsencrypt | Let's Encrypt certificates (optional) |
| Port | Protocol | Description |
|---|---|---|
| 25 | SMTP | Standard mail delivery (direct mode) and receiving |
| 587 | Submission | Authenticated submission with STARTTLS |
Most cloud providers block outbound port 25 by default:
If port 25 is blocked, use relay mode with an external SMTP provider.
SMTP_AUTH_USERS); otherwise submission is restricted to MY_NETWORKSAll logs go to stdout:
docker logs -f postfix
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
Content type
Image
Digest
sha256:4ad4f08f5…
Size
488 Bytes
Last updated
about 10 hours ago
docker pull 01it/postfix:sha256-aed04dc86fe6a9a76c57b30a3c7e00200c09fa82694540d524ac34ab6396452b.sig