Installing an SSL certificate isn't difficult, but the official documentation often skips the bit that actually goes wrong: the certificate chain. Most failed installs are technically "successful" — the cert loads, the server starts — but the chain isn't complete, so visitors on iPhones or older browsers see security errors while the developer's desktop Chrome works fine.
This guide covers the three setups we see most often: nginx, Apache, and cPanel. For each, we cover the automated path (Let's Encrypt or AutoSSL) and the manual path (paid certificate from a commercial CA). After install, we walk through how to verify the install is actually correct, not just running.
Before You Start
You'll need:
- A domain pointed at the server you're installing on (DNS A or AAAA record resolving to the right IP).
- SSH or control panel access to the server.
- Port 80 and port 443 open in the firewall and any upstream load balancer or CDN. Let's Encrypt's HTTP challenge needs port 80 reachable; visitors need port 443.
- A working HTTP (port 80) version of the site already serving content. ACME clients use this to prove domain ownership.
If your DNS is behind Cloudflare or a similar CDN proxy, you'll typically install the certificate on the origin server and have a separate edge certificate at the CDN. Cloudflare provides free origin certificates specifically for this — they're trusted by Cloudflare but not by browsers, which is fine because browsers only ever see Cloudflare's edge cert.
Installing Let's Encrypt on nginx (Linux)
The standard tool is Certbot. On Ubuntu, Debian, and most modern distros:
- Install Certbot and the nginx plugin:
sudo apt install certbot python3-certbot-nginx(or the equivalent for your distro). - Make sure your nginx config has a
server { listen 80; server_name example.com www.example.com; }block for the domains you're securing. - Run
sudo certbot --nginx -d example.com -d www.example.com. Certbot will obtain the certificate, edit your nginx config to enable HTTPS, and reload nginx. - When prompted, choose to redirect all HTTP traffic to HTTPS. This sets up a 301 redirect from port 80 to port 443.
- Certbot installs a systemd timer (or cron job) that automatically renews the certificate every 60 days. Verify with
sudo systemctl list-timers | grep certbot.
That's it. The cert and chain are stored in /etc/letsencrypt/live/example.com/. The full chain is in fullchain.pem, and the private key is in privkey.pem. Certbot's nginx plugin points to these correctly by default — don't move them.
Installing Let's Encrypt on Apache (Linux)
Almost identical to nginx:
- Install Certbot with the Apache plugin:
sudo apt install certbot python3-certbot-apache. - Confirm your
VirtualHost *:80for the domain is configured and resolving. - Run
sudo certbot --apache -d example.com -d www.example.com. - Choose redirect, let Certbot edit your Apache config and reload.
Certbot creates a new SSL VirtualHost *:443 in /etc/apache2/sites-enabled/ with the correct paths. The SSLCertificateFile directive should point to fullchain.pem, not cert.pem — if Certbot configured it with cert.pem on an older Apache version, change it to fullchain.pem manually so the intermediate is included.
Installing on cPanel (AutoSSL)
cPanel includes AutoSSL, a free certificate service powered by either Let's Encrypt or Sectigo (depending on the host's configuration). For most users, this is the right choice — it's automated, free, and renews on its own.
- Log into cPanel.
- Go to Security → SSL/TLS Status.
- Find the domain you want to secure. If AutoSSL is enabled at the host level, you'll see a status indicator. If not, click Run AutoSSL and wait — issuance usually takes under a minute.
- Refresh and confirm the status shows a valid certificate covering the domain and its
wwwsubdomain.
If AutoSSL doesn't run, the most common cause is a DNS check failure — AutoSSL verifies the domain points to the cPanel server before issuing. Make sure the domain's A record matches the server's IP, then run AutoSSL again. If you've recently changed nameservers or DNS records, allow a few hours for propagation.
Manually Installing a Paid Certificate (cPanel)
If you've bought a certificate from a commercial CA, you'll have three things from them:
- The certificate file (
example_com.crtor similar). - The CA bundle / intermediate certificates (
example_com.ca-bundle). - The private key — generated either when you submitted the CSR, or by your CA's portal.
To install:
- In cPanel, go to Security → SSL/TLS → Install and Manage SSL for your site (HTTPS).
- Select the domain.
- Paste the certificate into the Certificate (CRT) box.
- Paste the private key into the Private Key (KEY) box. cPanel may auto-fill this if it generated the CSR.
- Paste the CA bundle into the Certificate Authority Bundle (CABUNDLE) box. Don't skip this step — without it, your chain will be incomplete.
- Click Install Certificate.
Refresh the page and you should see the certificate listed as installed. Then test it (see "Verifying the Install" below).
Manually Installing a Paid Certificate on nginx
From the CA, you'll have a cert.crt (your domain certificate) and a chain.crt or ca-bundle.crt (intermediates). nginx wants these concatenated into a single fullchain file, with your domain certificate first.
cat cert.crt chain.crt > /etc/ssl/certs/example.com.fullchain.pem
chmod 644 /etc/ssl/certs/example.com.fullchain.pem
# move the private key into place, restrict its permissions
mv privatekey.key /etc/ssl/private/example.com.key
chmod 600 /etc/ssl/private/example.com.key
Then in your nginx server block:
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/certs/example.com.fullchain.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
# rest of config
}
Test the config with sudo nginx -t and reload with sudo systemctl reload nginx. The reload is graceful — open connections aren't dropped, so this is safe to run at any time.
Manually Installing a Paid Certificate on Apache
Apache wants the leaf cert and the intermediate chain in separate files, referenced by separate directives. In your VirtualHost:
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/example.com.ca-bundle
# rest of config
</VirtualHost>
Note: Apache 2.4.8+ supports SSLCertificateFile pointing to a fullchain file with the chain bundled in (the directive then includes the intermediates automatically), and SSLCertificateChainFile is deprecated. For Apache 2.4.8 or newer, prefer:
SSLCertificateFile /etc/ssl/certs/example.com.fullchain.pem
Run sudo apache2ctl configtest and reload with sudo systemctl reload apache2.
Setting Up the HTTP → HTTPS Redirect
Once HTTPS works, you want to force all traffic onto it. On nginx:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
On Apache, in the port-80 VirtualHost:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Use 301 (permanent), not 302. 302 prevents browsers and search engines from caching the redirect, which means every request continues to hit HTTP first — slower, and a small SEO penalty.
Verifying the Install
This is the step almost everyone skips, and it's the step that catches most install errors.
Run the domain through SSL Checker. Confirm:
- Grade is A or A+. Anything lower is a sign of a configuration issue.
- The certificate chain is complete — leaf, intermediate, root all listed. If you see only the leaf, you've installed without the intermediates and mobile browsers will fail.
- Both TLS 1.2 and TLS 1.3 are supported. If only TLS 1.2 shows up, your version of OpenSSL or the server may not support 1.3 — fine, but worth knowing. If TLS 1.0 or 1.1 are listed, disable them.
- The certificate covers all the hostnames you serve. Check the SAN list — if you serve
example.comandwww.example.com, both should be there. - Days remaining looks correct — 90 for Let's Encrypt, 365 for paid annual certs.
If anything looks off, fix it now before configuring monitoring or telling anyone the site is live. SSL issues are easier to fix in the install window than three months later when nobody remembers what changed.
Set Up Monitoring
Even with auto-renewal, you should be alerted before a cert expires. Add the domain to a monitoring tool — ModusOp tracks SSL across portfolios, or you can run periodic checks via SSL Checker on a calendar reminder.
Auto-renewal failure modes are real: a DNS provider changes their API, a Certbot version bump breaks an old plugin, the systemd timer gets accidentally disabled during a server upgrade. None of these are catastrophic if you have monitoring; all of them are catastrophic if you don't.
If Something Goes Wrong
The vast majority of install issues come down to:
- Missing intermediates — chain is incomplete, mobile clients fail. Reinstall with the full chain.
- Wrong key — server fails to start, often with a "key does not match certificate" error. Check that
privkey.pemmatches the cert (openssl x509 -noout -modulus -in cert.pem | openssl md5andopenssl rsa -noout -modulus -in privkey.pem | openssl md5should produce the same hash). - Firewall blocking 443 — install succeeds, but no one can connect. Check firewall and any cloud security groups.
- HTTP-only redirect loop — if you're behind a CDN, the CDN talks to your origin over HTTP but tells the origin the original request was HTTPS. Use the
X-Forwarded-Protoheader instead of checking the local protocol when deciding whether to redirect.
None of these are difficult to fix once identified. Run an SSL Checker scan as the final step of every install — it's a 10-second sanity check that prevents weeks of "it works on my laptop" debugging later.