All Deployment guides Deployment

How to Install an SSL Certificate on Apache

This guide walks you through installing an SSL certificate on Apache HTTP Server using mod_ssl — from uploading files to hardened TLS settings and troubleshooting common errors. Works with certificates from GetHTTPS, Certbot, or any CA.

If you don’t have a certificate yet, get one for free in 5 minutes.

Prerequisites

  • Apache 2.4+ installed and serving your site on HTTP (port 80)
  • Root/sudo access to the server
  • Certificate files — Apache needs three separate files:
    • cert.pem — your certificate (end-entity only)
    • privkey.pem — your private key
    • chain.pem — intermediate CA certificate chain

Why three files? Unlike Nginx (which uses a single fullchain.pem), Apache traditionally expects the certificate and chain as separate files. Apache 2.4.8+ can use fullchain.pem in SSLCertificateFile and skip SSLCertificateChainFile. Format details →

Step 1: Upload certificate files

# Create a secure directory
sudo mkdir -p /etc/ssl/gethttps

# Copy files to the server
sudo cp cert.pem chain.pem privkey.pem /etc/ssl/gethttps/

# Lock down the private key
sudo chmod 600 /etc/ssl/gethttps/privkey.pem
sudo chmod 644 /etc/ssl/gethttps/cert.pem /etc/ssl/gethttps/chain.pem
sudo chown root:root /etc/ssl/gethttps/*

If transferring via SCP:

scp cert.pem chain.pem privkey.pem user@your-server:/tmp/
# On the server:
sudo mv /tmp/{cert,chain,privkey}.pem /etc/ssl/gethttps/

Step 2: Enable required Apache modules

# Debian/Ubuntu
sudo a2enmod ssl        # Core SSL module
sudo a2enmod headers    # For HSTS and security headers
sudo a2enmod rewrite    # For HTTP→HTTPS redirect (if using .htaccess)
sudo systemctl restart apache2

# CentOS/RHEL/Amazon Linux
sudo yum install mod_ssl    # Usually installs and enables in one step
sudo systemctl restart httpd

Verify mod_ssl is loaded:

apachectl -M | grep ssl
# Expected: ssl_module (shared)

Step 3: Configure the HTTPS VirtualHost

Create or edit your site’s SSL config. On Debian/Ubuntu, this is typically /etc/apache2/sites-available/yourdomain-ssl.conf:

# ─── HTTPS server ────────────────────────────
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com

    # Certificate files
    SSLEngine on
    SSLCertificateFile      /etc/ssl/gethttps/cert.pem
    SSLCertificateKeyFile   /etc/ssl/gethttps/privkey.pem
    SSLCertificateChainFile /etc/ssl/gethttps/chain.pem

    # TLS protocol — only 1.2 and 1.3
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLHonorCipherOrder off
    SSLCompression off

    # OCSP stapling (faster cert verification for clients)
    SSLUseStapling on
    SSLStaplingCache "shmcb:/var/run/apache2/ssl_stapling(128000)"

    # Security headers
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"

    # Your site
    DocumentRoot /var/www/html
    <Directory /var/www/html>
        AllowOverride All
    </Directory>
</VirtualHost>

# ─── HTTP redirect ───────────────────────────
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    Redirect permanent / https://example.com/
</VirtualHost>

What each directive does:

DirectivePurpose
SSLEngine onEnables SSL/TLS for this VirtualHost
SSLCertificateFilePath to your certificate
SSLCertificateKeyFilePath to your private key
SSLCertificateChainFilePath to intermediate CA certificate
SSLProtocolOnly TLS 1.2/1.3 — older versions deprecated
SSLHonorCipherOrder offLet the client pick the best cipher
SSLCompression offPrevents CRIME attack
SSLUseStaplingServer pre-fetches OCSP response
Strict-Transport-SecurityHSTS — browsers remember to always use HTTPS
Redirect permanent301 redirect HTTP → HTTPS

Step 4: Enable the site and test

# Debian/Ubuntu
sudo a2ensite yourdomain-ssl.conf
sudo apachectl configtest          # Must say "Syntax OK"
sudo systemctl reload apache2

# CentOS/RHEL
sudo apachectl configtest
sudo systemctl reload httpd

If configtest reports an error, it tells you the exact line — fix it before reloading.

Step 5: Verify

Browser: Visit https://yourdomain.com. Click the padlock → verify “Let’s Encrypt” as issuer.

Command line:

echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

Online: Use SSL Labs Server Test for a comprehensive grade. Target: A or A+.

Apache vs Nginx: certificate file differences

ApacheNginx
CertificateSSLCertificateFile cert.pemssl_certificate fullchain.pem
Private keySSLCertificateKeyFile privkey.pemssl_certificate_key privkey.pem
ChainSSLCertificateChainFile chain.pemIncluded in fullchain.pem
Files needed3 separate files2 files (chain combined)

Apache 2.4.8+ can also use the combined fullchain.pem in SSLCertificateFile — then you can omit SSLCertificateChainFile.

Renewal

When your certificate approaches expiry (check here):

# Replace files
sudo cp new-cert.pem /etc/ssl/gethttps/cert.pem
sudo cp new-chain.pem /etc/ssl/gethttps/chain.pem
sudo cp new-privkey.pem /etc/ssl/gethttps/privkey.pem

# Reload (not restart) — zero downtime
sudo systemctl reload apache2    # Debian/Ubuntu
sudo systemctl reload httpd      # CentOS/RHEL

Full renewal guide → | Automate with Certbot →

Troubleshooting

”AH02572: Failed to configure certificate” / key mismatch

The certificate and private key don’t correspond. Verify they match:

# These two hashes must be identical
openssl x509 -noout -modulus -in /etc/ssl/gethttps/cert.pem | md5sum
openssl rsa -noout -modulus -in /etc/ssl/gethttps/privkey.pem | md5sum

If they differ, you’re using files from different GetHTTPS sessions. Re-download both from the same session.

”AH01909: server certificate does NOT include an ID”

Your ServerName doesn’t match any domain in the certificate’s SAN field:

openssl x509 -noout -text -in /etc/ssl/gethttps/cert.pem | grep -A1 "Subject Alternative Name"

Make sure your Apache ServerName matches one of the listed DNS names exactly.

Browser shows “certificate not trusted”

Missing the intermediate chain. Verify SSLCertificateChainFile points to chain.pem (the intermediate), not cert.pem. Test the chain:

echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | grep "Verify return code"
# "Verify return code: 0 (ok)" = good
# "Verify return code: 21 (unable to verify)" = chain incomplete

“AH00526: Syntax error on line X”

Apache config syntax error. Common causes:

  • Missing closing </VirtualHost> tag
  • SSLCertificateChainFile misspelled
  • Missing quotes around header values
  • File path doesn’t exist

HTTPS works but shows “Not Secure”

Mixed content — your page loads resources over HTTP. Open DevTools → Console → fix the http:// URLs.

Frequently asked questions

Can I use fullchain.pem instead of separate cert + chain?

Yes, on Apache 2.4.8+. Use SSLCertificateFile /path/to/fullchain.pem and remove the SSLCertificateChainFile directive entirely. On older Apache, you need separate files.

How do I check which Apache version I have?

apachectl -v
# or
httpd -v

Do I need to restart Apache or just reload?

Reload (systemctl reload) is sufficient and causes zero downtime. Restart (systemctl restart) drops all active connections. Always reload for certificate changes.

Can Apache serve different certificates for different domains?

Yes. Create separate <VirtualHost *:443> blocks with different ServerName and SSLCertificate* directives. Apache uses SNI (Server Name Indication) to select the correct certificate.

Does Apache support ECDSA certificates?

Yes. Apache 2.4+ handles ECDSA the same way as RSA — same directives, same file format. GetHTTPS generates ECDSA P-256 by default.

Where are Apache’s SSL error logs?

# Debian/Ubuntu
tail -f /var/log/apache2/error.log

# CentOS/RHEL
tail -f /var/log/httpd/ssl_error_log

Related articles

Getting Started 2026-05-08
How to Get a Free SSL Certificate (Step-by-Step Guide)
Get a free SSL certificate from Let's Encrypt in 5 minutes — no software to install, no account to create. Complete guide covering 4 methods, both challenge types, installation on 6 platforms, and troubleshooting.
Deployment 2026-05-07
How to Redirect HTTP to HTTPS
Force all traffic to HTTPS with server-side redirects. Configuration examples for Nginx, Apache, and .htaccess with 301 permanent redirects.
Deployment 2026-05-08
How to Install an SSL Certificate on Nginx
Step-by-step guide to installing an SSL certificate on Nginx. Covers file upload, full server block config, TLS best practices, HTTP/2, HSTS, redirect setup, testing, and troubleshooting 6 common errors.
Deployment 2026-05-07
How to Fix Mixed Content Warnings
Mixed content happens when an HTTPS page loads resources over HTTP. Learn how to find and fix mixed content errors to get a clean padlock icon.
Get a free SSL certificate in your browser
No installation, no account. Your private key never leaves your device.
Get your certificate