Create a private root certificate authority

To create a root CA, generate a key and a self-signed CA certificate with the CA basic constraint set — `openssl req -x509 -new -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3650 -subj "/CN=Example Internal Root CA" -addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"`. The `basicConstraints=CA:TRUE` extension is what makes it a CA rather than an ordinary self-signed certificate; without it nothing will accept certificates it signs. Encrypt the CA key with a passphrase, because anything holding it can issue certificates your machines will trust.

Updated August 19, 2026 Verified against OpenSSL 3.5.7

Step 1 — the CA private key #

Encrypt it. This is the one key where a passphrase is unambiguously correct, because a CA key is not read by an unattended service:

4096-bit RSA, encrypted
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -aes-256-cbc -out ca.key
chmod 400 ca.key

Step 2 — the self-signed CA certificate #

A root CA certificate valid for ten years
openssl req -x509 -new -key ca.key -out ca.crt -days 3650 -sha256 \
-subj "/C=US/O=Example Inc/CN=Example Inc Internal Root CA" \
-addext "basicConstraints=critical,CA:TRUE" \
-addext "keyUsage=critical,keyCertSign,cRLSign" \
-addext "subjectKeyIdentifier=hash"

Replace these values

PlaceholderWhat to put there
basicConstraints=critical,CA:TRUEWhat makes this a CA. Marked critical so it cannot be ignored.
keyUsage=critical,keyCertSign,cRLSignRestricts the key to signing certificates and revocation lists.
subjectKeyIdentifier=hashLets clients link issued certificates back to this CA reliably.
-days 3650Ten years. Longer means fewer trust-store updates and a longer-lived risk.

Step 3 — check what you built #

openssl x509 -in ca.crt -noout -subject -issuer -dates -ext basicConstraints -ext keyUsage
Expected output
subject=C = US, O = Example Inc, CN = Example Inc Internal Root CA
issuer=C = US, O = Example Inc, CN = Example Inc Internal Root CA
notBefore=Aug 19 12:00:00 2026 GMT
notAfter=Aug 17 12:00:00 2036 GMT
X509v3 Basic Constraints: critical
  CA:TRUE
X509v3 Key Usage: critical
  Certificate Sign, CRL Sign

Identical subject and issuer confirms it is self-signed — correct for a root. CA:TRUE confirms it can sign. If CA:TRUE is missing, start again; certificates signed by this will be rejected and the error will not obviously point back here.

Step 4 — distribute the CA certificate #

Install ca.crt — never ca.key — on every machine that needs to trust what you issue:

sudo cp ca.crt /usr/local/share/ca-certificates/example-internal-ca.crt
sudo update-ca-certificates
sudo cp ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust extract
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ca.crt
sudo apk add ca-certificates
sudo cp ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

Step 5 — issue your first certificate #

Generate a key and CSR for a server
openssl req -new -newkey rsa:2048 -nodes \
-keyout server.key -out server.csr \
-subj "/CN=service.internal" \
-addext "subjectAltName=DNS:service.internal,DNS:*.service.internal"
Sign it with the CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 397 -sha256 \
-copy_extensions copyall

Why a CA beats self-signed certificates #

Self-signed Private CA
Trust-store operations One per certificate, per machine One per machine, ever
Renewals Re-trust every time Just reissue
Revocation None Possible via CRL
Effort for 1 certificate Lower Higher
Effort for 5+ certificates Much higher Much lower

Frequently asked questions

What makes a certificate a CA certificate?
The basicConstraints extension containing CA:TRUE, marked critical. Without it, a certificate is an ordinary end-entity certificate and every correct implementation will refuse to accept signatures it makes on other certificates.
How long should a root CA last?
Ten years is typical for an internal root, because replacing it means touching the trust store on every machine again. The trade-off is that a long-lived root is a long-lived liability if the key is ever exposed.
Should I sign certificates directly with the root?
For a small internal setup it is acceptable and much simpler. The reason public CAs do not is that the root key can then stay offline — an intermediate does the day-to-day signing, and a compromised intermediate can be revoked without reissuing every trust store.
Where should the CA key live?
Somewhere offline, encrypted, and backed up separately from anything internet-facing. Anyone with that key and its passphrase can issue certificates that every machine trusting your root will accept, for any hostname including ones you do not own.

References