How to create a local certificate authority using OpenSSL

Lab services, internal dashboards, and development endpoints sometimes need certificates that chain to a root your own clients trust. A throwaway self-signed server certificate does not create a reusable issuing boundary, while a local certificate authority root gives controlled systems one trust anchor for certificates that will never be publicly trusted.

OpenSSL builds the local CA from an encrypted private key and a self-signed X.509 root certificate. A small configuration file supplies the subject and v3 CA extensions, so the root certificate carries critical Basic Constraints with CA:TRUE and Key Usage values for certificate and CRL signing.

Keep the root key offline or limited to the machine that issues internal certificates. pathlen:0 prevents this root from issuing subordinate CAs, and only local-ca/certs/local-ca.cert.pem should be copied to clients or trust stores. Public browsers and operating systems will not trust the root until an administrator installs it explicitly.

Steps to create a local certificate authority using OpenSSL:

  1. Create storage directories for the local CA files.
    $ mkdir -p local-ca/private local-ca/certs
    $ chmod 700 local-ca/private

    The private directory holds the CA signing key. The certs directory holds the public root certificate that clients may later trust.

  2. Save the CA request and extension configuration.
    [ req ]
    prompt = no
    distinguished_name = dn
    x509_extensions = v3_ca
    string_mask = utf8only
     
    [ dn ]
    C = US
    O = Example Corp
    CN = Example Local Root CA
     
    [ v3_ca ]
    basicConstraints = critical, CA:true, pathlen:0
    keyUsage = critical, keyCertSign, cRLSign
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer

    The v3_ca section makes the certificate a CA certificate and limits it to issuing end-entity certificates rather than subordinate CA certificates.

  3. Generate an encrypted RSA private key for the local CA.
    $ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 \
      -aes-256-cbc -quiet -out local-ca/private/local-ca.key.pem
    Enter PEM pass phrase:
    Verifying - Enter PEM pass phrase:

    The CA private key can sign every certificate that chains to this root. Use a strong passphrase and do not pass it as a command-line argument on shared systems.

  4. Restrict the CA private key file.
    $ chmod 400 local-ca/private/local-ca.key.pem
  5. Create the self-signed root certificate from the CA key and configuration.
    $ openssl req -new -x509 -sha256 -days 3650 \
      -key local-ca/private/local-ca.key.pem \
      -out local-ca/certs/local-ca.cert.pem \
      -config local-ca/openssl-local-ca.cnf -extensions v3_ca
    Enter pass phrase for local-ca/private/local-ca.key.pem:

    Change C, O, CN, and the validity period before creating a long-lived root for a real internal environment.

  6. Inspect the root certificate subject, issuer, validity, and CA extensions.
    $ openssl x509 -in local-ca/certs/local-ca.cert.pem -noout \
      -subject -issuer -dates -ext basicConstraints,keyUsage
    subject=C=US, O=Example Corp, CN=Example Local Root CA
    issuer=C=US, O=Example Corp, CN=Example Local Root CA
    notBefore=Jun  5 20:36:42 2026 GMT
    notAfter=Jun  2 20:36:42 2036 GMT
    X509v3 Basic Constraints: critical
        CA:TRUE, pathlen:0
    X509v3 Key Usage: critical
        Certificate Sign, CRL Sign
  7. Verify that OpenSSL accepts the root certificate as its own trust anchor.
    $ openssl verify -CAfile local-ca/certs/local-ca.cert.pem local-ca/certs/local-ca.cert.pem
    local-ca/certs/local-ca.cert.pem: OK
  8. Check that the private key and public root certificate have the intended file permissions.
    $ ls -l local-ca/certs local-ca/private
    local-ca/certs:
    total 4
    -r--r--r-- 1 user user 1964 Jun  5 20:36 local-ca.cert.pem
    
    local-ca/private:
    total 4
    -r-------- 1 user user 3446 Jun  5 20:36 local-ca.key.pem

    Use local-ca/private/local-ca.key.pem only for issuing certificates. Distribute local-ca/certs/local-ca.cert.pem to clients and systems that should trust certificates signed by this local CA.