Last update: Nov 2025.
Attention: this is the key used to sign the certificate requests, anyone holding this can sign certificates on your behalf. So keep it in a safe place!
openssl ecparam -genkey -name secp384r1 | openssl ec -aes256 -out rootCA.keyopenssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crtHere we used our root key to create the root certificate that needs to be distributed in all the computers that have to trust us.
This procedure needs to be followed for each server/appliance that needs a trusted certificate from our CA
openssl ecparam -genkey -name prime256v1 -noout -out mydomain.com.key
The certificate signing request is where you specify the details for the certificate you want to generate. This request will be processed by the owner of the Root key (you in this case since you create it earlier) to generate the certificate.
Important: Please mind that while creating the signing request it is important to specify the Common Name providing the IP address or domain name for the service, otherwise the certificate cannot be verified.
Important: Modern browsers and clients require Subject Alternative Names (SANs). The Common Name alone is no longer sufficient.
I will describe here two ways to generate the csr
If you generate the csr in this way, openssl will ask you questions about the certificate to generate like the organization details and the Common Name (CN) that is the web address you are creating the certificate for, e.g mydomain.com.
openssl req -new -key mydomain.com.key -out mydomain.com.csr
This method generates the same output as Method A but it's suitable for use in your automation :) .
openssl req -new -sha256 -key mydomain.com.key -subj "/C=US/ST=CA/O=MyOrg, Inc./CN=mydomain.com" -out mydomain.com.csr
If you need to pass additional config you can use the -config parameter, here for example I want to add alternative names to my certificate.
openssl req -new -sha256 \
-key mydomain.com.key \
-subj "/C=US/ST=CA/O=MyOrg, Inc./CN=mydomain.com" \
-reqexts SAN \
-config <(cat /etc/ssl/openssl.cnf \
<(printf "\n[SAN]\nsubjectAltName=DNS:mydomain.com,DNS:www.mydomain.com")) \
-out mydomain.com.csr
openssl req -in mydomain.com.csr -noout -text
Important: Modern certificates require Subject Alternative Names (SANs) to be included during signing, not just in the CSR.
Create an extensions file (mydomain.com.ext):
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = mydomain.com
DNS.2 = www.mydomain.com
Then sign the certificate:
openssl x509 -req -in mydomain.com.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out mydomain.com.crt -days 397 -sha256 -extfile mydomain.com.ext
Note: 397 days is the maximum validity now accepted by major browsers. For internal use, you may use longer periods (e.g., -days 825), but shorter validity is recommended.
openssl x509 -in mydomain.com.crt -text -noout
Check that the Subject Alternative Names are present:
openssl x509 -in mydomain.com.crt -noout -ext subjectAltName

some may require the certificate contain
extendedKeyUsage=serverAuth, the sign command needs some more attributes: