Serving web traffic over HTTPS requires a valid TLS certificate and a correctly configured web server. On RHEL 8, the openssl tool is available out of the box and lets you generate RSA keys, create certificate signing requests, and issue self-signed certificates entirely from the command line. Self-signed certificates are ideal for internal services, staging environments, or learning without the cost of a public CA. This guide covers the full workflow from key generation through configuring Apache or Nginx to use the certificate and verifying the result with curl.

Prerequisites

  • RHEL 8 server with Apache (httpd) or Nginx installed
  • Root or sudo access
  • openssl package installed (included by default)
  • firewalld allowing port 443

Step 1 — Generate an RSA Private Key

Create a dedicated directory to store your certificate files, then generate a 2048-bit RSA private key.

sudo mkdir -p /etc/ssl/myserver
cd /etc/ssl/myserver

sudo openssl genrsa -out server.key 2048
sudo chmod 600 server.key

The chmod 600 ensures only root can read the private key. Never share or expose this file.

Step 2 — Create a Certificate Signing Request (CSR)

Generate a CSR that encodes your server’s identity. The -subj flag passes the Distinguished Name non-interactively; adjust the values to match your organisation and hostname.

sudo openssl req -new 
  -key server.key 
  -out server.csr 
  -subj "/C=US/ST=California/L=San Francisco/O=MyOrg/CN=myserver.example.com"

The CN (Common Name) must match the hostname or IP address clients will use to reach the server, otherwise browsers will show a hostname mismatch warning even after accepting the self-signed cert.

Step 3 — Issue a Self-Signed Certificate

Sign the CSR with the private key to produce a certificate valid for 365 days.

sudo openssl x509 -req 
  -days 365 
  -in server.csr 
  -signkey server.key 
  -out server.crt

sudo chmod 644 server.crt

Confirm the certificate details with openssl x509 -text -noout -in server.crt | grep -E "Subject:|Not After".

Step 4 — Configure the Web Server SSL Block

For Apache, install mod_ssl and create a virtual host configuration. For Nginx, edit the server block to reference the key and certificate.

# Apache
sudo dnf install -y mod_ssl

sudo tee /etc/httpd/conf.d/ssl-myserver.conf > /dev/null <<'EOF'

    ServerName myserver.example.com
    SSLEngine on
    SSLCertificateFile    /etc/ssl/myserver/server.crt
    SSLCertificateKeyFile /etc/ssl/myserver/server.key
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    DocumentRoot /var/www/html

EOF

sudo systemctl reload httpd

# --- OR Nginx ---
sudo tee /etc/nginx/conf.d/ssl-myserver.conf > /dev/null <<'EOF'
server {
    listen 443 ssl;
    server_name myserver.example.com;
    ssl_certificate     /etc/ssl/myserver/server.crt;
    ssl_certificate_key /etc/ssl/myserver/server.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    root /usr/share/nginx/html;
}
EOF

sudo nginx -t && sudo systemctl reload nginx

Step 5 — Open Port 443 and Test the Connection

Allow HTTPS traffic through firewalld and verify the certificate is served correctly. The -k flag tells curl to skip certificate validation for self-signed certs.

sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

curl -k -v https://localhost 2>&1 | grep -E "SSL|TLS|subject:|expire"

You should see output confirming the TLS handshake succeeded and showing the certificate subject and expiry date.

Step 6 — Restrict to TLS 1.2 and TLS 1.3 Only

Older TLS versions (1.0 and 1.1) are deprecated and must be explicitly disabled. The configuration in Step 4 already sets this, but verify the active protocols.

openssl s_client -connect localhost:443 -tls1 2>&1 | grep "handshake"
# Expected: handshake failure — TLS 1.0 should be rejected

openssl s_client -connect localhost:443 -tls1_3 2>&1 | grep "Protocol"
# Expected: Protocol : TLSv1.3

Conclusion

You have generated a 2048-bit RSA key, created a CSR, issued a self-signed certificate, and configured your web server on RHEL 8 to serve HTTPS with TLS 1.2 and TLS 1.3 only. While self-signed certificates are not trusted by public browsers, this workflow mirrors production certificate management and is directly applicable when switching to a CA-issued certificate by replacing the .crt file.

Next steps: How to Set Up a LAMP Stack on RHEL 8, How to Harden Nginx: Security Headers, TLS 1.3 and OCSP Stapling on RHEL 8, and How to Configure Nginx WebSocket Proxying on RHEL 8.