bg-tutorials

How to Install an SSL Certificate on Qmail

This tutorial shows you how to install an SSL/TLS certificate on Qmail, the mail transfer agent originally written by D. J. Bernstein. The process is the same one Qmail has used for years: build a single PEM file that contains the private key, your server certificate, and the intermediate chain, drop it at /var/qmail/control/servercert.pem, and restart Qmail.

Before you start: Qmail is a legacy MTA

Qmail itself has not been updated since the original qmail-1.03 release in 1998. D. J. Bernstein placed the code in the public domain in 2007 but did not resume development. The well-known community fork netqmail reached its final 1.06 release in 2007 and has been unmaintained for over a decade. The active modern successor is notqmail (current release 1.09, May 2024), which carries forward bug fixes and modern-system compatibility while staying drop-in compatible with the original.

Just as important for this guide: stock qmail has no native SSL/TLS support. TLS is added by one of two third-party paths:

  • The qmail-tls patch by Frederik Vermeulen, which adds STARTTLS to qmail-smtpd and reads the certificate from a hardcoded path: /var/qmail/control/servercert.pem. Most modern qmail packages (including netqmail and notqmail builds, the s/qmail distribution, and many vendor packages) ship this patch or an equivalent.
  • stunnel in front of qmail-smtpd to wrap the connection in TLS on port 465 (SMTPS). This works with any qmail build because the TLS termination happens outside Qmail.

If you maintain an existing qmail deployment, the steps below still apply. If you are building a new mail server from scratch, consider Postfix or OpenSMTPD instead: both have native, well-maintained TLS support and active security teams. We have a separate tutorial on how to install an SSL certificate on Postfix.

Generate a CSR code for Qmail

If you have already generated your CSR and received the SSL files from your CA, skip ahead to Install the SSL certificate on Qmail.

CSR stands for Certificate Signing Request: a block of encoded text that contains your domain and organization details. You submit it to the Certificate Authority (CA) so it can validate your request and issue the certificate. Generating the CSR also creates the matching private key, which stays on your server and is required for installation. You have two options:

Open the CSR file in any plain text editor and copy the entire block, including the BEGIN CERTIFICATE REQUEST and END CERTIFICATE REQUEST lines, into the CSR field of your order form. Keep the private key file safe: you will merge it into the PEM file in the next section.

Install the SSL certificate on Qmail

After validation, the CA emails you a ZIP archive with your SSL files: the primary (server) certificate and one or more intermediate (CA) certificates. Extract the archive on your server, then follow the steps below.

Step 1: Combine the key, certificate, and chain into one PEM file

The qmail-tls patch (and the equivalents in netqmail, notqmail, and s/qmail) reads everything it needs to terminate TLS from one PEM file. Concatenate the files in this order: your private key first, then your server certificate, then the intermediate (CA) chain. The root certificate is not required (clients already trust it). From the directory holding your extracted files, run:

cat yourdomain.key yourdomain.crt yourdomain.ca-bundle > servercert.pem

If your CA delivered the intermediates as separate files instead of a single .ca-bundle, list each one after the server certificate, leaf first and root-issuing intermediate last:

cat yourdomain.key yourdomain.crt intermediate1.crt intermediate2.crt > servercert.pem

Open the resulting file in a text editor to confirm the structure. It should look like this, with real five-hyphen markers around each block:

-----BEGIN RSA PRIVATE KEY-----
(the text of your private key)
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
(the text of your primary SSL certificate)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(the text of the intermediate CA certificate)
-----END CERTIFICATE-----

Newer keys may be labeled BEGIN PRIVATE KEY instead of BEGIN RSA PRIVATE KEY; either is fine. The key must not be encrypted with a passphrase, because qmail-smtpd loads it at startup without prompting. If your CA issued an ECDSA certificate, the key block will be BEGIN EC PRIVATE KEY; nothing else changes.

Step 2: Move the file to Qmail’s control directory

The file name and path are fixed by the qmail-tls patch. Move the combined PEM into Qmail’s control directory and tighten its permissions, because it contains your private key:

sudo mv servercert.pem /var/qmail/control/servercert.pem
sudo chmod 600 /var/qmail/control/servercert.pem
sudo chown root:qmail /var/qmail/control/servercert.pem

The owner and group depend on which user runs qmail-smtpd on your system. On a stock netqmail or notqmail install that is usually qmaild or the qmail group, so root:qmail with mode 600 works. On a vpopmail-based setup, qmail-smtpd runs as vpopmail, so use:

sudo chown vpopmail:vchkpw /var/qmail/control/servercert.pem
sudo chmod 640 /var/qmail/control/servercert.pem

Either way, the goal is the same: the qmail-smtpd process must be able to read the file, and nothing else should.

Step 3: Adjust for custom builds

Most qmail flavors look in the default location, but a few use environment variables instead. Match your build:

  • Stock qmail with the qmail-tls patch (netqmail / notqmail / vendor packages): no further configuration is needed. qmail-smtpd reads /var/qmail/control/servercert.pem automatically. To make qmail-smtpd advertise STARTTLS in the EHLO response, the UCSPITLS environment variable must be set in the qmail-smtpd run script (typically /var/qmail/supervise/qmail-smtpd/run): export UCSPITLS=”” before the qmail-smtpd line. To require encryption before authentication, also set FORCE_TLS=1.
  • s/qmail with ucspi-ssl: the certificate path is not hardcoded. Set these environment variables in your qmail-smtpd run script (or in the matching tcpserver / sslserver wrapper): CERTFILE for the server certificate, KEYFILE for the private key (these can point to the same combined PEM), and CERTCHAINFILE for the intermediates. See the s/qmail documentation for the exact directive names in your version.
  • stunnel front-end (SMTPS on port 465): point stunnel’s cert directive at /var/qmail/control/servercert.pem and have its exec launch qmail-smtpd. This path does not need the qmail-tls patch at all; TLS terminates at stunnel.

If you do not know which patch your qmail-smtpd was built with, check the binary:

strings /var/qmail/bin/qmail-smtpd | grep -iE 'tls|starttls|servercert'

If you see references to STARTTLS, servercert.pem, or UCSPITLS, the binary has the qmail-tls patch compiled in.

Step 4: Restart Qmail

Qmail reads the certificate at process start, so a restart of qmail-smtpd is required. On most installations that use the supplied control scripts:

sudo qmailctl restart

If your distribution wraps Qmail in a systemd service instead, use:

sudo systemctl restart qmail

On a daemontools / runit setup, send qmail-smtpd a TERM through svc instead:

sudo svc -t /service/qmail-smtpd

Watch the log (typically /var/log/qmail/smtpd/current) for errors during startup. A misformatted PEM or wrong ownership is the most common reason qmail-smtpd refuses to enable TLS.

Test your SSL installation

Confirm Qmail is offering STARTTLS and serving the correct certificate with OpenSSL. Replace mail.yourdomain.com with your mail server hostname:

openssl s_client -starttls smtp -connect mail.yourdomain.com:25 -servername mail.yourdomain.com </dev/null \
| openssl x509 -noout -issuer -subject -dates

The output should print your certificate’s subject (common name), issuer (the CA), and validity dates. If you set up SMTPS through stunnel on port 465 instead, drop -starttls smtp and connect to port 465 directly:

openssl s_client -connect mail.yourdomain.com:465 -servername mail.yourdomain.com

Look for Verify return code: 0 (ok) at the bottom of the handshake. If you see a chain error, the intermediate certificates are missing from servercert.pem: append them and restart qmail-smtpd. For a full report on the certificate, chain, and protocol support, run our SSL Checker against your mail hostname.

Frequently Asked Questions

Where does Qmail read the SSL certificate from?

From the file /var/qmail/control/servercert.pem. That path is hardcoded in the qmail-tls patch that adds STARTTLS to qmail-smtpd, and the same path is used by every common qmail flavor (netqmail, notqmail, vendor packages). The file must contain the private key, the server certificate, and the intermediate chain, in that order. s/qmail with ucspi-ssl is the exception: it reads CERTFILE, KEYFILE, and CERTCHAINFILE environment variables instead.

In what order do I put the files in servercert.pem?

Private key first, then the server (leaf) certificate, then the intermediate CA certificate(s). The root certificate is not required, because mail clients already trust it. A one-line build is enough:
cat yourdomain.key yourdomain.crt yourdomain.ca-bundle > servercert.pem
If the order is wrong, qmail-smtpd will fail to load the certificate at startup and TLS will not be offered. Check the log under /var/log/qmail/smtpd/ if you suspect this.

Does stock qmail support TLS?

Not by itself. The original qmail-1.03 release from 1998 has no SSL or TLS support. TLS is added either by the qmail-tls patch (compiled into the qmail-smtpd binary, adds STARTTLS on ports 25 and 587) or by running stunnel in front of qmail-smtpd for SMTPS on port 465. Almost every modern qmail package ships with the qmail-tls patch already applied, so you usually do not need to patch the source yourself.

Is Qmail still maintained?

The original Qmail (qmail-1.03) has not been updated since 1998. The first community fork, netqmail, made its last release (1.06) in 2007. The active modern successor is notqmail, which released version 1.09 in May 2024 and continues to ship bug fixes and modern-system compatibility patches. For new mail servers, most operators choose Postfix or OpenSMTPD instead, both of which have native and actively maintained TLS support.

Why does qmail-smtpd start but not offer STARTTLS?

Three common causes. First, the UCSPITLS environment variable is not exported in the qmail-smtpd run script: set UCSPITLS=”” (the value can be empty) before the qmail-smtpd line and restart the service. Second, the qmail-smtpd binary was built without the qmail-tls patch: confirm with strings /var/qmail/bin/qmail-smtpd | grep -i tls. Third, /var/qmail/control/servercert.pem is missing, unreadable to the qmail-smtpd user, or malformed; check permissions and the order of the PEM blocks.

How do I verify the certificate after restarting Qmail?

Connect to the SMTP port with OpenSSL and read the certificate Qmail presents over STARTTLS:
openssl s_client -starttls smtp -connect mail.yourdomain.com:25 -servername mail.yourdomain.com </dev/null \ | openssl x509 -noout -issuer -subject -dates
This prints the subject, issuer, and validity dates. For SMTPS through stunnel on port 465, drop the -starttls smtp flag. Confirm the issuer matches your CA and the handshake ends with Verify return code: 0 (ok).

Save 10% on SSL Certificates when ordering from SSL Dragon today!

Fast issuance, strong encryption, 99.99% browser trust, dedicated support, and 25-day money-back guarantee. Coupon code: SAVE10

A detailed image of a dragon in flight
Written by

I've been writing for SSL Dragon for over 10 years, focusing entirely on SSL certificates and digital security. My job is to take complex cybersecurity topics and strip away the jargon, making sure you get the clear, practical information you need to keep your website safe.