Choose the path that matches your certificate
Apache does not care who issued the certificate. It needs three files in one VirtualHost block: the certificate, the private key, and the intermediate chain. How you get those files is the only real difference between the two paths.
| Free, automated | Purchased certificate | |
|---|---|---|
| Issuer | Let's Encrypt through certbot | A commercial CA, or WebJi for Sectigo |
| What you create first | Nothing; certbot makes the key | A CSR and a private key with OpenSSL |
| Where the files land | /etc/letsencrypt | Any folder you choose, commonly /etc/ssl/ |
| Renewal | Automatic via the certbot timer | Manual, at the CA's expiry date |
| Best for | Public sites that can answer an HTTP challenge | Wildcards, OV or EV validation, offline renewal windows |
If the certificate is already issued, skip to the VirtualHost section. If not, pick one of the two paths below; do not mix them on the same hostname.
Path A: certbot issues and configures it
certbot reads your Apache configuration, proves control of the domain, writes the certificate, and edits the VirtualHost for you. This is the faster path on Ubuntu and Debian, and it works on RHEL with the EPEL package.
- Install the plugin:
sudo apt install certbot python3-. On RHEL, enable EPEL first, thencertbot- apache sudo dnf install certbot python3-.certbot- apache - Enable the module and the default SSL site with
sudo a2enmod ssl, then restart Apache once so the module is loaded. - Run
sudo certbot --apache -d example.com -d www.example.com. Certbot offers to redirect HTTP to HTTPS; accept it unless something in front of Apache already handles that. - Test the renewal path with
sudo certbot renew --dry-run. A dry run that succeeds is the only proof renewal will work unattended.
Three things must be true for the challenge to pass: DNS for the domain points at this server, port 80 is reachable from the internet, and Apache is running. A CDN or proxy in front of the server can break the HTTP challenge, which is the usual reason a first attempt fails.
Path B: create the CSR and install the issued files
A purchased certificate is issued against a CSR you generate. The private key never leaves the server, and the CSR is the only part you paste into the order form.
- Generate the key and CSR in one command:
sudo openssl req -new -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csr. Answer the prompts; Common Name is the exact hostname. - Copy the CSR with
cat example.com.csrand paste it into the certificate order. Keep the .key file on the server and setchmod 600on it. - When the CA emails the files, you will have your certificate, an intermediate bundle, and sometimes a root. Upload the certificate and the intermediate bundle into one folder, for example
/etc/ssl/.example. com/ - Confirm the certificate matches the key before touching Apache:
openssl x509 -noout -modulus -in example.com.crt | openssl md5and the same against the key. The two hashes must be identical.
That modulus check saves an outage. A certificate installed against the wrong key makes Apache refuse to start, and the error names a mismatch rather than the file you swapped.
The VirtualHost block that serves 443
One block per hostname, listening on 443, with the three directives that matter. Keep it in /etc/apache2/ on Debian and /etc/httpd/conf.d/ on RHEL.
SSLEngine onand a<VirtualHost *:443>withServerNameandDocumentRootmatching the port 80 block exactly.SSLCertificateFilepoints at your certificate;SSLCertificateKepoints at the private key.yFile SSLCertificateChpoints at the intermediate bundle. On Apache 2.4.8 and later you can instead concatenate the certificate and intermediates into one fullchain file and use onlyainFile SSLCertificateFile.SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1drops the protocols browsers already refuse, without breaking modern clients.
Then enable the site and the module on Debian with sudo a2ensite example.com-ssl and sudo a2enmod ssl. On RHEL there is no a2ensite step; the conf.d file loads automatically.
For the redirect, put a RewriteEngine on and RewriteRule ^ https://%{ inside the port 80 block, or use Redirect permanent / https://. Test with curl -I http://example.com and look for a 301 pointing at the https address.
configtest, reload, and prove it worked
Never restart Apache with an untested configuration. One test command catches a typo before it takes every site on the server down.
- Run
sudo apachectl configtestand wait for Syntax OK. On RHEL usesudo httpd -t. - Reload rather than restart:
sudo systemctl reload apache2. A reload keeps existing connections alive. - Check the certificate the server actually presents:
openssl s_client -connect example.com:443 -servername example.comand read the subject, issuer, and verify return code. - Load the site in a browser and confirm the padlock, then open the developer console for mixed-content warnings from images or scripts still on http.
You know the install is complete when the certificate chain verifies without errors and the browser shows no warning. If the browser warns but openssl verifies, the problem is usually a page asset rather than the certificate.
Renewal, expiry, and moving the certificate
Let's Encrypt certificates last 90 days, and certbot's systemd timer renews them when about 30 days remain. Check the timer with systemctl list-timers | grep certbot, and keep the dry run in your monitoring so a broken challenge is caught weeks early rather than on expiry day.
A purchased certificate is your calendar's job. Note the expiry date when it is issued, renew 30 days before, and replace the files in place. Apache picks up new files on reload, so no configuration change is needed if the paths stay the same.
To move a certificate to another server, copy the certificate, the intermediate bundle, and the private key, keep the key at chmod 600 and owned by root, then paste the same VirtualHost block. Reissuing is better than copying when the old server will keep running, because two machines sharing one key cannot be audited separately.
Errors you will hit, and the fix
Apache fails loudly but vaguely. Match the message, check the file it names, and test again before changing anything else.
| Message | Cause | Fix |
|---|---|---|
| AH00526: SSLCerti | The path is wrong or the file was not uploaded | Use an absolute path and confirm with ls -l |
| SSL_ERROR_ | Plain HTTP is being served on 443, or another service owns the port | Check the VirtualHost listens on 443 with SSLEngine on, and run ss -tlnp | grep 443 |
| NET::ERR_ | The hostname is not in the certificate's SAN list | Reissue for that exact name, or fix ServerName and the www alias |
| unable to get local issuer certificate | The intermediate chain is missing | Add SSLCerti |
| Address already in use: AH00072 | Another web server or an old Apache process holds 80 or 443 | Stop the other service, then restart Apache |
Certificates from WebJi
Sectigo Positive SSL covers one domain and its www name for ₹1,800 per year before 18% GST, and the wildcard version covers a domain and all of its subdomains for ₹7,500 per year before GST. Both are issued as DV certificates, so validation is by email or DNS rather than paperwork.
Email support@webji.
Frequently Asked Questions
How do I install an SSL certificate on Apache?
With certbot, enable mod_ssl and run certbot --apache -d example.com, which writes the certificate and edits the VirtualHost. With a purchased certificate, add SSLCertificateFi
Where do SSLCertificateFile and the key go in Apache?
Inside the VirtualHost block that listens on 443. SSLCertificateFile points at the domain certificate, SSLCertificateKe
Why does Apache fail to start after I enable SSL?
Almost always a missing or mismatched file: a wrong path, a certificate paired with the wrong private key, or a missing chain. Run apachectl configtest for the exact line, then confirm the certificate and key modulus hashes match before restarting.
How do I redirect HTTP to HTTPS in Apache?
Add RewriteEngine on and RewriteRule ^ https://
How do I renew a Let's Encrypt certificate on Apache?
Certbot's systemd timer renews it automatically when about 30 days remain. Confirm with systemctl list-timers, then run certbot renew --dry-run to prove the challenge still works. After any manual renewal, reload Apache so it serves the new file.
What is the difference between the chain file and fullchain?
The chain file holds only the intermediate certificates. A fullchain file holds your certificate plus the intermediates in one file. Apache 2.4.8 and later accepts fullchain in SSLCertificateFi

