keepcalculator

06 Numbers and Powers

Fix Let’s Encrypt Certificate Errors on Apache

Card No. 06·21435 · Updated · Standard formula, shown below

Let’s Encrypt certificate errors on Apache usually appear as browser warnings like “Your connection is not private” or “NET::ERR_CERT_DATE_INVALID”. These errors happen when the certificate is expired, the web server isn’t serving the correct certificate, or the automatic renewal isn’t working. This guide walks you through diagnosing and fixing the most common causes, from checking certificate expiry to reconfiguring virtual hosts and forcing renewal.

What You’ll Need

  • SSH (terminal) access to your server with sudo privileges
  • Your Apache configuration files located in /etc/apache2/ (Debian/Ubuntu) or /etc/httpd/ (RHEL/CentOS)
  • The Certbot client installed (usually via certbot package)
  • Your domain name and the path to your web root (e.g., /var/www/html)

Step-by-Step

  1. Identify the exact error. Open your browser’s error page and click “Advanced” or “More information”. Note the error code (e.g., SEC_ERROR_EXPIRED_CERTIFICATE, SSL_ERROR_BAD_CERT_DOMAIN). This tells you whether the problem is expiry, domain mismatch, or something else.
  2. Check certificate expiry. Run sudo certbot certificates to list all certificates managed by Certbot. Look for the Expiry Date of your domain. If it’s in the past, the certificate is expired and needs renewal.
  3. Test the renewal process. Run sudo certbot renew --dry-run. This simulates renewal without actually changing anything. If it fails, you’ll see the error (often a DNS issue or port 80 blocked). Fix that first before proceeding.
  4. Force renewal if needed. If the certificate is expired or the dry run succeeds but the real renewal didn’t happen, run sudo certbot renew --force-renewal. This will obtain a new certificate and automatically reload Apache if the Certbot Apache plugin is installed.
  5. Verify the certificate is being served. After renewal, check which certificate Apache is actually using: sudo openssl s_client -connect yourdomain.com:443 -servername yourdomain.com (replace yourdomain.com). Look for the subject and issuer lines. The issuer should be R3 or similar Let’s Encrypt root. If it’s a self-signed or old certificate, Apache is pointing to the wrong file.
  6. Check Apache virtual host configuration. Open your site’s SSL config file (e.g., /etc/apache2/sites-available/yourdomain-le-ssl.conf). Ensure the SSLCertificateFile and SSLCertificateKeyFile paths match the ones shown in sudo certbot certificates (usually under /etc/letsencrypt/live/yourdomain/). Also verify that SSLCertificateChainFile or SSLCACertificateFile points to chain.pem or fullchain.pem.
  7. Test Apache configuration. Run sudo apachectl configtest (or sudo httpd -t on RHEL). Fix any syntax errors it reports. Then reload Apache: sudo systemctl reload apache2 (or sudo systemctl reload httpd).
  8. Check port 80 is open. Let’s Encrypt HTTP-01 challenge requires port 80 to be reachable from the internet. Use sudo netstat -tulpn | grep :80 to see if Apache is listening. If a firewall blocks it, open port 80 (and 443) in your firewall settings.
  9. Verify renewal timer. Ensure the systemd timer for Certbot is enabled: sudo systemctl list-timers | grep certbot. If it’s not there, enable it with sudo systemctl enable --now certbot.timer (Debian/Ubuntu) or set up a cron job.
  10. Test the site in a browser. After all fixes, clear your browser cache or use an incognito window to visit your domain. The padlock should appear. Use an online SSL checker (like SSL Labs) to confirm the certificate chain is valid.

Common Mistakes

  • Forgetting to renew before expiry. Let’s Encrypt certificates last 90 days. If your renewal cron/timer isn’t running, you’ll hit expiry. Always test the renewal process after setup.
  • Wrong file paths in Apache config. Copy-pasting config from a tutorial but not updating the domain name in the SSLCertificateFile paths is a classic error. Always use the exact paths from certbot certificates.
  • Blocking port 80. Many firewalls only allow 443. The HTTP-01 challenge needs port 80 open, even if you redirect all HTTP to HTTPS. If port 80 is blocked, renewal fails silently.
  • Editing the wrong virtual host. Apache may load a default SSL config that overrides yours. Use sudo apachectl -S to see which virtual hosts are actually loaded and on which ports.
  • Not reloading Apache after renewal. Certbot usually reloads Apache automatically, but if you manually renew or change config, you must reload Apache to apply the new certificate.

Tips

  • Set up a cron job to renew certificates twice a day: 0 0,12 * * * certbot renew --quiet. This ensures you never miss the 90-day window.
  • Use the Certbot Apache plugin (sudo certbot --apache) to automatically configure virtual hosts and handle renewals. It’s less error-prone than manual config.
  • Keep a backup of your Apache config before making changes: sudo cp /etc/apache2/sites-available/yourdomain-le-ssl.conf /etc/apache2/sites-available/yourdomain-le-ssl.conf.bak.
  • Monitor your certificate expiry with a service like UptimeRobot or a simple script that checks openssl s_client and alerts you a week before expiry.
  • If you use a CDN (like Cloudflare), ensure the SSL mode is set to “Full (strict)” so the CDN trusts your Let’s Encrypt certificate.

Troubleshooting

Renewal fails with “Failed to connect to host for DVSNI challenge”. This usually means port 80 is blocked or Apache isn’t listening. Check your firewall and that Apache is running. Also verify DNS resolves to your server’s IP.

Certificate renews but browser still shows error. Your browser may have cached the old certificate. Try a different browser or clear the SSL cache. Also check if you have multiple certificates for the same domain; Certbot may be renewing the wrong one.

Apache won’t start after config change. Run sudo apachectl configtest to see the exact syntax error. Common issues: missing closing tag, wrong path, or a typo in the certificate file name.

Certificate is valid but shows “Not Secure” for subdomains. Ensure your certificate covers all subdomains you use. If not, run sudo certbot --apache -d example.com -d www.example.com to expand the certificate.

Certbot says “No renewals were attempted” and exits. This means the certificate is not yet due for renewal. Check the expiry date; if it’s more than 30 days away, you can force renewal with --force-renewal.

Error “Certbot doesn’t know how to automatically configure the web server”. This happens when the Apache plugin is missing. Install it with sudo apt install python3-certbot-apache (Debian/Ubuntu) or sudo yum install python3-certbot-apache (RHEL).

Frequently Asked Questions

Q: How often do Let’s Encrypt certificates expire?
A: Every 90 days. You must renew before that, and automatic renewal is essential.

Q: What is the difference between fullchain.pem and cert.pem?
A: cert.pem is just your certificate; fullchain.pem includes the intermediate certificates. Apache should use fullchain.pem to ensure browsers trust the chain.

Q: Can I use the same certificate for multiple domains?
A: Yes, use a SAN certificate by specifying multiple -d flags when issuing. For example: sudo certbot --apache -d example.com -d www.example.com -d api.example.com.

Q: Why does my certificate show as “self-signed” in the browser?
A: This usually means Apache is pointing to a self-signed certificate file instead of the Let’s Encrypt one. Check the SSLCertificateFile path in your virtual host.

Q: What if I can’t access port 80 from the internet?
A: You can use the DNS-01 challenge instead of HTTP-01. Run sudo certbot --apache --preferred-challenges dns and follow the prompts to add a TXT record to your DNS.

Q: How do I check if my certificate is installed correctly?
A: Use an online SSL checker or run openssl s_client -connect yourdomain.com:443 -servername yourdomain.com and look for the issuer and validity dates.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →