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
opensslpackage installed (included by default)firewalldallowing 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.