• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

Mister PKI

SSL Certificates * SSL Tools * Certificate Decoder

  • PKI Training
  • OpenSSL
  • Keytool
  • PKI Tools
    • Apereo CAS
    • SAML
    • OpenID Connect
  • Get expert help

How to Create a Private CA with OpenSSL CA.pl

July 31, 2026 by Mister PKI Leave a Comment

Overview

System administrators frequently need TLS certificates for systems that are not publicly accessible (and can leverage OpenSSL CA.pl as a solution), including:

  • internal web applications;
  • monitoring dashboards;
  • development servers;
  • network appliances;
  • test environments;
  • configuration-management servers;
  • lab systems;
  • temporary proof-of-concept deployments.

A public certificate authority may not be appropriate for these systems, especially when their hostnames are only resolvable on an internal network.

For a small lab or test environment, OpenSSL includes a Perl script named CA.pl. It provides a simplified interface to several OpenSSL certificate commands and can create a basic certificate authority directory, generate certificate requests, sign certificates, revoke certificates, verify certificates, and generate certificate revocation lists.

The OpenSSL documentation describes CA.pl as a beginner-friendly front end that supplies arguments to underlying commands such as openssl req, openssl ca, openssl verify, and openssl pkcs12. It also warns that the script does not provide the control required for every use case.

This tutorial uses CA.pl to create a small internal certificate authority and issue a TLS certificate for an internal monitoring server named:

monitoring.example.internal

This guide follows the official OpenSSL 3.5 CA.pl documentation and includes compatibility notes for OpenSSL 3.0 and OpenSSL 4.0.

OpenSSL version compatibility

This article applies to:

  • OpenSSL 3.0;
  • OpenSSL 3.1;
  • OpenSSL 3.2;
  • OpenSSL 3.3;
  • OpenSSL 3.4;
  • OpenSSL 3.5 LTS;
  • OpenSSL 4.0.

The workflow and principal CA.pl options covered here are available across OpenSSL 3.0, OpenSSL 3.5, and OpenSSL 4.0. The command remains listed in the official command indexes for all three versions.

The examples use the OpenSSL 3.5 documentation as the primary reference.

Check your installed version before continuing:

openssl version -a

Example:

OpenSSL 3.5.5 27 January 2026

This series supports OpenSSL 3.0 and later. OpenSSL 1.0 and 1.1 are outside its scope.

When should a system administrator use CA.pl?

CA.pl is appropriate for:

  • learning how a certificate authority works;
  • creating certificates for a personal lab;
  • testing TLS configurations;
  • generating temporary certificates for development;
  • demonstrating certificate issuance and revocation;
  • building a disposable CA for automation testing.

It is generally not the best choice for:

  • a large enterprise PKI;
  • a highly available certificate service;
  • automated certificate enrollment at scale;
  • Internet-facing public trust;
  • environments requiring formal certificate profiles;
  • environments requiring approval workflows;
  • a production root CA that must remain offline and carefully audited.

The underlying openssl ca command is itself documented as a sample minimal CA application, and OpenSSL advises reviewing its warnings before using it productively. It maintains a text database of issued certificates and their status rather than providing a transactional or multi-user CA database.

For a real enterprise deployment, administrators will usually want a dedicated CA platform or a more carefully designed OpenSSL configuration and operating procedure.

What CA.pl does

The CA.pl script wraps several common certificate operations.

CA.pl optionPurpose
-newcaCreates a new CA directory and root certificate
-newreqCreates an encrypted private key and CSR
-newreq-nodesCreates an unencrypted private key and CSR
-signSigns the CSR in newreq.pem
-signCASigns a CSR as an intermediate CA certificate
-signcertSigns an existing self-signed certificate
-verifyVerifies a certificate against the CA
-revokeRevokes an issued certificate
-crlGenerates a certificate revocation list
-pkcs12Exports the certificate and key as a PKCS#12 file
-newcertCreates a new self-signed certificate

The script uses predictable filenames such as:

newkey.pem
newreq.pem
newcert.pem
newcert.p12

It creates its certificate authority files under a directory named:

demoCA

These fixed names make the script easy to learn, but they also make it less flexible than using the underlying OpenSSL commands directly.

Prerequisites

You need:

  • OpenSSL 3.0 or later;
  • Perl;
  • access to the CA.pl script;
  • a Linux, Unix-like, WSL, or compatible Windows environment;
  • a dedicated working directory;
  • permission to protect the generated CA private key.

Verify OpenSSL:

openssl version

Verify Perl:

perl --version

Locate CA.pl

Depending on the operating system and installation method, CA.pl may not be in the normal executable path.

Try:

command -v CA.pl

If that returns no result, search common OpenSSL directories:

find /usr/lib /usr/local/lib /opt -name CA.pl 2>/dev/null

You may also be able to locate it through the OpenSSL installation directory:

openssl version -d

A Linux distribution may place the script in an OpenSSL miscellaneous-tools directory rather than /usr/bin.

For the remainder of this article, replace CA.pl with its complete path when necessary.

For example:

/usr/lib/ssl/misc/CA.pl

You can make the examples easier to follow by assigning the path to a shell variable:

CAPL=/usr/lib/ssl/misc/CA.pl

Then run commands using:

"$CAPL" -help

If the script cannot be executed directly, run it through Perl:

perl -S CA.pl -help

The OpenSSL documentation specifically notes that invoking the script through Perl may be necessary in some environments, including Windows.

Real-world scenario

Assume that you administer a monitoring server with the following internal DNS name:

monitoring.example.internal

The server hosts Grafana, Prometheus, or another administrative dashboard over HTTPS.

Because the hostname is internal, you cannot obtain a normal publicly trusted certificate for it. Instead, you will:

  1. create a private root CA;
  2. create a server private key;
  3. generate a certificate signing request;
  4. sign the request with the private CA;
  5. verify the resulting certificate;
  6. install the CA certificate on administrator workstations;
  7. deploy the certificate and key to the monitoring server;
  8. test revocation and CRL generation.

Step 1: Create a secure working directory

Do not create your CA in a shared home directory or a directory accessible to other users.

Create a dedicated directory:

mkdir -p ~/openssl-ca-lab
cd ~/openssl-ca-lab

Restrict access:

chmod 700 ~/openssl-ca-lab

Confirm the current directory:

pwd

CA.pl creates its demoCA hierarchy in the current working directory, so the directory from which you run the command matters.

Step 2: Set a secure file-creation mask

Set a restrictive umask before generating private keys:

umask 077

Files created during the current shell session will not be readable by other users by default.

You can confirm it with:

umask

Expected output:

0077

Step 3: Create the private certificate authority

Run:

"$CAPL" -newca

Or, when calling the script through Perl:

perl "$CAPL" -newca

The script will ask whether you already have a CA certificate and private key.

For a new lab CA, press Enter when prompted for an existing CA certificate. The script will then generate a new private key and self-signed CA certificate.

You will be asked to create a passphrase for the CA private key.

Use a strong, unique passphrase. This private key can issue certificates trusted by any machine on which you install the CA certificate.

You will also be prompted for certificate subject fields, which may include:

Country Name
State or Province Name
Locality Name
Organization Name
Organizational Unit Name
Common Name
Email Address

A reasonable example is:

Country Name: US
State or Province Name: Virginia
Locality Name: Reston
Organization Name: Example Internal IT
Organizational Unit Name: Infrastructure
Common Name: Example Internal Root CA
Email Address: pki@example.com

The most important value is the common name. Use a name that clearly identifies the certificate as a CA rather than as a server certificate.

For example:

Example Internal Root CA

The -newca operation creates the demoCA hierarchy and uses the underlying openssl req and openssl ca functionality. If demoCA already exists, the script will not overwrite it.

Step 4: Examine the CA directory

List the generated files:

find demoCA -maxdepth 2 -type f -print

You should see files similar to:

demoCA/cacert.pem
demoCA/private/cakey.pem
demoCA/index.txt
demoCA/serial

Depending on the script and configuration, additional files or directories may also exist.

Important files include:

FilePurpose
demoCA/cacert.pemRoot CA certificate
demoCA/private/cakey.pemRoot CA private key
demoCA/index.txtDatabase of issued and revoked certificates
demoCA/serialNext certificate serial number
demoCA/newcerts/Copies of certificates issued by the CA

The underlying openssl ca application requires a CA certificate, private key, new-certificates directory, serial file, policy configuration, and certificate database.

Step 5: Protect the CA private key

Check the permissions:

ls -l demoCA/private/cakey.pem

The key should not be accessible to other users.

Set restrictive permissions explicitly:

chmod 600 demoCA/private/cakey.pem
chmod 700 demoCA/private

For a disposable lab, keeping the CA on the same host may be acceptable.

For anything more important, the root CA key should be:

  • stored offline when not in use;
  • backed up securely;
  • encrypted with a strong passphrase;
  • accessible only to authorized administrators;
  • separated from ordinary application servers.

Never copy the CA private key to the server receiving the TLS certificate.

The monitoring server should receive only:

its own private key
its signed server certificate
the CA certificate or chain when required

Step 6: Inspect the root CA certificate

Display the root certificate:

openssl x509 \
  -in demoCA/cacert.pem \
  -noout \
  -subject \
  -issuer \
  -serial \
  -dates

Because this is a self-signed root certificate, the subject and issuer should match.

Inspect its extensions:

openssl x509 \
  -in demoCA/cacert.pem \
  -noout \
  -text

Look for values similar to:

X509v3 Basic Constraints:
    CA:TRUE

You can also confirm the certificate’s purpose with:

openssl x509 \
  -in demoCA/cacert.pem \
  -noout \
  -purpose

Step 7: Back up the CA before issuing certificates

Before proceeding, create an encrypted or otherwise securely protected backup of:

demoCA/cacert.pem
demoCA/private/cakey.pem
demoCA/index.txt
demoCA/serial

The CA database and serial files matter because they track certificate issuance and revocation.

A CA is not just a certificate and key. Losing the database can make ongoing certificate management and revocation more difficult.

Do not store an unencrypted backup of cakey.pem in a general shared folder.

Step 8: Create a server certificate request

The simplest CA.pl workflow is:

"$CAPL" -newreq

This creates:

newkey.pem
newreq.pem

The private key in newkey.pem is encrypted, and newreq.pem contains the certificate signing request.

The OpenSSL documentation confirms that -newreq generates the private key and request using the underlying openssl req command.

When prompted for the certificate subject, use a common name matching the server:

monitoring.example.internal

Example subject information:

Country Name: US
State or Province Name: Virginia
Locality Name: Reston
Organization Name: Example Internal IT
Organizational Unit Name: Infrastructure
Common Name: monitoring.example.internal
Email Address:

However, the common name alone is not sufficient for modern TLS hostname validation. The certificate should also contain a Subject Alternative Name.

Step 9: Add a Subject Alternative Name

Modern clients validate server names against the Subject Alternative Name extension.

For this server, the desired extension is:

DNS:monitoring.example.internal

You may also need aliases:

DNS:monitoring.example.internal
DNS:grafana.example.internal

Because CA.pl is only a wrapper, SAN handling depends on the OpenSSL configuration and parameters passed to the underlying req and ca commands.

Create a small extension file:

cat > monitoring-ext.cnf <<'EOF'

[server_cert]

basicConstraints = critical, CA:FALSE keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @server_names

[server_names]

DNS.1 = monitoring.example.internal EOF

This extension file defines the certificate as an end-entity server certificate rather than a CA certificate.

The OpenSSL CA documentation warns against blindly copying extensions from a request, particularly because an unreviewed request could attempt to include CA:TRUE. It recommends explicitly enforcing values such as basicConstraints = CA:FALSE and appropriate key usage.

Step 10: Inspect the CSR before signing

Display the request:

openssl req \
  -in newreq.pem \
  -noout \
  -subject \
  -verify

Inspect the complete CSR:

openssl req \
  -in newreq.pem \
  -noout \
  -text

Verify that the public key, subject, and requested extensions are appropriate.

A CA administrator should never sign an unreviewed CSR.

At a minimum, verify:

  • the common name;
  • all DNS names;
  • the organization;
  • the key algorithm;
  • the key length;
  • whether the request asks for CA capabilities;
  • whether the request contains unexpected extensions.

Step 11: Sign the server certificate

The basic CA.pl signing command is:

"$CAPL" -sign

This expects the CSR to be named:

newreq.pem

It writes the issued certificate to:

newcert.pem

The command prompts for the CA private-key passphrase and asks you to confirm certificate issuance.

The -sign operation invokes the underlying openssl ca command.

For a certificate that requires explicit TLS server extensions, pass the extension file and section to the underlying ca command:

"$CAPL" \
  -sign \
  -extra-ca "-extfile monitoring-ext.cnf" \
  -extra-ca "-extensions server_cert"

Depending on the shell and CA.pl build, the arguments may also be supplied separately:

"$CAPL" \
  -sign \
  -extra-ca -extfile \
  -extra-ca monitoring-ext.cnf \
  -extra-ca -extensions \
  -extra-ca server_cert

The -extra-cmd mechanism passes additional parameters to the corresponding OpenSSL subcommand. In this example, -extra-ca passes arguments to openssl ca. Multiword parameters may be quoted or supplied through repeated options.

If your distribution’s CA.pl wrapper handles quoted arguments differently, use the underlying command directly:

openssl ca \
  -in newreq.pem \
  -out newcert.pem \
  -extfile monitoring-ext.cnf \
  -extensions server_cert

That is often preferable when building a repeatable production procedure.

Step 12: Inspect the issued certificate

Display the certificate summary:

openssl x509 \
  -in newcert.pem \
  -noout \
  -subject \
  -issuer \
  -serial \
  -dates

Inspect the Subject Alternative Name:

openssl x509 \
  -in newcert.pem \
  -noout \
  -ext subjectAltName

Expected output:

X509v3 Subject Alternative Name:
    DNS:monitoring.example.internal

Check basic constraints:

openssl x509 \
  -in newcert.pem \
  -noout \
  -ext basicConstraints

Expected:

CA:FALSE

Check extended key usage:

openssl x509 \
  -in newcert.pem \
  -noout \
  -ext extendedKeyUsage

Expected:

TLS Web Server Authentication

Review the complete certificate:

openssl x509 \
  -in newcert.pem \
  -noout \
  -text

Step 13: Verify the certificate with CA.pl

Run:

"$CAPL" -verify newcert.pem

The script verifies the certificate against:

demoCA/cacert.pem

A successful result should resemble:

newcert.pem: OK

If no filename is supplied, CA.pl -verify attempts to verify newcert.pem.

You can perform the same test directly:

openssl verify \
  -CAfile demoCA/cacert.pem \
  newcert.pem

Step 14: Verify the server hostname

Certificate-chain validation and hostname validation are related but distinct checks.

Use:

openssl verify \
  -CAfile demoCA/cacert.pem \
  -verify_hostname monitoring.example.internal \
  newcert.pem

Expected output:

newcert.pem: OK

Test an incorrect name:

openssl verify \
  -CAfile demoCA/cacert.pem \
  -verify_hostname wrong.example.internal \
  newcert.pem

This should fail with a hostname mismatch.

This test confirms why the Subject Alternative Name is essential.

Step 15: Rename the certificate and key

The default filenames are useful for learning but poor for long-term administration.

Create a deployment directory:

mkdir -p issued/monitoring.example.internal

Copy the files:

cp newcert.pem \
  issued/monitoring.example.internal/monitoring.example.internal.crt
cp newkey.pem \
  issued/monitoring.example.internal/monitoring.example.internal.key
cp demoCA/cacert.pem \
  issued/monitoring.example.internal/example-internal-root-ca.crt

Protect the key:

chmod 600 \
  issued/monitoring.example.internal/monitoring.example.internal.key

After copying the files, avoid confusing them with the fixed newcert.pem and newkey.pem names that CA.pl will reuse during the next issuance.

Step 16: Decide whether the server key should remain encrypted

The -newreq option creates an encrypted private key.

An encrypted key is safer at rest, but a web service normally needs a way to unlock the key whenever it starts.

For an unattended service, administrators commonly use an unencrypted service key protected by:

  • restrictive filesystem permissions;
  • root ownership;
  • disk encryption;
  • host-access controls;
  • configuration-management controls;
  • secrets management where supported.

CA.pl provides:

"$CAPL" -newreq-nodes

This creates a request like -newreq, but leaves the private key unencrypted.

Despite the option name, -newreq-nodes does not mean that no certificate nodes are created. Historically, “nodes” refers to “no DES,” meaning no private-key encryption.

For a server certificate, you may use:

"$CAPL" -newreq-nodes

Then protect the resulting key immediately:

chmod 600 newkey.pem

Do not use unencrypted keys casually on administrator laptops, shared servers, or untrusted filesystems.

Step 17: Deploy the certificate

A typical web server needs:

monitoring.example.internal.crt
monitoring.example.internal.key

It may also need the CA certificate or a chain file, depending on the application.

For an internal root CA that directly issued the server certificate, the client trust store normally receives:

example-internal-root-ca.crt

The root CA certificate is not secret. The root CA private key is secret.

Never deploy this file to the monitoring server:

demoCA/private/cakey.pem

Step 18: Trust the private CA on client systems

Browsers and operating systems will not automatically trust your private CA.

You must install:

demoCA/cacert.pem

into the appropriate trust store on each authorized client.

Examples include:

  • Linux system trust stores;
  • Windows Trusted Root Certification Authorities;
  • browser-specific trust stores;
  • Java trust stores;
  • application-specific certificate bundles.

Only install the CA certificate on systems that should trust certificates issued by this private CA.

Once a root CA is trusted, any certificate validly issued by that CA may be trusted for the names and purposes permitted by the certificate.

Step 19: Test the deployed TLS service

After configuring the monitoring server, test it with:

openssl s_client \
  -connect monitoring.example.internal:443 \
  -servername monitoring.example.internal \
  -CAfile demoCA/cacert.pem \
  -verify_return_error

Review:

  • the certificate chain;
  • the subject;
  • the issuer;
  • the verification result;
  • the negotiated TLS protocol;
  • the negotiated cipher suite.

Look for:

Verify return code: 0 (ok)

The -servername option sends the intended hostname through Server Name Indication, which is necessary when multiple TLS virtual hosts share an IP address.

Step 20: Export a PKCS#12 file

Some Windows applications, browsers, appliances, and administrative tools expect a PKCS#12 file containing:

  • the private key;
  • the issued certificate;
  • the CA certificate.

CA.pl can create one with:

"$CAPL" -pkcs12 "Monitoring Server"

This expects:

newcert.pem
newkey.pem
demoCA/cacert.pem

It creates:

newcert.p12

The optional text becomes the certificate’s friendly name.

Rename the file:

mv newcert.p12 monitoring.example.internal.p12

Inspect it without displaying private-key material:

openssl pkcs12 \
  -in monitoring.example.internal.p12 \
  -info \
  -noout

Protect the file carefully. A PKCS#12 bundle may contain the server’s private key.

Step 21: Issue another certificate

CA.pl reuses generic filenames.

Before generating the next certificate, move or remove:

newkey.pem
newreq.pem
newcert.pem

A safer workflow is to create a separate working directory for each request while keeping the CA database in a controlled location.

For example:

openssl-ca-lab/
├── demoCA/
├── requests/
│   ├── monitoring.example.internal/
│   └── grafana.example.internal/
└── issued/

However, because CA.pl expects demoCA in the current directory, more advanced layouts may require:

  • symbolic links;
  • script modifications;
  • a custom OpenSSL configuration;
  • direct use of openssl ca.

This is one of the points where administrators often outgrow CA.pl.

Step 22: View the issued-certificate database

Display the CA database:

cat demoCA/index.txt

A valid certificate entry usually begins with:

V

A revoked certificate usually begins with:

R

The database records information such as:

  • certificate status;
  • expiration date;
  • revocation date;
  • serial number;
  • certificate subject.

Do not edit this file casually.

Back it up with the CA key, certificate, and serial file.

Step 23: Revoke the server certificate

Assume the monitoring server was compromised and its private key may have been exposed.

Revoke its certificate:

"$CAPL" \
  -revoke newcert.pem \
  keyCompromise

The supported reasons include:

unspecified
keyCompromise
CACompromise
affiliationChanged
superseded
cessationOfOperation
certificateHold
removeFromCRL

The script passes the operation to the underlying openssl ca command.

Confirm the database entry:

grep monitoring.example.internal demoCA/index.txt

The line should now begin with:

R

Revoking the certificate updates the CA database, but it does not automatically inform clients.

Clients need access to a CRL or another revocation-status mechanism and must be configured to check it.

Step 24: Generate a certificate revocation list

Generate a CRL:

"$CAPL" -crl

Depending on the CA.pl implementation and configuration, the output may be written to a default CRL filename or standard output.

To generate a clearly named CRL directly, use:

openssl ca \
  -gencrl \
  -out demoCA/crl.pem

Inspect the CRL:

openssl crl \
  -in demoCA/crl.pem \
  -noout \
  -issuer \
  -lastupdate \
  -nextupdate

Display revoked entries:

openssl crl \
  -in demoCA/crl.pem \
  -noout \
  -text

The underlying OpenSSL CA command generates a CRL from the status information maintained in its index database.

Step 25: Verify a certificate against the CRL

Verify the certificate and check the CRL:

openssl verify \
  -CAfile demoCA/cacert.pem \
  -CRLfile demoCA/crl.pem \
  -crl_check \
  newcert.pem

A revoked certificate should fail verification with an error similar to:

certificate revoked

This illustrates an important operational requirement: creating a CRL is not enough. It must be:

  • published at a stable location;
  • refreshed before expiration;
  • reachable by clients;
  • referenced by certificates when appropriate;
  • checked by the consuming software.

CA.pl can demonstrate revocation mechanics, but it does not build a complete CRL publishing service.

Creating an intermediate CA with CA.pl

CA.pl also provides:

"$CAPL" -signCA

This signs the request in newreq.pem using the v3_ca configuration section, producing a certificate capable of acting as a CA. The documented purpose is creating an intermediate CA signed by a root CA.

A better PKI design generally keeps the root CA offline and uses an intermediate CA for routine certificate issuance.

However, a secure intermediate-CA design requires careful control over:

  • basicConstraints;
  • path-length constraints;
  • key usage;
  • certificate policies;
  • name constraints where required;
  • validity periods;
  • CRL distribution points;
  • authority information access;
  • private-key storage;
  • signing procedures.

Do not rely solely on the default -signCA workflow for an important production hierarchy.

For a serious root-and-intermediate design, use a reviewed OpenSSL configuration and direct openssl req and openssl ca commands.

Using a custom OpenSSL configuration

CA.pl can pass a custom configuration location to the commands it invokes.

The documented environment variable is:

OPENSSL_CONFIG

Its value should contain a configuration option and path, such as:

export OPENSSL_CONFIG="-config /path/to/openssl-ca.cnf"

CA.pl also supports setting the OPENSSL environment variable to specify the OpenSSL executable it should call.

For example:

export OPENSSL=/usr/local/openssl-3.5/bin/openssl

This is useful when multiple OpenSSL versions are installed:

/usr/bin/openssl
/usr/local/openssl-3.5/bin/openssl
/opt/openssl-4.0/bin/openssl

Confirm the selected binary:

"$OPENSSL" version -a

Some CA.pl versions or platform notes may also reference OPENSSL_CONF, which is the broader OpenSSL environment variable used to identify the default configuration file. When troubleshooting configuration selection, inspect both:

env | grep '^OPENSSL'

OpenSSL 3.0, 3.5, and 4.0 differences

The basic CA.pl workflow is largely unchanged across these versions:

CA.pl -newca
CA.pl -newreq
CA.pl -sign
CA.pl -verify
CA.pl -revoke
CA.pl -crl
CA.pl -pkcs12

However, the underlying OpenSSL behavior can differ.

OpenSSL 3.0

OpenSSL 3.0 introduced the provider architecture and deprecated the older ENGINE framework.

When using algorithms that are no longer available through the default provider, an administrator may need to load another provider, such as the legacy provider.

CA.pl can pass extra provider-related parameters to an underlying command through options such as:

-extra-req
-extra-ca
-extra-pkcs12

For modern certificates, avoid legacy algorithms unless compatibility explicitly requires them.

OpenSSL 3.2 and later

The official openssl ca history notes that beginning with OpenSSL 3.2, generated certificates are X.509 version 3 and key identifier extensions are included by default unless otherwise configured.

You should still define critical certificate extensions explicitly rather than relying solely on defaults.

OpenSSL 3.5 LTS

OpenSSL 3.5 is the primary version used by this article series.

The CA.pl interface remains consistent with the OpenSSL 3.0 workflow, including:

  • -newca;
  • -newreq;
  • -newreq-nodes;
  • -sign;
  • -signCA;
  • -verify;
  • -revoke;
  • -crl;
  • -pkcs12;
  • -extra-cmd.

OpenSSL 3.5 is the recommended documentation target for new MisterPKI articles, while OpenSSL 3.0 remains the compatibility baseline.

OpenSSL 4.0

CA.pl is still included in the OpenSSL 4.0 command documentation.

The principal CA.pl workflow remains available, but OpenSSL 4.0 removes additional legacy ENGINE support from the underlying commands. For example, the OpenSSL 4.0 openssl ca syntax no longer lists the deprecated -engine option that appeared in OpenSSL 3.5.

Provider-based configuration should therefore be preferred for procedures intended to work on both OpenSSL 3 and OpenSSL 4.

For normal RSA or elliptic-curve internal certificates using the default provider, the workflow in this article should remain substantially the same.

Windows considerations

Windows does not normally include a native system-wide CA.pl command.

A Windows administrator may use CA.pl through:

  • a third-party OpenSSL installation;
  • a manually built OpenSSL installation;
  • Git Bash or another Unix-like environment;
  • Strawberry Perl or another Perl distribution;
  • Windows Subsystem for Linux.

Check the OpenSSL executable:

Get-Command openssl | Format-List Source

Check Perl:

Get-Command perl | Format-List Source

Locate CA.pl:

Get-ChildItem C:\ -Filter CA.pl -Recurse -ErrorAction SilentlyContinue

Run the script through Perl:

perl C:\OpenSSL\bin\CA.pl -help

Because CA.pl assumes Unix-like paths and a particular configuration location, WSL is often the least troublesome Windows method.

Inside WSL, follow the Linux instructions and use the OpenSSL version supplied by the installed WSL distribution.

Common CA.pl errors

CA.pl: command not found

The script is not in your PATH.

Locate it:

find /usr /usr/local /opt -name CA.pl 2>/dev/null

Then run it by full path.

Cannot open configuration file

Find the OpenSSL configuration directory:

openssl version -d

Find possible configuration files:

find /etc /usr/lib/ssl /usr/local/ssl -name openssl.cnf 2>/dev/null

Then specify the configuration through the appropriate environment variable or direct OpenSSL command.

demoCA already exists

CA.pl -newca will not overwrite an existing demoCA directory.

Inspect it before deleting anything:

find demoCA -maxdepth 2 -type f -ls

If it is an incomplete disposable test CA, remove it:

rm -rf demoCA

Then rerun:

"$CAPL" -newca

Never delete an active CA directory merely to clear an error.

Unable to load CA private key

Confirm that the key exists:

ls -l demoCA/private/cakey.pem

Check whether it is readable:

openssl pkey \
  -in demoCA/private/cakey.pem \
  -noout \
  -check

You will be prompted for the passphrase.

TXT_DB error number 2

This commonly indicates that the CA database believes a valid certificate with the same subject already exists.

Inspect:

cat demoCA/index.txt

For server certificates, repeated subjects may be expected during renewal. A custom CA configuration can set:

unique_subject = no

Do not manually delete entries from index.txt without understanding the effect on CA state.

The certificate has no Subject Alternative Name

The CSR or signing configuration did not supply a SAN.

Check the CSR:

openssl req \
  -in newreq.pem \
  -noout \
  -text

Check the certificate:

openssl x509 \
  -in newcert.pem \
  -noout \
  -ext subjectAltName

Use an explicit extension file during signing.

The browser still reports an untrusted certificate

Verify that:

  • the root CA certificate was installed in the correct trust store;
  • the browser uses that trust store;
  • the server sent the correct certificate;
  • the certificate has the correct SAN;
  • the certificate is within its validity period;
  • the server was restarted after certificate deployment.

Test from the command line:

openssl s_client \
  -connect monitoring.example.internal:443 \
  -servername monitoring.example.internal \
  -CAfile demoCA/cacert.pem \
  -verify_return_error

The certificate verifies but the hostname fails

Check the SAN:

openssl x509 \
  -in newcert.pem \
  -noout \
  -ext subjectAltName

Then test:

openssl verify \
  -CAfile demoCA/cacert.pem \
  -verify_hostname monitoring.example.internal \
  newcert.pem

The DNS name must match an entry in the SAN extension.

Security recommendations

When using CA.pl, follow these minimum safeguards:

  1. Protect the CA private key with a strong passphrase.
  2. Restrict permissions on the CA directory.
  3. Back up the CA certificate, key, database, and serial state.
  4. Do not place the root private key on application servers.
  5. Review every CSR before signing it.
  6. Explicitly set CA:FALSE on server and client certificates.
  7. Explicitly define key usage and extended key usage.
  8. Avoid blindly copying CSR extensions.
  9. Use SANs for DNS names.
  10. Use an intermediate CA for anything beyond a disposable lab.
  11. Keep the root CA offline when practical.
  12. Document certificate owners, purposes, and expiration dates.
  13. Establish a renewal process before certificates expire.
  14. Establish a CRL publishing process before relying on revocation.
  15. Migrate away from CA.pl when the environment requires automation, scale, auditing, or multiple administrators.

CA.pl versus openssl ca

CA.pl is easier to learn:

CA.pl -newca
CA.pl -newreq
CA.pl -sign

Direct OpenSSL commands provide more control:

openssl req ...
openssl ca ...
openssl verify ...
openssl pkcs12 ...

Use CA.pl when:

  • teaching OpenSSL certificate concepts;
  • running a small lab;
  • testing basic certificate workflows;
  • creating a disposable internal CA.

Use direct OpenSSL commands or dedicated PKI software when:

  • certificate profiles must be tightly controlled;
  • SANs and extensions vary;
  • certificates are issued automatically;
  • multiple operators manage the CA;
  • audit records are required;
  • hardware-protected keys are used;
  • the CA serves production systems;
  • revocation information must be reliably published;
  • high availability is required.

The OpenSSL documentation itself states that CA.pl may not behave exactly as desired and recommends calling the underlying OpenSSL commands directly when more control is needed.

Complete CA.pl command summary

Create a new private CA:

CA.pl -newca

Create an encrypted private key and CSR:

CA.pl -newreq

Create an unencrypted private key and CSR:

CA.pl -newreq-nodes

Sign the CSR:

CA.pl -sign

Sign an intermediate CA CSR:

CA.pl -signCA

Verify the issued certificate:

CA.pl -verify newcert.pem

Export a PKCS#12 file:

CA.pl -pkcs12 "Certificate Friendly Name"

Revoke a certificate:

CA.pl -revoke newcert.pem keyCompromise

Generate a CRL:

CA.pl -crl

Display help:

CA.pl -help

Conclusion

The OpenSSL CA.pl script provides a convenient way to learn and demonstrate the certificate-authority lifecycle:

Create CA
Create private key
Generate CSR
Review CSR
Sign certificate
Verify certificate
Deploy certificate
Revoke certificate
Generate CRL

For a system administrator managing a small internal lab, it can quickly produce certificates for internal dashboards, test servers, development systems, and administrative tools.

Its simplicity is also its limitation. It relies on fixed filenames, a demoCA directory, a text certificate database, and defaults that may not match a production PKI design.

Use CA.pl to understand the workflow and handle limited lab use. Once you need repeatability, carefully controlled extensions, automated issuance, intermediate CAs, hardware-backed keys, multiple administrators, or reliable revocation services, move to direct OpenSSL commands or a dedicated certificate-authority platform.

linux,  openssl,  redhat,  SSL Certificates,  Ubuntu

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Popular Posts

PKCS12

openssl s_client

Keytool

Keytool list

ECDSA vs RSA

OpenSSL

PKCS7

Certificate Decoder

PKI for DevOps Engineers – Free Training Series

PKI for DevOps Training Hub

Lesson 1 – How TLS and PKI Work

Lesson 2 – Understanding X.509 Certificates

Lesson 3 – Certificate Chains Explained

Lesson 4 – Debug TLS with OpenSSL

Lesson 5 – Verify Certificate Chains

Lesson 6 – Creating CSRs with OpenSSL

Lesson 7 – Working with PKCS12 Certificates

Lesson 8 – Java Keystores and keytool

Lesson 9 – Certificate Expiration Monitoring

Lesson 10 – Automating Certificate Renewal

Lesson 11 – Common TLS Errors

Lesson 12 – PKI Architecture for DevOps

Recent Posts

  • Apache mod_auth_cas: Protect Web Applications with Apereo CAS and Docker
  • Apache mod_auth_mellon: Configure SAML SSO & Docker
  • Configure OpenID Connect (OIDC) in Apereo CAS 7.3 and 8
  • Certificate Ownership Is an Operating Model Problem, Not a Tooling Problem
  • OpenSSL dgst: Create Checksums and Verify Digital Signatures

Footer

  • Twitter
  • YouTube
Mister PKI

Practical security engineering for the systems that establish trust.

Learn OpenSSL Keytool Free training
Work together PKI consulting CAS consulting Sponsored contributions
Site About Support Mister PKI Cookie policy Search
© 2026 Mister PKI Secure systems. Clear guidance.