惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
J
Java Code Geeks
博客园 - 聂微东
量子位
C
Check Point Blog
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
B
Blog
罗磊的独立博客
腾讯CDC
GbyAI
GbyAI
博客园 - 【当耐特】
A
About on SuperTechFans
M
MIT News - Artificial intelligence
U
Unit 42
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Y
Y Combinator Blog
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队

DigitalOcean Community Tutorials

It's Time to Break Up with Your Cloud: Why AI Teams are Switching We Built a Private-Document AI App to Test Platform Security. Here Is What We Could Actually Verify. PostgreSQL Explained: A Complete Beginner-to-Advanced Guide How To Install and Configure Postfix on Ubuntu How To Build a Web Application Using Flask in Python 3 Build AI Reading List with DigitalOcean Functions and Mistral How To Concatenate Strings in Python How to Allow MySQL Remote Access Securely How To Install and Use Docker on Rocky Linux How To Build a Multi-Agent AI System with Docker Agent DSPy Use Cases: Build Optimized LLM Pipelines How To Submit AJAX Forms with jQuery Build an AI-Powered GPU Fleet Optimizer with the DigitalOcean AI Platform ADK Monitor GPU Utilization in Real Time: A Complete Guide Reduce File Size of Images in Linux - CLI and GUI methods Reduce PDF File Size in Linux: Tools and Methods How To Set Up a Private Docker Registry on Ubuntu How To Troubleshoot Terraform: Errors and Fixes How to Use Go Modules Python Multiprocessing Example: Process, Pool & Queue Convert Class Components to Functional Components with React Hooks How To Install and Configure Ansible on Ubuntu LLM Tokenizers Simplified: BPE, SentencePiece, and More How To Monitor System Authentication Logs on Ubuntu How to Use Traceroute and MTR to Diagnose Network Issues How to Deploy Postgres to Kubernetes Cluster Importing Packages in Go: A Complete Guide Create RAID Arrays with mdadm on Ubuntu How To Make an HTTP Server in Go How To Set Up Time Synchronization on Ubuntu
How To Secure Apache with Let's Encrypt on Ubuntu
Anish Singh Walia · 2022-04-27 · via DigitalOcean Community Tutorials

Introduction

How to secure Apache with Let’s Encrypt on Ubuntu: you install Certbot, point Apache at your domain with a virtual host, run sudo certbot --apache, then harden TLS and confirm automatic renewal. When you finish, visitors reach your site over HTTPS with a trusted certificate from Let’s Encrypt, a nonprofit certificate authority operated by the Internet Security Research Group (ISRG).

Let’s Encrypt issues free domain-validated (DV) TLS certificates. Certbot is the recommended ACME client on Ubuntu. It requests the certificate, proves you control the domain, and updates Apache for HTTPS.

This tutorial is for Ubuntu 22.04 LTS, 24.04 LTS (Noble Numbat), and 26.04 LTS (Resolute Raccoon) with Apache 2.4. You use a dedicated virtual host file (not the default site alone). If you still run Ubuntu 20.04, see the Ubuntu 20.04 version of this tutorial.

Version note: Commands were checked against Ubuntu 22.04, 24.04, and 26.04 LTS with Apache from the default repositories. Ubuntu 26.04 LTS shipped in April 2026. Certbot installs through snap per EFF instructions, not the older apt install certbot path. Renewal uses a systemd timer (often snap.certbot.renew.timer on snap installs).

Key takeaways

  • Install Certbot with sudo snap install --classic certbot and link /snap/bin/certbot into your PATH.
  • Apache needs correct ServerName and ServerAlias in a virtual host before you run sudo certbot --apache.
  • Open HTTPS in UFW with sudo ufw allow 'Apache Full' and remove the plain Apache profile if it is redundant.
  • Let’s Encrypt certificates are valid for 90 days. Certbot renews when a cert is within 30 days of expiry.
  • Harden TLS in /etc/apache2/mods-available/ssl.conf or a custom conf file: disable TLS 1.0/1.1, enable OCSP stapling, and add HSTS with mod_headers.
  • Test renewal with sudo certbot renew --dry-run and inspect /var/log/letsencrypt/letsencrypt.log if something fails.
  • Rate limits apply: see Let’s Encrypt rate limits (for example, 50 certificates per registered domain per week).
  • On Ubuntu 26.04 LTS, the same snap-based Certbot and Apache paths apply. Confirm versions with lsb_release, apache2 -v, and openssl version.

How Let’s Encrypt certificate issuance works

Here is a simplified flow of how Let’s Encrypt certificate issuance works:

Flowchart showing HTTPS traffic from a visitor browser to Apache using a Let's Encrypt certificate, initial Certbot HTTP-01 validation on port 80 against the Let's Encrypt ACME API, and automatic renewal via a systemd timer

Figure: Serving HTTPS, first-time certificate issuance with Certbot, and automatic renewal on Ubuntu.

  1. Your browser requests https://your_domain.
  2. Apache presents the certificate from /etc/letsencrypt/live/your_domain/.
  3. When you first run Certbot, it places a temporary challenge file or uses an Apache plugin to prove domain control on port 80.
  4. Let’s Encrypt’s ACME API issues the certificate. Certbot stores keys on your server (Let’s Encrypt never holds your private key).
  5. A systemd timer runs certbot renew twice per day and renews certs before they expire.

Port 80 must reach your server for HTTP-01 validation unless you use a DNS plugin for wildcards.

Prerequisites

To follow this tutorial, you need:

Verify your environment

Run these checks on the server before you install or renew certificates. They help you confirm you are on a supported LTS release and that Apache is ready.

Check the Ubuntu release:

  1. lsb_release -ds

You should see Ubuntu 22.04.x LTS, Ubuntu 24.04.x LTS, or Ubuntu 26.04.x LTS.

Confirm Apache is installed and note the version (package numbers change with security updates):

  1. apache2 -v

Example first line on current LTS images:

Server version: Apache/2.4.58 (Ubuntu)

Your output may differ on 22.04 or 26.04. Compare with Ubuntu package search for your suite (jammy, noble, or resolute).

Confirm OpenSSL (TLS 1.2 and 1.3 need OpenSSL 1.1.1 or newer; 22.04+ ships OpenSSL 3.x):

  1. openssl version

Confirm Apache is active:

  1. sudo systemctl is-active apache2

You want active. If Apache is not installed, follow How To Install the Apache Web Server on Ubuntu 22.04 first. The same apt install apache2 flow applies on 24.04 and 26.04.

Ubuntu LTS Codename Apache in default repos (approx.)
22.04 Jammy 2.4.52 or newer
24.04 Noble 2.4.58 or newer
26.04 Resolute 2.4.x (run apache2 -v on your host)

I have not pinned an exact Apache package revision for 26.04 here because security updates change the build string. Always trust apache2 -v on your VM.

Step 1: Installing Certbot

On Ubuntu 22.04, 24.04, and 26.04, the Certbot team recommends the snap package over the default apt Certbot packages.

Install snapd and Certbot

Update packages and install snapd (on minimal images snapd may already be present on Ubuntu 26.04 cloud images):

  1. sudo apt update
  2. sudo apt install snapd -y

Refresh the snap core runtime before installing Certbot (recommended on new 22.04, 24.04, and 26.04 servers):

  1. sudo snap install core
  2. sudo snap refresh core

Remove any older Certbot packages from apt so the snap binary is used:

  1. sudo apt remove certbot python3-certbot-apache 2>/dev/null || true

Install Certbot from snap:

  1. sudo snap install --classic certbot

Prepare the certbot command (EFF documents this symlink):

  1. sudo ln -sf /snap/bin/certbot /usr/bin/certbot

Confirm the version:

  1. certbot --version

You should see a Certbot version string. The exact number changes as snap updates the package.

Confirm the snap provides the Apache plugin and renewal timer:

  1. sudo certbot plugins

Look for an apache plugin in the list.

  1. snap list certbot
  2. systemctl list-timers --all | grep -i certbot

On snap installs you often see snap.certbot.renew.timer after the first successful certbot --apache run.

Ubuntu 26.04 LTS notes

Ubuntu 26.04 LTS (Resolute Raccoon) uses the same paths as 22.04 and 24.04: /etc/apache2/, a2ensite, apachectl configtest, and UFW Apache Full. Certbot still stores certificates under /etc/letsencrypt/.

If certbot runs the wrong binary, check which copy answers:

  1. which -a certbot

Remove leftover apt packages and keep the symlink at /usr/bin/certbot pointing to /snap/bin/certbot.

Step 2: Checking your Apache virtual host configuration

Certbot reads ServerName and ServerAlias from your virtual host to know which names to include on the certificate.

Open your site file:

  1. sudo nano /etc/apache2/sites-available/your_domain.conf

Confirm these lines exist inside the <VirtualHost *:80> block:

ServerName your_domain
ServerAlias www.your_domain

Enable the site and required modules if you have not already:

  1. sudo a2ensite your_domain.conf
  2. sudo a2enmod ssl
  3. sudo systemctl reload apache2

Test syntax before every reload:

  1. sudo apachectl configtest

You want Syntax OK. Fix typos, then reload:

  1. sudo systemctl reload apache2

Step 3: Allowing HTTPS through the firewall

If UFW is active, allow HTTP and HTTPS with the Apache Full application profile.

Check current rules:

  1. sudo ufw status

If only Apache (port 80) is allowed, add the full profile:

  1. sudo ufw allow 'Apache Full'

Remove the narrower profile when it is redundant:

  1. sudo ufw delete allow 'Apache'

Verify:

  1. sudo ufw status
UFW profile Ports opened Typical use
Apache 80/tcp HTTP only
Apache Full 80/tcp, 443/tcp HTTP and HTTPS
Apache (v6) / Apache Full (v6) Same on IPv6 Dual-stack hosts

Renewal uses HTTP-01 on port 80. Keep port 80 open even after HTTPS works.

Step 4: Obtaining an SSL certificate

Run Certbot with the Apache plugin:

  1. sudo certbot --apache

Certbot prompts for:

  1. An email address for renewal and security notices.
  2. Agreement to the Let’s Encrypt Subscriber Agreement.
  3. Optional EFF mailing list signup.
  4. Which hostnames to include (often both your_domain and www.your_domain).

Example successful output (dates and paths will differ on your server):

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/your_domain/privkey.pem
This certificate expires on YYYY-MM-DD.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for your_domain to /etc/apache2/sites-available/your_domain-le-ssl.conf
Successfully deployed certificate for www.your_domain to /etc/apache2/sites-available/your_domain-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://your_domain and https://www.your_domain

Visit https://your_domain in a browser. You should see a lock icon for a valid certificate.

Certificate file locations

Path Purpose
/etc/letsencrypt/live/your_domain/fullchain.pem Certificate plus intermediate chain (use in Apache SSLCertificateFile)
/etc/letsencrypt/live/your_domain/privkey.pem Private key (SSLCertificateKeyFile)
/etc/letsencrypt/live/your_domain/cert.pem Domain certificate only
/etc/letsencrypt/live/your_domain/chain.pem Intermediate certificates
/etc/letsencrypt/live/your_domain/README Notes from Certbot
/etc/letsencrypt/renewal/your_domain.conf Renewal settings for this cert

Files under live/ are symlinks. Certbot updates them on renewal.

For background on keys and CSRs, see OpenSSL Essentials.

Test with SSL Labs

Run the SSL Labs Server Test against your domain after hardening (Step 5) for an external grade.

Step 5: Hardening TLS and HTTP security headers

Certbot enables HTTPS. You should still disable old protocols and add security headers.

Enable headers module

  1. sudo a2enmod headers

Configure SSL protocols and ciphers

Edit the SSL module configuration:

  1. sudo nano /etc/apache2/mods-available/ssl.conf

Add or update these directives inside the file (comments explain each line):

# Allow TLS 1.2 and 1.3 only. Drop SSLv3, TLS 1.0, and TLS 1.1.
SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1

# Prefer modern AEAD ciphers. Apache negotiates the best match with clients.
SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384

# Let the client pick the cipher order (recommended for TLS 1.3).
SSLHonorCipherOrder     off

# OCSP stapling: Apache attaches revocation status to the handshake.
SSLUseStapling          on
SSLStaplingCache        "shmcb:${APACHE_RUN_DIR}/ssl_stapling(32768)"
Protocol Apache 2.4 on Ubuntu 22.04/24.04/26.04 Notes
TLS 1.3 Supported (OpenSSL 3.x on 22.04+) Default on modern clients
TLS 1.2 Supported Minimum for most production sites
TLS 1.1 and below Disabled with SSLProtocol above Required for strong grades on SSL Labs

Ubuntu 24.04 commonly ships Apache 2.4.58 in the default repos. Ubuntu 22.04 ships 2.4.52 or newer. On 26.04, run apache2 -v and check the resolute suite on packages.ubuntu.com for the current package revision.

Edit the SSL virtual host Certbot created (name may end in -le-ssl.conf):

  1. sudo nano /etc/apache2/sites-available/your_domain-le-ssl.conf

Inside <VirtualHost *:443>, add:

# Tell browsers to use HTTPS for one year, including subdomains.
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# Reduce MIME sniffing attacks.
Header always set X-Content-Type-Options "nosniff"

# Limit embedding in frames (adjust if you need iframes).
Header always set X-Frame-Options "SAMEORIGIN"

Test and reload:

  1. sudo apachectl configtest
  2. sudo systemctl reload apache2

Certbot often adds an HTTP to HTTPS redirect. Confirm http://your_domain redirects to https://. For redirect patterns, see How To Create Temporary and Permanent Redirects with Apache.

Step 6: Verifying automatic certificate renewal

Let’s Encrypt certificates expire after 90 days. Certbot installs a systemd timer that runs renewal checks twice per day.

Check the timer (snap installs often use this unit name):

  1. sudo systemctl status snap.certbot.renew.timer

If that unit is missing, try:

  1. sudo systemctl status certbot.timer

List all Certbot timers:

  1. systemctl list-timers | grep -i certbot

Run a dry run:

  1. sudo certbot renew --dry-run

Example success message:

Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/your_domain/fullchain.pem (success)

If renewal fails

  1. Read sudo less /var/log/letsencrypt/letsencrypt.log.
  2. Confirm port 80 is reachable from the internet (UFW and cloud firewalls).
  3. Confirm DNS still points to this server.
  4. Run sudo certbot renew --dry-run again after fixes.

Let’s Encrypt emails the address you registered before certificates expire. Do not rely on email alone for production monitoring.

Troubleshooting common issues

Domain validation failures

  • DNS not propagated: Use dig +short your_domain A and compare to your server IP.
  • Wrong virtual host: ServerName must match the domain you request.
  • Port 80 blocked: HTTP-01 needs inbound TCP 80. On DigitalOcean, check cloud firewalls plus UFW.

Apache errors after Certbot

Run sudo apachectl configtest. Certbot edits files under /etc/apache2/sites-available/. Restore from backup or re-run sudo certbot --apache after fixing ServerName typos.

Certificate rate limit errors

Let’s Encrypt enforces rate limits. The certificates per registered domain limit is 50 per week (see official docs for current numbers). If you hit a limit, wait for the window to reset or use a staging endpoint while testing:

  1. sudo certbot --apache --staging

Staging certificates are not trusted by browsers. Use them only for tests.

Firewall blocking renewal

Renewal still uses HTTP-01 on port 80 in the default setup. Keep Apache Full or explicit 80/tcp and 443/tcp rules in place.

Let’s Encrypt vs paid certificate authorities

Factor Let’s Encrypt Paid CA (DigiCert, Sectigo, etc.)
Cost Free Annual fee per cert or subscription
Validation Domain validation (DV) DV, OV, or EV options
Certificate lifetime 90 days (automated renewal) Often 1 year
Wildcard Yes, via DNS-01 challenge Yes, often easier with paid support
Support Community forums and docs Vendor SLA and phone support
Best fit Public websites, APIs, homelabs EV branding, legacy enterprise policies

When Let’s Encrypt fits: you control the server, you automate renewal, and you need standard DV HTTPS.

When a paid CA fits: your organization requires OV/EV seals, specific compliance paperwork, or a vendor support contract.

The CA/Browser Forum has discussed shorter maximum certificate lifetimes in the industry. Automated renewal with Certbot is the practical response on Ubuntu regardless of future lifetime changes. Watch Let’s Encrypt blog for policy updates.

FAQs

Here are some commonly asked questions about using Let’s Encrypt on Ubuntu with Apache.

1. How do you use Let’s Encrypt on Ubuntu with Apache?

Install Certbot from snap, configure Apache ServerName, open ports 80 and 443, then run sudo certbot --apache. Certbot requests the certificate and updates Apache. Renewal runs on a systemd timer.

2. How do you enable SSL in Apache2 on Ubuntu?

Enable mod_ssl with sudo a2enmod ssl, obtain certificates (Certbot is the usual path), and serve HTTPS on port 443 in a virtual host. Certbot creates your_domain-le-ssl.conf when you use the Apache plugin.

3. How do you enable TLS 1.2 in Apache2?

Set SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 in /etc/apache2/mods-available/ssl.conf. That leaves TLS 1.2 and 1.3 on current Ubuntu builds. Run sudo apachectl configtest before sudo systemctl reload apache2.

4. Is Let’s Encrypt really free?

Yes. Let’s Encrypt does not charge for certificates. ISRG runs the service as a nonprofit. See the Let’s Encrypt FAQ. Rate limits still apply.

5. How long does a Let’s Encrypt certificate last?

90 days by default. Certbot’s timer attempts renewal when a certificate is within 30 days of expiration. Run sudo certbot renew --dry-run to confirm your server renews correctly.

Conclusion

You installed Certbot from snap, obtained a Let’s Encrypt certificate with the Apache plugin, opened HTTPS in UFW, hardened TLS settings, and confirmed automatic renewal on Ubuntu. Your site now serves trusted HTTPS for your_domain.

For Nginx instead of Apache, follow How To Secure Nginx with Let’s Encrypt on Ubuntu 22.04. For local testing without a public CA, see How To Create a Self-Signed SSL Certificate for Apache in Ubuntu 18.04.

Official references: Certbot documentation and Let’s Encrypt documentation.

What’s next

Run Apache on a DigitalOcean Droplet with snapshots and monitoring so you can roll back if a config change breaks HTTPS.

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.