Generate a CSR with Subject Alternative Names
To generate a CSR with Subject Alternative Names, run `openssl req -new -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csr -subj "/CN=example.com" -addext "subjectAltName=DNS:example.com,DNS:www.example.com"`. The `-addext` flag requires OpenSSL 1.1.1 or later; on older versions you must supply the extension through a config file instead. Every hostname the certificate needs to cover must appear in the SAN list, including the one already in the Common Name, because browsers have ignored the Common Name for hostname matching since Chrome 58.
The command #
openssl req -new \
-newkey rsa:2048 -nodes -keyout example.com.key \
-out example.com.csr \
-subj "/C=US/ST=California/L=San Francisco/O=Example Inc/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com" This writes two files: an unencrypted private key and the CSR you send to the CA.
Replace these values
| Placeholder | What to put there |
|---|---|
example.com.key | The new private key. Never send this to anyone, including the CA. |
example.com.csr | The certificate signing request. This is the file you submit. |
-nodes | Leaves the private key unencrypted. Required if a web server must start unattended. |
/C=..., /ST=..., /O=... | Country, state and organisation. Public CAs verify these for OV and EV certificates. |
/CN=example.com | Common Name. Keep it as the primary hostname, but the SAN list is what actually matters. |
Adding more hostnames #
subjectAltName takes a comma-separated list. There is no practical limit for an internal CA, though public CAs cap it (typically at 100 names):
openssl req -new -newkey rsa:2048 -nodes \
-keyout example.com.key -out example.com.csr \
-subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com,DNS:api.example.com,DNS:*.staging.example.com" A wildcard such as *.staging.example.com matches exactly one label. It covers a.staging.example.com but not staging.example.com itself and not a.b.staging.example.com, so list the apex separately when you need both.
Using an EC key instead #
ECDSA keys are smaller and faster than RSA at equivalent strength, and P-256 is universally supported:
openssl req -new \
-newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \
-keyout example.com.key -out example.com.csr \
-subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com" On OpenSSL 1.0.2 — the config file method #
-addext does not exist before OpenSSL 1.1.1. Older versions need the extension supplied through a config file. This method also works on every newer version, so it is the portable choice for scripts you cannot pin:
[ req ]
default_bits = 2048
prompt = no
distinguished_name = dn
req_extensions = req_ext
[ dn ]
C = US
ST = California
L = San Francisco
O = Example Inc
CN = example.com
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = api.example.com openssl req -new -newkey rsa:2048 -nodes \
-keyout example.com.key -out example.com.csr \
-config csr.conf Always verify before you submit #
A CSR with missing SANs produces a certificate that fails in browsers, and you will not find out until after issuance. Check first:
openssl req -in example.com.csr -noout -text Expected output
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = US, ST = California, L = San Francisco, O = Example Inc, CN = example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
Signature Algorithm: sha256WithRSAEncryption For a one-line check in CI:
openssl req -in example.com.csr -noout -text | grep -A1 "Subject Alternative Name" If that prints nothing, the extension is absent — go back and check your OpenSSL version or your config section names.
Confirm the key matches #
The CSR and the key are only useful together. These two commands must print the same hash:
openssl req -in example.com.csr -noout -pubkey | openssl sha256
openssl pkey -in example.com.key -pubout | openssl sha256 Frequently asked questions
- Do I still need to set the Common Name?
- Set it, but do not rely on it. Every current browser matches hostnames against the SAN extension only and ignores the Common Name entirely, a change Chrome made in version 58. Most public CAs still require a CN and will copy it into the SAN list, but you should list it explicitly rather than depend on that.
- Why is my -addext argument being ignored?
-addextwas added in OpenSSL 1.1.1. On 1.0.2 the flag is silently unrecognised in some builds and produces a CSR with no extensions at all. Runopenssl versionand use the config-file method below if you are on anything older.- Can I put an IP address in a SAN?
- Yes, with the
IP:prefix, as in-addext "subjectAltName=DNS:example.com,IP:192.0.2.10". Public CAs will not issue for private IP ranges, so in practice this is only useful for an internal CA. - Does the CA have to honour my SAN list?
- No. The CSR is a request. The CA decides what goes into the issued certificate, and it will drop any hostname you have not proven control of. Always inspect the issued certificate rather than assuming it matches the CSR.
References
- openssl-req(1) — -addext, which is how a SAN reaches the request
- RFC 6125: service identity in TLS — why the common name stopped being authoritative for hostnames