SSL Certificate Setup - Apache web server
Category: Administration → Web Server
Applies To: Apache HTTP Server 2.4.x (Linux environments)
Issues Summary:
This document provides a step-by-step guide to configure SSL/TLS certificates on an Apache HTTP Web Server running on Red Hat Enterprise Linux (RHEL) 9. Enabling HTTPS is essential for encrypting web traffic, securing sensitive data, authenticating your server, and meeting modern web security standards. This guide leverages RHEL's standard directory structures and commands.
Key Concepts (Brief Overview)
SSL/TLS: Protocols for secure, encrypted communication over the internet.
SSL Certificate: A digital file that verifies your server's identity and enables encryption. It's issued by a trusted Certificate Authority (CA).
Key Pair: Consists of a Private Key (kept secret on the server) and a Public Key (embedded in the certificate).
CSR (Certificate Signing Request): A request file submitted to a CA containing your public key and domain information.
Chain of Trust: The hierarchy of certificates (Server -> Intermediate -> Root CA) that browsers use to verify your certificate's authenticity.
mod_ssl: The Apache module that handles SSL/TLS. It's typically installed and enabled by default with Apache on RHEL.
HTTPS: The secure version of HTTP, running over SSL/TLS (usually on port 443).
Step-by-Step Setup
Prerequisites:
Apache HTTP Server (httpd) installed: sudo dnf install httpd
mod_ssl module installed (usually part of httpd package): sudo dnf install mod_ssl (if not already installed).
Port 443 (default for HTTPS) must be open in your firewall.
Root or sudo access to the server.
Generate a Private Key
Description: Creates a unique, secret private key on your server. This key will be used to generate your CSR and later by Apache to decrypt traffic.
Standard RHEL Path: /etc/pki/tls/private/
Command:
sudo openssl genrsa -out /etc/pki/tls/private/your_domain_name.key 2048
Replace your_domain_name.key with a descriptive name related to your domain (e.g., www.example.com.key).
2048 bits is the recommended key length.
Permissions: Secure the private key to prevent unauthorized access.
sudo chmod 600 /etc/pki/tls/private/your_domain_name.key
Generate a Certificate Signing Request (CSR)
Description: This file contains your public key and identifiable information. You send this to your Certificate Authority (CA).
Standard RHEL Path: /etc/pki/tls/csr/
Command:
sudo openssl req -new -key /etc/pki/tls/private/your_domain_name.key -out /etc/pki/tls/csr/your_domain_name.csr
You will be prompted for various details. Crucially, for Common Name (e.g. server FQDN or YOUR name), enter your exact domain name (e.g., www.example.com or example.com). For a wildcard certificate, use *.example.com.
Leave "A challenge password" and "An optional company name" blank unless your CA specifically requires them.
Obtain Your SSL Certificate from a Certificate Authority (CA)
Process:
Submit the content of your your_domain_name.csr file to your chosen CA (e.g., Let's Encrypt, DigiCert, Comodo).
The CA will verify your domain ownership (e.g., via DNS record, email, or file upload).
Once verified, the CA will provide your certificate files.
Files You'll Receive:
Server Certificate: Your domain's primary certificate (e.g., your_domain_name.crt).
Intermediate Certificate(s): One or more certificates that link your server certificate to the CA's root (e.g., intermediate.crt, ca-bundle.crt).
Root Certificate: Usually not needed, as it's pre-installed in browsers.
Placement on RHEL: Copy these certificate files to the standard RHEL directory for certificates: /etc/pki/tls/certs/.
Configure Apache for SSL on RHEL 9
Description: Edit the main SSL configuration file for Apache on RHEL.
Configuration File: /etc/httpd/conf.d/ssl.conf
Edit the Virtual Host for Port 443:
Locate the <VirtualHost _default_:443> block in /etc/httpd/conf.d/ssl.conf (or create a new .conf file in conf.d for a dedicated virtual host).
nano /etc/httpd/conf.d/ssl.conf
<VirtualHost _default_:443>
# General Apache settings (ServerName, DocumentRoot, etc.)
ServerName your_domain_name.com
ServerAlias www.your_domain_name.com # If applicable
DocumentRoot "/var/www/html" # Your website's root directory
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 # Only allow TLS 1.2 and 1.3
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH # Strong, modern cipher suites
SSLHonorCipherOrder on
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" env=HTTPS
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
# Paths to your certificate files
SSLCertificateFile /etc/pki/tls/certs/your_domain_name.crt
SSLCertificateKeyFile /etc/pki/tls/private/your_domain_name.key
SSLCertificateChainFile /etc/pki/tls/certs/intermediate_certificate.crt
# OR, if your CA provided a bundle file containing your intermediate(s)
# SSLCertificateChainFile /etc/pki/tls/certs/your_domain_name_bundle.crt
<Files ".ht*">
Require all denied
</Files>
</VirtualHost>
Important Notes:
SSLCertificateFile: Path to your domain's certificate (e.g., your_domain_name.crt).
SSLCertificateKeyFile: Path to your private key (e.g., your_domain_name.key).
SSLCertificateChainFile: Path to the intermediate certificate(s) provided by your CA. For multiple intermediates, they should usually be concatenated into one file.
Security Directives: The SSLProtocol, SSLCipherSuite, SSLHonorCipherOrder, and Header directives are crucial for hardening your SSL configuration. Adjust SSLProtocol to only allow TLS 1.2 and 1.3 for modern security.
HSTS (Strict-Transport-Security): Forces browsers to use HTTPS for future visits. Enable only after confirming full SSL functionality.
Configure Firewall (Firewalld on RHEL 9)
Description: Allow HTTPS traffic through the firewall.
Commands:
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd -reload
Verify: sudo firewall-cmd --list-all
Test Apache Configuration and Restart
Test Syntax:
sudo apachectl configtest
You should see Syntax OK. If not, fix any reported errors.
Restart Apache:
sudo systemctl restart httpd
sudo systemctl enable httpd # Ensure Apache starts on boot
Verify SSL Installation
Open your web browser and navigate to https://your_domain_name.com.
Check the padlock icon in the address bar. Click to view certificate details (issuer, validity, common name).
Use online SSL checkers (e.g., https://www.ssllabs.com/ssltest/) to perform a deep analysis of your SSL configuration. Aim for an A or A+ rating.
Configure HTTP to HTTPS Redirection (Optional but Recommended)
Description: Automatically redirect all HTTP (port 80) traffic to HTTPS (port 443).
Edit Default HTTP Virtual Host: In /etc/httpd/conf/httpd.conf or a separate virtual host file in /etc/httpd/conf.d/ for port 80.
<VirtualHost *:80>
ServerName your_domain_name.com
ServerAlias www.your_domain_name.com
Redirect / https://your_domain_name.com/
</VirtualHost>
Restart Apache after making this change.
Additional Notes
SELinux Context: If you store your private key or certificate files in non-standard locations, or if you encounter permission-denied errors related to SELinux, you might need to adjust SELinux contexts:
sudo restorecon -Rv /etc/pki/tls/ (resets contexts to default).
If you use custom paths: sudo semanage fcontext -a -t httpd_cert_t "/path/to/your/custom/certs(/.*)?" and then sudo restorecon -Rv /path/to/your/custom/certs.
Let's Encrypt / Certbot: For automated certificate issuance and renewal, especially for a single domain, Certbot is highly recommended. It automatically handles key generation, CSR, certificate retrieval, and Apache configuration.
sudo dnf install certbot python3-certbot-apache
sudo certbot --apache -d your_domain_name.com -d www.your_domain_name.com
Certificate Renewal: Certificates have an expiration date. For Certbot, a cron job is usually set up for automatic renewal. For commercial CAs, ensure you have a process to renew certificates before they expire to prevent website downtime.
Troubleshooting:
Check Apache error logs: sudo tail -f /var/log/httpd/error_log or sudo journalctl -xeu httpd.
Verify file paths and permissions for all key and certificate files.
Double-check firewall rules.