Configure and Verify Postfix tlsproxy for STARTTLS
You will configure the Postfix TLS proxy through main.cf, check which certificate and policy it will actually use, reload the daemon, and test STARTTLS from a client. tlsproxy is an internal Postfix service: normally you do not start it by hand or pass it a listening port.
The route
Jump straight to the step you need, or tick off Done means at the end.
The examples use Postfix 3.8.6 from the installed package. Allow about twenty minutes, plus a maintenance window if this is a production mail service. You need root or equivalent privilege for configuration and reload commands, a certificate and private key already deployed on the host, and a hostname and port at which Postfix accepts SMTP connections.
Security boundary
Tlsproxy handles untrusted network clients and private key material. Do not paste private keys into a shell, loosen their permissions to make a test pass, or reload a production MTA without checking the proposed values first.
1. Confirm the installed service and version
Start with read-only checks. These ordinary commands do not need sudo:
$ command -v postconf
/usr/sbin/postconf
$ postconf mail_version
mail_version = 3.8.6
$ postconf -M | rg '^tlsproxy' || echo 'no tlsproxy entry in active master.cf'
no tlsproxy entry in active master.cf
The service line depends on the local master.cf. This host has no active tlsproxy entry, so the command reports that fact. If your Postfix configuration is meant to use tlsproxy, inspect the package's master.cf and the active config_directory before changing anything. The important point is that Postfix master normally owns the tlsproxy process.
Checkpoint: record the reported version and whether the service is enabled. Do not infer the running configuration from a different Postfix installation or from a copied manpage.
2. Inspect the values tlsproxy inherits
The server-side tlsproxy settings are clones of the SMTP server settings. On a new configuration, values such as the certificate, private key and TLS security level commonly resolve through $smtpd_... parameters. Ask Postfix for both the effective value and the built-in default:
$ for p in tlsproxy_tls_security_level tlsproxy_tls_cert_file tlsproxy_tls_key_file tlsproxy_watchdog_timeout; do
> printf '%s = ' "$p"
> postconf -h "$p"
> done
tlsproxy_tls_security_level = $smtpd_tls_security_level
tlsproxy_tls_cert_file = $smtpd_tls_cert_file
tlsproxy_tls_key_file = $smtpd_tls_key_file
tlsproxy_watchdog_timeout = 10s
These are parameter expressions, not proof that the referenced SMTP settings contain usable files. Resolve the chain explicitly:
$ postconf -h smtpd_tls_security_level smtpd_tls_cert_file smtpd_tls_key_file
<your configured security level>
<your certificate path>
<your private-key path>
Your output will be host-specific. On this machine the paths point to the deployed certificate for server.dixon.cx. An empty certificate path is not a reason to invent one: establish where your certificate deployment puts the files and whether the Postfix service account can access them after the master process has loaded them.
3. Choose the server TLS policy deliberately
Set only the tlsproxy-specific values that need to differ from the SMTP server. For example, this gives the proxy an explicit server certificate, key and mandatory TLS policy:
# sudo postconf -e 'tlsproxy_tls_cert_file=/etc/postfix/tls/mail.example.test.fullchain.pem'
# sudo postconf -e 'tlsproxy_tls_key_file=/etc/postfix/tls/mail.example.test.key.pem'
# sudo postconf -e 'tlsproxy_tls_security_level=encrypt'
encrypt means that TLS is required for the tlsproxy server role. If your deployment intentionally uses opportunistic encryption, use the policy chosen for that design and verify it against your organisation's mail requirements. Do not copy encrypt into a live system without considering clients that cannot use STARTTLS.
Postfix can load the key before dropping privileges, so the key file can remain readable only by root. Keep ownership and mode restrictive:
# sudo stat -c '%U:%G %a %n' /etc/postfix/tls/mail.example.test.key.pem
root:root 600 /etc/postfix/tls/mail.example.test.key.pem
If the certificate and key are managed by another service, use its supported renewal and permission mechanism. Do not replace a key manually while a renewal process may be writing the same path.
4. Validate before reloading
Check the resulting values and ask Postfix to validate its configuration. These commands do not open a listener or alter the service:
$ postconf -h tlsproxy_tls_security_level tlsproxy_tls_cert_file tlsproxy_tls_key_file
encrypt
/etc/postfix/tls/mail.example.test.fullchain.pem
/etc/postfix/tls/mail.example.test.key.pem
# sudo postfix check
# echo $?
0
postfix check can report missing files, ownership problems and other configuration errors. Treat any non-zero result as a stop. Check the path, file format and permissions, then rerun the command. Do not solve a permission error with chmod 644 on a private key.
Recovery before reload: if you changed a parameter and decide not to keep the override, remove that override and let the inherited value apply again:
# sudo postconf -X tlsproxy_tls_security_level
# sudo postconf -X tlsproxy_tls_cert_file
# sudo postconf -X tlsproxy_tls_key_file
Use postconf -X only for parameters you deliberately set. Save the previous output if you need to restore an intentional local value rather than remove it.
5. Reload Postfix and check the logs
Reloading affects the running mail service. Once the checks pass, apply the configuration:
# sudo postfix reload
tlsproxy processes may live for a while under load, so a change to main.cf is not necessarily visible to every existing process immediately. The manpage recommends postfix reload to speed up adoption. Watch the Postfix log using the logging facility configured on your host:
$ sudo journalctl -u postfix --since '5 minutes ago' --no-pager
# or, on a syslog-based host:
$ sudo tail -n 50 /var/log/mail.log
Look for certificate-loading errors, TLS handshake failures and permission errors. The exact log destination is host-dependent; tlsproxy reports problems through syslogd or postlogd.
6. Test the live SMTP STARTTLS path
Run this from a client that can reach the SMTP listener. It is an ordinary client test, but it creates a real network connection to the mail service:
$ openssl s_client -starttls smtp \
> -connect mail.example.test:25 \
> -servername mail.example.test \
> -crlf
CONNECTED(00000003)
...
New, TLSv1.3, Cipher is ...
...
250 ...
Do not treat the placeholder output as exact: OpenSSL, the negotiated protocol and the server greeting vary. The useful checks are that the connection reaches the expected host, STARTTLS completes, and the presented certificate names the hostname you used. If you need certificate verification, add the CA options appropriate to your trust store rather than ignoring verification errors.
A successful TLS handshake does not prove that every Postfix SMTP policy is correct. Confirm the effective values, inspect the logs, and test from the network paths your clients actually use. If the test fails after a reload, compare the configured paths with postconf -h, verify the key and certificate match, and read the first relevant log error rather than repeatedly reloading.
Done means
- Postfix reports the expected installed version and a managed
tlsproxyservice. - The effective certificate, key and TLS policy were checked with
postconf -h. postfix checkreturned status 0 before the reload.- The private key remains protected and was not made world-readable for troubleshooting.
- Postfix was reloaded deliberately, and its logs show no new tlsproxy or TLS errors.
- A real SMTP client completed STARTTLS and received the expected certificate.