Enabling HTTPS with a Let's Encrypt certificate protects logins, cookies, and API traffic from interception and tampering, while also eliminating modern browser “Not Secure” warnings. It also unlocks safer defaults like HTTP→HTTPS redirects and (once stable) HSTS for stricter transport security.
Let's Encrypt issues short-lived (90-day) certificates via the ACME protocol, typically using an HTTP-01 challenge on port 80 to prove domain control. certbot can request the certificate, write the Apache SSL virtual host configuration, store keys and certificates under /etc/letsencrypt, and keep renewals automated via systemd timers.
A correct DNS setup and real inbound reachability matter more than local tests, especially when a firewall, reverse proxy, or CDN sits in front of Apache. A broken .AAAA record (IPv6) can also cause validation failure even when IPv4 works, because the CA may try both. Treat Apache vhost edits as a production change, validate config syntax before reloads, and confirm automated renewal before enabling stricter policies like HSTS.
Steps to configure Let's Encrypt SSL in Apache:
- Confirm that the domain resolves to the server public IP address.
$ getent ahosts example.com | head -n 2 203.0.113.10 STREAM example.com 203.0.113.10 DGRAM example.com
- Confirm that Apache serves the site over HTTP on port 80.
$ curl -I http://example.com HTTP/1.1 200 OK Server: Apache/2.4.57 (Debian) ##### snipped #####
- Confirm that the Apache virtual host selection matches the intended site for the domain.
$ sudo apache2ctl -S VirtualHost configuration: *:80 example.com (/etc/apache2/sites-enabled/example.com.conf:1) ServerRoot: "/etc/apache2" ##### snipped #####
Multiple vhosts with overlapping ServerName or ServerAlias entries can cause certbot to edit the wrong site.
- Install certbot and the Apache plugin on Debian-style systems.
$ sudo apt update Hit:1 http://deb.debian.org/debian bookworm InRelease ##### snipped ##### $ sudo apt install --assume-yes certbot python3-certbot-apache ##### snipped #####
On RHEL-family systems, install with dnf install certbot python3-certbot-apache when available.
- Run certbot with the Apache plugin for the domain.
$ sudo certbot --apache -d example.com -d www.example.com Saving debug log to /var/log/letsencrypt/letsencrypt.log Requesting a certificate for example.com and www.example.com ##### snipped ##### Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem Deploying certificate ##### snipped #####
Use --test-cert for trial runs to avoid Let's Encrypt rate limits, and select the redirect option only when HTTP can safely be forced to HTTPS.
- Validate the Apache configuration syntax after the SSL vhost change.
$ sudo apache2ctl configtest Syntax OK
Reloading with a broken SSL vhost can take HTTPS offline for the entire server.
- Reload the Apache service to apply the SSL configuration.
$ sudo systemctl reload apache2
- Verify that the Apache service is active after the reload.
$ sudo systemctl status apache2 --no-pager ● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2025-12-13 11:58:04 UTC; 2min ago ##### snipped ##### - Verify HTTPS responses for the site.
$ curl -I https://example.com HTTP/2 200 server: Apache/2.4.57 (Debian) ##### snipped #####
- Verify that HTTP redirects to HTTPS when redirect is enabled.
$ curl -I http://example.com HTTP/1.1 301 Moved Permanently Location: https://example.com/ ##### snipped #####
- Verify the certificate chain and expiry served by the site using openssl.
$ echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -issuer -subject -dates issuer=C=US,O=Let's Encrypt,CN=R3 subject=CN=example.com notBefore=Dec 13 00:00:00 2025 GMT notAfter=Mar 13 23:59:59 2026 GMT
- Validate that the certbot renewal timer is active.
$ sudo systemctl status certbot.timer --no-pager ● certbot.timer - Run certbot twice daily Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled) Active: active (waiting) since Sat 2025-12-13 12:00:00 UTC; 1min ago Trigger: Sat 2025-12-13 12:19:02 UTC ##### snipped ##### - Perform a renewal dry run to confirm automated renewal works.
$ sudo certbot renew --dry-run Saving debug log to /var/log/letsencrypt/letsencrypt.log ##### snipped ##### Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/example.com/fullchain.pem (success)
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
