SSL/TLS certificates are the foundation of encrypted communications on the internet, authenticating servers and encrypting data in transit. On RHEL 8, OpenSSL provides a full-featured toolkit for creating your own Certificate Authority, generating server certificates, and managing the entire certificate lifecycle. Understanding this process is essential for securing internal services without relying on external providers. This tutorial walks through every step from building a CA to verifying a signed certificate.
Prerequisites
- RHEL 8 server with sudo or root access
- OpenSSL installed (included by default on RHEL 8; verify with
openssl version) - Basic familiarity with public-key cryptography concepts
- A working directory with appropriate permissions for storing key material
Step 1 — Create a Private Certificate Authority
A Certificate Authority (CA) is the trust anchor that signs server certificates. Generate a 4096-bit RSA private key for the CA, then create a self-signed root certificate valid for five years.
mkdir -p ~/myCA/{certs,newcerts,private,csr}
chmod 700 ~/myCA/private
cd ~/myCA
# Generate CA private key
openssl genrsa -aes256 -out private/ca.key 4096
chmod 400 private/ca.key
# Generate self-signed CA root certificate (valid 1825 days = 5 years)
openssl req -x509 -new -nodes -key private/ca.key
-sha256 -days 1825
-subj "/C=US/ST=State/L=City/O=MyOrg/CN=MyOrg Root CA"
-out certs/ca.crt
# Verify the CA certificate
openssl x509 -in certs/ca.crt -text -noout | head -20
Step 2 — Generate a Server Private Key and Certificate Signing Request
Each server that needs a certificate requires its own private key and a Certificate Signing Request (CSR). The CSR contains the server’s identity information and public key, which the CA uses to produce the signed certificate.
# Generate server private key (no passphrase for automated services)
openssl genrsa -out ~/myCA/private/server.key 4096
chmod 400 ~/myCA/private/server.key
# Create a CSR configuration file with Subject Alternative Names
cat > ~/myCA/server.cnf <<EOF
[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[dn]
C=US
ST=State
L=City
O=MyOrg
CN=server.example.com
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = server.example.com
DNS.2 = www.server.example.com
IP.1 = 192.168.1.10
EOF
# Generate the CSR
openssl req -new -key ~/myCA/private/server.key
-config ~/myCA/server.cnf
-out ~/myCA/csr/server.csr
# Verify the CSR
openssl req -in ~/myCA/csr/server.csr -text -noout | grep -A5 "Subject:"
Step 3 — Sign the Server CSR with the CA
With the CA key and the server CSR in hand, sign the certificate. The -CAcreateserial flag generates a serial number file used to track issued certificates.
# Create an extension file for Subject Alternative Names
cat > ~/myCA/server_ext.cnf <<EOF
[v3_req]
subjectAltName = @alt_names
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = server.example.com
DNS.2 = www.server.example.com
IP.1 = 192.168.1.10
EOF
# Sign the CSR with the CA (valid 365 days)
openssl x509 -req
-in ~/myCA/csr/server.csr
-CA ~/myCA/certs/ca.crt
-CAkey ~/myCA/private/ca.key
-CAcreateserial
-out ~/myCA/certs/server.crt
-days 365
-sha256
-extfile ~/myCA/server_ext.cnf
-extensions v3_req
echo "Certificate signed successfully"
ls -lh ~/myCA/certs/
Step 4 — Verify the Signed Certificate
Always verify a newly signed certificate against the CA before deploying it. OpenSSL will output “OK” if the certificate chain is valid.
# Verify the server certificate against the CA
openssl verify -CAfile ~/myCA/certs/ca.crt ~/myCA/certs/server.crt
# Inspect the full certificate details
openssl x509 -in ~/myCA/certs/server.crt -text -noout
# Check the Subject Alternative Names specifically
openssl x509 -in ~/myCA/certs/server.crt -ext subjectAltName -noout
# Check certificate dates
openssl x509 -in ~/myCA/certs/server.crt -noout -dates
# Verify key matches the certificate (both should output the same hash)
openssl rsa -in ~/myCA/private/server.key -modulus -noout | openssl md5
openssl x509 -in ~/myCA/certs/server.crt -modulus -noout | openssl md5
Step 5 — Inspect and Convert Certificate Formats
Different services require certificates in different formats. OpenSSL can inspect PEM certificates in detail and convert between PEM, DER, and PKCS#12 formats.
# Detailed human-readable inspection of the certificate
openssl x509 -in ~/myCA/certs/server.crt -text -noout
# Convert PEM certificate to DER (binary) format
openssl x509 -in ~/myCA/certs/server.crt
-outform DER -out ~/myCA/certs/server.der
# Convert to PKCS#12 bundle (cert + key, for Java keystores or Windows)
openssl pkcs12 -export
-in ~/myCA/certs/server.crt
-inkey ~/myCA/private/server.key
-certfile ~/myCA/certs/ca.crt
-out ~/myCA/certs/server.p12
-name "server.example.com"
# Install CA cert so the system trusts it
sudo cp ~/myCA/certs/ca.crt /etc/pki/ca-trust/source/anchors/myorg-ca.crt
sudo update-ca-trust extract
trust list | grep "MyOrg"
Step 6 — Renewing and Revoking Certificates
Certificates expire and sometimes need to be revoked before expiry. Generate a Certificate Revocation List (CRL) and check certificate expiry dates proactively.
# Check days remaining before a certificate expires
openssl x509 -in ~/myCA/certs/server.crt -noout -enddate
# Script to warn if certificate expires within 30 days
EXPIRY=$(openssl x509 -in ~/myCA/certs/server.crt -noout -enddate
| cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
echo "Certificate expires in $DAYS_LEFT days"
# Re-sign with a new expiry (using the same CSR)
openssl x509 -req
-in ~/myCA/csr/server.csr
-CA ~/myCA/certs/ca.crt
-CAkey ~/myCA/private/ca.key
-CAserial ~/myCA/certs/ca.srl
-out ~/myCA/certs/server-renewed.crt
-days 365 -sha256
-extfile ~/myCA/server_ext.cnf
-extensions v3_req
Conclusion
You have built a complete internal PKI on RHEL 8: a root CA, server key and CSR, a signed certificate with Subject Alternative Names, verification against the CA, and format conversion utilities. This workflow is repeatable for any internal service — web servers, mail servers, or API endpoints — without incurring public CA costs. Always store CA private keys offline or in a hardware security module for production use, and set calendar reminders to renew certificates before they expire.
Next steps: Configuring Apache/Nginx with the signed certificate on RHEL 8, Setting up an OCSP responder for real-time certificate validation, and Automating certificate renewal with Certbot and Let’s Encrypt on RHEL 8.