Secure Apache With Let’s Encrypt on Ubuntu: The TLS Checklist That Matters
A practical Learning Hub checklist for getting Apache onto trusted HTTPS with Certbot, then hardening renewal, firewall, and TLS settings before calling the job done.
Putting Apache behind a valid certificate is easy to start and easy to half-finish. The real job is not just getting the browser lock icon once. It is proving that the domain validates cleanly, the firewall permits renewal, TLS avoids outdated protocols, and Certbot will keep renewing without someone remembering a calendar date.
Table Of Content
- Start with ownership, not encryption
- Prerequisites to verify
- The minimum safe path
- Commands to adapt on the server
- Firewall and validation are part of TLS
- Renewal proof is the real finish line
- Harden what Certbot does not decide
- TLS, renewal, and headers
- Do not fight rate limits in production
- Final verification checklist
- Operational appendix: prove the certificate path before you call it done
- Target system: DNS/admin workstation
- Target system: Ubuntu Apache host
- Target system: Ubuntu Apache host, staging before production when uncertain
- Target system: Ubuntu Apache host after issuance
- Failure modes to document
This checklist is based on DigitalOcean’s refreshed guide to securing Apache with Let’s Encrypt on Ubuntu, with cross-checks against Certbot’s Apache instructions and Let’s Encrypt’s own getting-started guidance.
Start with ownership, not encryption
Let’s Encrypt issues certificates through the ACME protocol, which means the certificate request must prove control of the hostname. Before installing anything, confirm that the domain’s A or AAAA record points at the Apache server and that the Apache virtual host contains the intended ServerName and any ServerAlias names.
Prerequisites to verify
- Ubuntu 22.04 LTS, 24.04 LTS, or a current Ubuntu release supported by your host.
- Apache 2.4 installed and serving the correct virtual host on port 80.
- A non-root sudo user and a firewall policy you understand.
- DNS records for both apex and
wwwnames if both will appear on the certificate.
The minimum safe path
DigitalOcean and Certbot both point modern Ubuntu users toward the snap-based Certbot package. The common sequence is to install snapd if needed, install Certbot with classic confinement, ensure the certbot command is on the path, and then run the Apache installer for the target hostnames.
Commands to adapt on the server
sudo snap install --classic certbotinstalls the Certbot client recommended by the Certbot project for Ubuntu snap setups.sudo ln -s /snap/bin/certbot /usr/bin/certbotmakes the command available in the usual path if the symlink is not already present.sudo certbot --apacherequests the certificate and lets Certbot update the matching Apache virtual host.
Do not copy these blindly onto a server you have not inspected. Confirm the OS, Apache site file, DNS records, and firewall first; then use Certbot’s live instruction page for the final command path.
Firewall and validation are part of TLS
For HTTP-01 validation, Let’s Encrypt needs to reach the server on port 80. Closing HTTP after enabling HTTPS can break future renewals unless you use a different validation method such as DNS-01. If UFW is active, DigitalOcean’s guide recommends allowing the Apache Full profile so both HTTP and HTTPS are open.
Renewal proof is the real finish line
Let’s Encrypt certificates are intentionally short-lived. The useful verification step is sudo certbot renew --dry-run, which exercises the renewal flow without waiting for the production certificate to approach expiry. Certbot installs a systemd timer or cron path for automatic renewal; inspect it after the first successful issuance.
Harden what Certbot does not decide
Certbot enables HTTPS, but it does not answer every security policy question for your site. Review Apache’s SSL configuration and disable obsolete protocol versions such as TLS 1.0 and TLS 1.1. Add security headers deliberately, especially HSTS, only after you are sure every required hostname works over HTTPS.
TLS, renewal, and headers
A practical hardening pass should check TLS 1.2 and TLS 1.3 support, redirects from HTTP to HTTPS, certificate-chain validity, and response headers such as HSTS, X-Content-Type-Options, and a sensible Referrer-Policy. For Let’s Encrypt certificates issued after OCSP support ended, focus on the certificate chain and renewal path rather than trying to enable OCSP stapling. Run an external scan such as SSL Labs after the configuration is reloaded.
Do not fight rate limits in production
Let’s Encrypt publishes rate limits to keep the service reliable. The current documentation says production testing should avoid repeated failed issuance attempts and recommends the staging environment while debugging integrations. The rate-limits page also notes that revoking certificates does not reset issuance limits.
Final verification checklist
- The site loads at
https://your_domainand the browser reports a trusted certificate. - Both apex and
wwwhostnames are covered if both are public entry points. - Port 80 remains reachable for HTTP-01 validation or DNS-01 is intentionally configured.
sudo certbot renew --dry-runsucceeds.- Apache reloads cleanly after TLS and header changes.
- An external TLS scan confirms the expected protocols, ciphers, and certificate chain.
When all six checks pass, HTTPS is not just enabled. It is operational.
Operational appendix: prove the certificate path before you call it done
Use this as a runbook for an Ubuntu Apache host, not as a generic TLS checklist. Let’s Encrypt validation, Certbot’s Apache installer, Apache virtual-host selection, and Ubuntu firewall rules all have to line up. The safest habit is to verify DNS, Apache’s view of the site, the firewall, issuance, reload, and renewal as separate steps.
Target system: DNS/admin workstation
dig +short A example.com
dig +short AAAA example.com
curl -I http://example.com/
For HTTP-01 validation, Let’s Encrypt must be able to reach the requested hostname over HTTP on port 80. A redirect from HTTP to HTTPS is fine after the site is configured, but a timeout, wrong server, closed firewall, or DNS record pointing at an old host will cause validation to fail. If both example.com and www.example.com are on the certificate, verify both names before requesting issuance. Let’s Encrypt challenge types
Target system: Ubuntu Apache host
sudo apache2ctl -S
sudo apache2ctl configtest
sudo ufw status verbose
sudo ufw app list
sudo ufw allow 'Apache Full'
apache2ctl -S shows which virtual hosts Apache believes are active, including the configured ServerName and aliases. apache2ctl configtest catches syntax errors before Certbot or a manual reload touches the running service. Apache documents apachectl as the control interface for syntax checks and server control. Apache apachectl docs On UFW-managed Ubuntu hosts, the Apache Full application profile permits both HTTP and HTTPS; that matters because closing port 80 can break future HTTP-01 renewals unless you intentionally use DNS-01 instead. Ubuntu firewall docs
Target system: Ubuntu Apache host, staging before production when uncertain
sudo snap install --classic certbot
sudo ln -sf /snap/bin/certbot /usr/bin/certbot
sudo certbot --apache --staging -d example.com -d www.example.com
sudo certbot --apache -d example.com -d www.example.com
Certbot’s Apache instructions for snap-based installs are the right baseline for current Ubuntu deployments. Use Let’s Encrypt staging while debugging DNS, virtual hosts, proxies, or firewall changes. Staging certificates are not trusted by browsers, but they protect the production account and hostname from avoidable rate-limit pain. Move to the production command only after the staging run succeeds for the exact hostnames you intend to serve. Certbot Apache snap instructions Let’s Encrypt rate limits
Target system: Ubuntu Apache host after issuance
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo certbot certificates
sudo certbot renew --dry-run
systemctl list-timers 'snap.certbot*' --no-pager
The finish line is not “Certbot printed Congratulations.” Confirm Apache still parses cleanly, reloads without error, Certbot lists the expected names, and certbot renew --dry-run completes. Certbot documents renewal behavior and dry-run testing, which is why the renewal test belongs in the article instead of being left to memory. Certbot renewal docs The timer check verifies that automatic renewal is installed for the snap path. If the dry run fails, inspect whether port 80 is reachable from the public internet, whether the vhost still serves the requested name, whether a reverse proxy is intercepting /.well-known/acme-challenge/, or whether a firewall rule differs between IPv4 and IPv6.
Failure modes to document
- Wrong vhost: Certbot updates a default site because Apache lacks the intended
ServerName. - IPv6 drift: the AAAA record points to a host that does not serve the same Apache site.
- Renewal outage: port 80 was closed after issuance without switching to DNS-01 validation.
- Premature HSTS: HSTS is enabled before every required hostname works over HTTPS.
- Protocol debt: TLS is enabled, but Apache still allows obsolete protocols that should be disabled in the
mod_sslconfiguration. Apache mod_ssl docs
Featured image: “Server room at CERN” by torkildr, licensed under CC BY-SA 2.0.








No Comment! Be the first one.