Skip to main content

How to Create a Certificate Authority with openssl

· 4 min read
Jagdish Kumawat
Founder @ Dewiride

A certificate authority is just a certificate that's allowed to sign others, plus its private key. For servers on your own network, one openssl command makes a private one. The part people get wrong is marking it as a CA, so this states that in the command.

What You Need​

Docker, for the commands below: they run OpenSSL from the mysql:9.7 image, so they're the same on macOS, Linux and Windows. If you have OpenSSL installed, drop the docker run … part and use the rest.

Make a folder for the files, and run everything from the folder above it:

Terminal
mkdir certs

Step 1: Create the CA​

${PWD} means your current folder, in bash, zsh and PowerShell alike:

Terminal
docker run --rm -v "${PWD}/certs:/certs" -w /certs mysql:9.7 openssl req -x509 -newkey rsa:2048 -nodes -days 3650 -keyout ca-key.pem -out ca.pem -subj "/CN=Inventory Demo CA" -addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"

The Docker part runs a throwaway container (--rm), shares certs with it (-v), and starts in that folder (-w). The OpenSSL part:

OptionWhat it does
req -x509Makes a self-signed certificate directly, without a separate request
-newkey rsa:2048Creates a new 2,048-bit RSA key to go with it
-nodesDoesn't encrypt the key with a passphrase. Remove it if a person will always be there to type one
-days 3650Valid for about 10 years
-keyout, -outWhere to write the key and the certificate
-subj "/CN=…"The CA's name. It must differ from the name on the certificates it signs
-addext "basicConstraints=critical,CA:TRUE"Marks it as a CA
-addext "keyUsage=…"Allows it to sign certificates and revocation lists

I learned about the -addext lines the hard way. Without them, whether you get a CA depends on the computer's openssl.cnf, and with an empty configuration I got a certificate that couldn't sign anything.

Step 2: Check It​

Terminal
docker run --rm -v "${PWD}/certs:/certs" -w /certs mysql:9.7 openssl x509 -in ca.pem -noout -subject -ext basicConstraints,keyUsage
Output
subject=CN=Inventory Demo CA
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Certificate Sign, CRL Sign

The new CA's subject, Basic Constraints of CA and Key Usage of Certificate Sign and CRL Sign.

Step 3: Keep the Two Files Apart​

You now have two files, and they need opposite treatment:

  • ca.pem is public. Give it to every client that needs to check your servers.
  • ca-key.pem is the secret. Anyone holding it can sign a certificate that your clients will trust. Keep it off your servers, and out of Git. If you only sign a few certificates a year, keep it offline.

Cost​

OpenSSL and the MySQL image are free. A private CA is trusted only by clients you give ca.pem to, which is what you want for an internal database. A public website needs a public CA instead.

Common Mistakes​

MistakeWhat happensDo this instead
Leaving out basicConstraintsinvalid CA certificate, on some computersState it in the command
Using the same CN for the CA and the serverMySQL's manual warns that it doesn't workGive each its own name
Putting ca-key.pem on a serverA stolen server can sign anythingKeep it separate
Committing the folder to GitThe key is out for goodAdd certs/ to .gitignore

Troubleshooting​

SymptomLikely causeFix
On Linux, the files belong to rootThe container runs as rootsudo chown them to your account
The CA doesn't sign what you expectedreq -x509 used the wrong key fileCheck -keyout, and keep each CA in its own folder

Conclusion​

One openssl req -x509 command makes a CA. State basicConstraints=critical,CA:TRUE in it, share ca.pem, and protect ca-key.pem.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.