This guide shows you how to generate a CSR (Certificate Signing Request) on Postfix using the OpenSSL command line. Postfix itself does not generate keys or CSRs; it consumes the files OpenSSL produces and references them from /etc/postfix/main.cf. You run a single command that creates two files at once: a private key that stays on the server, and the CSR you submit to your Certificate Authority (CA).
The CSR encodes the hostname your MTA presents on STARTTLS, your organization details, and the public half of the key. The matching private key never leaves the server. If you lose it, the issued certificate becomes unusable and you have to start over.
Prerequisites
- Root or sudo access to the server running Postfix.
- OpenSSL installed. It ships in the base system on every mainstream Linux distribution; check with
openssl version. - The fully qualified mail hostname you want on the certificate, for example mail.example.com. This must match the MX record clients connect to over STARTTLS, not the bare apex domain.
Step 1: Prepare a directory for the key and CSR
Keep the Postfix TLS material in its own directory under /etc/postfix/ so the permissions are easy to manage. Create it and lock it down to root:
sudo mkdir -p /etc/postfix/ssl
sudo chmod 700 /etc/postfix/ssl
cd /etc/postfix/ssl
You will generate the key and CSR inside this directory, then reference them from main.cf after the CA issues the certificate.
Step 2: Generate the private key and CSR
Run the command below. It creates the private key and the CSR in one step and includes the Subject Alternative Name (SAN) that modern browsers, mail clients, and CAs require. The SAN must list the mail hostname (the one your MX record points to), not the bare apex domain:
sudo openssl req -new -newkey rsa:2048 -nodes \
-keyout /etc/postfix/ssl/mail.example.com.key \
-out /etc/postfix/ssl/mail.example.com.csr \
-subj "/C=US/ST=YourState/L=YourCity/O=YourCompany/CN=mail.example.com" \
-addext "subjectAltName=DNS:mail.example.com"
Here is what each part does:
- req -new creates a new certificate signing request.
- -newkey rsa:2048 generates a new 2048-bit RSA private key. 2048 bits is the current minimum for public certificates; you can use rsa:4096 for a larger key.
- -nodes leaves the private key unencrypted (no passphrase), so Postfix can load it on boot without prompting.
- -keyout writes the private key. Keep this file private and never send it to anyone, including the CA.
- -out writes the CSR you submit to the CA.
- -subj fills in the subject fields inline so the command runs without interactive prompts. Set CN (Common Name) to your mail hostname.
- -addext “subjectAltName=…” adds the SAN entry. CAs issue against the SAN list, so the mail hostname must appear here.
Replace mail.example.com with the real hostname clients connect to (often the same name as your MX record), and edit the -subj values to match your organization. The two-letter country code (C) must be uppercase, for example US or GB. For a domain-validated (DV) certificate, the organization fields are not verified, but the command still needs valid values. Modern OpenSSL signs the CSR with SHA-256 by default, which is what every public CA requires.
If you prefer to fill in the fields interactively instead of with -subj, drop that line and OpenSSL will prompt you for each value:
sudo openssl req -new -newkey rsa:2048 -nodes \
-keyout /etc/postfix/ssl/mail.example.com.key \
-out /etc/postfix/ssl/mail.example.com.csr \
-addext "subjectAltName=DNS:mail.example.com"
When prompted, leave the challenge password and optional company name blank by pressing Enter. CAs ignore those fields, and a challenge password causes problems later.
Covering more than one hostname
If the same Postfix instance answers on more than one name (for example, both mail.example.com and smtp.example.com, or a shared certificate for mail and webmail), list every hostname in the SAN value, separated by commas:
-addext "subjectAltName=DNS:mail.example.com,DNS:smtp.example.com,DNS:webmail.example.com"
The Common Name should still be the primary mail hostname. Adding the bare apex domain to the SAN is only useful if mail clients ever connect to it directly; if your MX record points to a sub-hostname, you do not need the apex on the certificate.
Prefer an ECDSA key?
ECDSA keys are smaller and faster than RSA at the same security level and are supported by every current mail client and CA. To generate a P-256 (prime256v1) key and CSR instead, swap the -newkey argument:
sudo openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \
-keyout /etc/postfix/ssl/mail.example.com.key \
-out /etc/postfix/ssl/mail.example.com.csr \
-subj "/C=US/ST=YourState/L=YourCity/O=YourCompany/CN=mail.example.com" \
-addext "subjectAltName=DNS:mail.example.com"
Step 3: Protect the private key
Lock the private key down so only root can read it. Postfix opens its TLS material before dropping privileges, so root ownership and mode 600 are both correct and required:
sudo chown root:root /etc/postfix/ssl/mail.example.com.key
sudo chmod 600 /etc/postfix/ssl/mail.example.com.key
The CSR file is not secret (it contains only the public key and your subject details), but keeping it in the same locked-down directory keeps the layout tidy.
Step 4: Verify the CSR
Before you submit the request, confirm it contains the right hostname and SAN and that its signature is valid. This command prints the decoded contents and checks the signature locally:
openssl req -noout -text -verify -in /etc/postfix/ssl/mail.example.com.csr
Look for verify OK in the output, check that the Subject line shows your mail hostname as the Common Name, and confirm the X509v3 Subject Alternative Name section lists every hostname you expect. If a SAN is missing, regenerate the CSR with the correct -addext value: a CA cannot add hostnames after issuance. You can also paste the CSR into our online CSR Decoder to check these fields in a browser.
Step 5: Submit the CSR
Open the CSR file and copy its entire contents, including the BEGIN and END lines:
cat /etc/postfix/ssl/mail.example.com.csr
The block looks like this. Copy everything from the first line to the last, including the five hyphens on each side of the BEGIN and END markers:
-----BEGIN CERTIFICATE REQUEST-----
MIIC...base64-encoded data...AB
-----END CERTIFICATE REQUEST-----
Paste that block into your SSL order form. After the CA validates the CSR and issues the certificate, follow our Postfix SSL installation instructions to deploy it. Keep the .key file on the server: you need it together with the issued certificate to serve STARTTLS, and you must never send it to the CA or anyone else.
If you would rather not use the command line, build the request with our CSR Generator and paste the result into your order. The generator returns a matching private key that you place at the same path on the server.
Where the files go in Postfix
For context, this is how the files you just generated are wired into Postfix once the CA returns the certificate and intermediate (CA bundle). On Postfix 3.4 and newer, the recommended single-directive form takes one PEM file that contains the private key followed by the full certificate chain:
cat mail.example.com.key mail.example.com.crt intermediate.pem \
> /etc/postfix/ssl/mail.example.com.chain.pem
sudo chmod 600 /etc/postfix/ssl/mail.example.com.chain.pem
Then in /etc/postfix/main.cf:
smtpd_tls_chain_files = /etc/postfix/ssl/mail.example.com.chain.pem
smtpd_tls_security_level = may
On Postfix older than 3.4, use the legacy pair of directives, with the key and a full-chain certificate kept in separate files:
smtpd_tls_cert_file = /etc/postfix/ssl/mail.example.com.fullchain.crt
smtpd_tls_key_file = /etc/postfix/ssl/mail.example.com.key
smtpd_tls_security_level = may
The full install walk-through, including the submission service on port 587 and verification with OpenSSL, lives in our Postfix SSL installation guide.
Generate a CSR on other mail platforms
Running a different mail server or gateway? See our other CSR guides:
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


