How to Use OpenSSL to Generate, Sign and Manage SSL Certificates on RHEL 7

OpenSSL is the standard open-source toolkit for implementing the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols, and it is used on almost every Linux server in production. On Red Hat Enterprise Linux 7, OpenSSL is installed by default and provides everything you need to generate private keys, create certificate signing requests (CSRs), issue self-signed certificates, build a local Certificate Authority (CA), and convert between the many certificate formats used in the wild. Whether you are securing an internal web service, creating test certificates for development, or running a small internal PKI, understanding how to drive OpenSSL from the command line is an essential skill. This tutorial walks through each task step by step with realistic commands you can run directly on RHEL 7.

Prerequisites

  • A running RHEL 7 system with root or sudo access.
  • OpenSSL installed (verify with openssl version; install with sudo yum install openssl if missing).
  • Basic familiarity with the Linux command line.
  • The openssl-perl package if you intend to use CA.pl helper scripts (sudo yum install openssl-perl).

Step 1: Generate an RSA Private Key

Every certificate operation starts with a private key. The private key is the secret component that proves identity during the TLS handshake. RSA keys of 2048 bits are the practical minimum for production; 4096 bits provide a larger security margin at the cost of slightly slower operations.

# Generate a 2048-bit RSA key, unencrypted (suitable for automated services)
openssl genrsa -out server.key 2048

# Generate a 4096-bit RSA key protected by AES-256 passphrase
openssl genrsa -aes256 -out server-encrypted.key 4096

# Inspect the key
openssl rsa -in server.key -text -noout

Store the private key in a directory accessible only to root or the service account. A common convention is /etc/pki/tls/private/ with permissions set to 0600.

chmod 600 server.key
chown root:root server.key
mv server.key /etc/pki/tls/private/server.key

Step 2: Create a Certificate Signing Request (CSR)

A CSR is a block of encoded text that you submit to a Certificate Authority. It contains the public key and identifying information such as the Common Name (CN), organisation, and country. The CA signs the CSR with its own key and returns a certificate.

# Interactive CSR — OpenSSL will prompt for each field
openssl req -new -key /etc/pki/tls/private/server.key 
    -out server.csr

# Non-interactive CSR using a subject string
openssl req -new 
    -key /etc/pki/tls/private/server.key 
    -subj "/C=US/ST=California/L=San Francisco/O=Example Corp/CN=www.example.com" 
    -out server.csr

# Inspect the CSR to verify the fields
openssl req -in server.csr -text -noout

For Subject Alternative Names (SANs), which modern browsers require, create a config file first:

cat > san.cnf <<EOF
[req]
distinguished_name = req_distinguished_name
req_extensions     = v3_req
prompt             = no

[req_distinguished_name]
C  = US
ST = California
L  = San Francisco
O  = Example Corp
CN = www.example.com

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com
DNS.3 = mail.example.com
EOF

openssl req -new 
    -key /etc/pki/tls/private/server.key 
    -config san.cnf 
    -out server-san.csr

Step 3: Create a Self-Signed Certificate

For internal services, testing environments, or when you control both ends of the connection, a self-signed certificate avoids the need to involve a CA. The x509 subcommand is used to sign the CSR with the private key itself.

# Sign the CSR with the private key — valid for 365 days
openssl x509 -req 
    -days 365 
    -in server.csr 
    -signkey /etc/pki/tls/private/server.key 
    -out server.crt

# One-liner shortcut: generate key + self-signed cert together
openssl req -x509 -nodes -days 365 
    -newkey rsa:2048 
    -keyout /etc/pki/tls/private/server.key 
    -out /etc/pki/tls/certs/server.crt 
    -subj "/C=US/ST=California/O=Example Corp/CN=www.example.com"

Set appropriate permissions on the certificate file (it is public, but keeping it tidy helps):

chmod 644 /etc/pki/tls/certs/server.crt

Step 4: Inspect a Certificate

The x509 -text command decodes a certificate and displays all of its fields in human-readable form, including the validity dates, the subject, the issuer, the public key, and any extensions such as SANs or Key Usage constraints.

# Inspect a local certificate file
openssl x509 -in /etc/pki/tls/certs/server.crt -text -noout

# Check only the dates (quick expiry audit)
openssl x509 -in /etc/pki/tls/certs/server.crt -noout -dates

# Fetch and inspect a live server certificate
echo | openssl s_client -connect www.example.com:443 2>/dev/null 
    | openssl x509 -noout -text

# Check the certificate serial number
openssl x509 -in server.crt -noout -serial

Step 5: Create a Local Certificate Authority (CA)

For an internal PKI — for example, to issue certificates to many internal servers and have all of them trusted by adding just one root CA to client trust stores — you need to set up your own CA. You can do this manually or use the CA.pl helper script bundled with openssl-perl.

Manual CA Setup

# Create the CA directory structure
mkdir -p /etc/pki/myCA/{certs,crl,newcerts,private}
chmod 700 /etc/pki/myCA/private
touch /etc/pki/myCA/index.txt
echo 1000 > /etc/pki/myCA/serial

# Create the CA configuration file
cat > /etc/pki/myCA/openssl.cnf <<'EOF'
[ ca ]
default_ca = CA_default

[ CA_default ]
dir              = /etc/pki/myCA
certs            = $dir/certs
crl_dir          = $dir/crl
database         = $dir/index.txt
new_certs_dir    = $dir/newcerts
certificate      = $dir/cacert.pem
serial           = $dir/serial
crlnumber        = $dir/crlnumber
crl              = $dir/crl.pem
private_key      = $dir/private/cakey.pem
x509_extensions  = usr_cert
name_opt         = ca_default
cert_opt         = ca_default
default_days     = 365
default_crl_days = 30
default_md       = sha256
preserve         = no
policy           = policy_strict

[ policy_strict ]
countryName            = match
stateOrProvinceName    = match
organizationName       = match
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

[ usr_cert ]
basicConstraints       = CA:FALSE
keyUsage               = digitalSignature, keyEncipherment
extendedKeyUsage       = serverAuth
EOF

# Generate the CA private key (4096-bit, passphrase protected)
openssl genrsa -aes256 
    -out /etc/pki/myCA/private/cakey.pem 4096
chmod 400 /etc/pki/myCA/private/cakey.pem

# Self-sign the CA certificate (valid 10 years)
openssl req -new -x509 -days 3650 
    -config /etc/pki/myCA/openssl.cnf 
    -key /etc/pki/myCA/private/cakey.pem 
    -out /etc/pki/myCA/cacert.pem 
    -subj "/C=US/ST=California/O=Example Corp/CN=Example Corp CA"

Step 6: Sign a Certificate with Your CA

Once the CA is in place, you can sign CSRs from any server in your organisation. The signed certificate will be trusted by any client that has your CA certificate in its trust store.

# Sign a CSR with the CA
openssl ca 
    -config /etc/pki/myCA/openssl.cnf 
    -in server.csr 
    -out server-signed.crt 
    -days 365

# Verify the signed certificate against the CA
openssl verify -CAfile /etc/pki/myCA/cacert.pem server-signed.crt

Add your CA certificate to the system-wide trust store on RHEL 7 so that tools like curl trust certificates signed by it:

cp /etc/pki/myCA/cacert.pem /etc/pki/ca-trust/source/anchors/myCA.crt
update-ca-trust

Step 7: PEM vs DER Formats and Format Conversion

OpenSSL primarily works in PEM format (Base64-encoded with -----BEGIN CERTIFICATE----- headers). Some applications, particularly Java-based ones and Windows systems, require DER (binary) or PKCS#12 (bundled key and cert) formats.

# Convert PEM certificate to DER
openssl x509 -in server.crt -outform DER -out server.der

# Convert DER certificate back to PEM
openssl x509 -in server.der -inform DER -outform PEM -out server-from-der.crt

# Create a PKCS#12 bundle (key + cert + optional CA chain) for Java/Windows
openssl pkcs12 -export 
    -in server.crt 
    -inkey /etc/pki/tls/private/server.key 
    -certfile /etc/pki/myCA/cacert.pem 
    -out server.p12 
    -name "www.example.com"

# Extract the certificate from a PKCS#12 bundle
openssl pkcs12 -in server.p12 -nokeys -out extracted.crt

# Extract the private key from a PKCS#12 bundle
openssl pkcs12 -in server.p12 -nocerts -nodes -out extracted.key

Step 8: Verify a Certificate Chain

When troubleshooting TLS handshake failures, verifying the complete certificate chain is often the first diagnostic step. A broken chain — typically caused by a missing intermediate certificate — is one of the most common production TLS issues.

# Verify the server cert against a CA bundle
openssl verify -CAfile /etc/pki/myCA/cacert.pem server-signed.crt

# Verify a chain with an intermediate CA
cat intermediate.crt cacert.pem > chain.pem
openssl verify -CAfile chain.pem server-signed.crt

# Check what a remote server is actually presenting
echo | openssl s_client -connect internal.example.com:443 -showcerts 2>/dev/null

A successful verification outputs server-signed.crt: OK. Any error code — such as 20 (unable to get local issuer certificate) — indicates a chain problem that must be resolved before clients will trust the certificate.

Conclusion

OpenSSL’s command-line interface covers the full certificate lifecycle: generating strong private keys, building CSRs with the right attributes, issuing self-signed certificates for internal use, running a local CA to sign certificates for multiple services, and converting between the PEM, DER, and PKCS#12 formats required by different applications. On RHEL 7, these skills complement the system’s built-in PKI infrastructure under /etc/pki/ and integrate naturally with services like Apache HTTPD and Nginx. Regularly auditing certificate expiry dates, keeping CA private keys offline where possible, and automating renewal with cron jobs or tools like Certbot will keep your PKI healthy over time.