Report this

What is the reason for this report?

How To Secure Apache with Let's Encrypt on Ubuntu

Updated on December 18, 2025
English

Not using Ubuntu 20.04?
Choose a different version or distribution.
Ubuntu 20.04
How To Secure Apache with Let's Encrypt on Ubuntu

Introduction

Serving your Apache site over HTTPS encrypts traffic between clients and your server, preventing passive interception and tampering. Let’s Encrypt is a Certificate Authority (CA) that provides free TLS/SSL certificates, enabling encrypted HTTPS on web servers without the cost and complexity of traditional certificate authorities.

Certbot, the official Let’s Encrypt client, automates the entire process of obtaining, installing, and renewing SSL certificates for Apache on Ubuntu 20.04. With a single command, you can configure your web server to serve encrypted traffic and automatically renew certificates before they expire.

This tutorial uses a separate virtual host file instead of Apache’s default configuration file for setting up the website that will be secured by Let’s Encrypt. We recommend creating new Apache virtual host files for each domain hosted on a server, as this helps to avoid common mistakes and maintains the default configuration files as a fallback setup.

Deploy your frontend applications from GitHub using DigitalOcean App Platform. Let DigitalOcean focus on scaling your app.

Key Takeaways

Automated Certificate Management: Certbot’s Apache plugin automates SSL certificate installation and configuration, handling certificate issuance, Apache virtual host updates, and HTTP to HTTPS redirects in a single interactive command.

Automatic Renewal: Let’s Encrypt certificates expire after 90 days, but Certbot’s built-in systemd timer service automatically renews certificates twice daily when they’re within 30 days of expiration, ensuring continuous HTTPS coverage without manual intervention.

TLS Configuration: Once HTTPS is working, review Apache’s TLS settings to turn off legacy protocols, keep Certbot’s defaults where possible, and enable HSTS only after confirming your site functions correctly over HTTPS.

Multiple Domain Support: Certbot can secure multiple domains and subdomains simultaneously by detecting all domains configured in your Apache virtual hosts, allowing you to enable HTTPS for your main domain and www subdomain in one operation.

Troubleshooting Essentials: Common certificate issuance failures include DNS misconfiguration, firewall blocking ports 80/443, incorrect virtual host ServerName directives, and rate limiting from Let’s Encrypt. Verify DNS records, firewall rules, and Apache configuration before retrying.

Note: Ubuntu 20.04 reached end of life (EOL) in April 2025 and no longer receives security updates. While the commands and procedures in this tutorial still work on Ubuntu 20.04, we recommend upgrading to a supported Ubuntu version (22.04 LTS or 24.04 LTS) for security and support. The commands in this tutorial are compatible with newer Ubuntu versions as well.

Understanding TLS, HTTPS, and Let’s Encrypt

TLS (Transport Layer Security) is the cryptographic protocol that secures data transmission between web browsers and servers. HTTPS (HTTP Secure) uses TLS to encrypt HTTP traffic, preventing tampering and man-in-the-middle attacks.

Let’s Encrypt is a free, automated, and open Certificate Authority operated by the Internet Security Research Group (ISRG). It provides Domain Validation (DV) certificates that verify domain ownership through automated challenges, making SSL/TLS encryption accessible to everyone without cost or complex verification processes.

Certbot is the official ACME (Automated Certificate Management Environment) client for Let’s Encrypt. The Apache plugin (python3-certbot-apache) integrates directly with Apache’s configuration system, automatically detecting virtual hosts, obtaining certificates, and configuring SSL settings without manual file editing.

Let’s Encrypt certificates are free, automatically renewable, and issued within minutes. The 90-day validity period encourages automation and reduces the impact of compromised certificates.

Note: To understand more about the differences between SSL and TLS protocols, please refer to this article on TLS vs. SSL: What’s the Difference?.

Prerequisites

To follow this tutorial, you will need:

  • One Ubuntu server set up by following this initial server setup for Ubuntu tutorial, including a sudo non-root user and a firewall.

  • A fully registered domain name. This tutorial will use your_domain as an example throughout. You can purchase a domain name on Namecheap, get one for free on Freenom, or use the domain registrar of your choice.

  • Both of the following DNS records set up for your server. You can follow this introduction to DigitalOcean DNS documentation for details on how to add them.

    • An A record with your_domain pointing to your server’s public IP address.
    • An A record with www.your_domain pointing to your server’s public IP address.
  • Apache installed by following How To Install the Apache Web Server on Ubuntu. Be sure that you have a virtual host file for your domain. This tutorial will use /etc/apache2/sites-available/your_domain.conf as an example.

Important: Ensure your domain’s DNS records have fully propagated before proceeding. You can verify DNS resolution using dig your_domain or nslookup your_domain. Certbot requires valid DNS resolution to complete the HTTP-01 challenge that verifies domain ownership.

Installing Certbot and Required Packages

Certbot and the Apache plugin are installed via Ubuntu’s package manager. The certbot package provides the core ACME client, while python3-certbot-apache adds Apache-specific automation capabilities.

Update your package index and install both packages:

sudo apt update
sudo apt install certbot python3-certbot-apache

You will be prompted to confirm the installation by pressing Y, then ENTER.

The python3-certbot-apache plugin enables Certbot to:

  • Automatically detect Apache virtual hosts from your configuration files
  • Modify virtual host configurations to enable SSL
  • Reload Apache after certificate installation
  • Configure HTTP to HTTPS redirects

Note: If you prefer manual certificate management or need more control over the SSL configuration, you can install only certbot and use the certonly method instead of --apache. This tutorial focuses on the automated approach, but we’ll cover manual configuration alternatives in the troubleshooting section.

After installation, verify Certbot is working correctly by using:

certbot --version

You should see output showing the Certbot version number. Next, we’ll verify your Apache virtual host configuration to ensure Certbot can detect your domains correctly.

For example, after running certbot --version, you might see output like:

certbot 2.9.0

If you see a similar version number, you’re ready to continue.

Checking Your Apache Virtual Host Configuration

Certbot automatically detects domains from your Apache virtual host ServerName and ServerAlias directives. Before running Certbot, verify these settings are correctly configured in your virtual host file.

Open your domain’s virtual host configuration file:

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

Your virtual host should include ServerName and ServerAlias directives that match your domain. A typical configuration looks like this:

<VirtualHost *:80>
    ServerName your_domain
    ServerAlias www.your_domain
    DocumentRoot /var/www/your_domain
    ...
</VirtualHost>

If your virtual host configuration doesn’t match this structure, update it accordingly. The ServerName should be your primary domain, and ServerAlias should include the www subdomain and any other aliases you want to secure.

Once you have updated your configuration, check that your Apache settings are valid:

sudo apache2ctl configtest

You should see Syntax OK as a response. If you encounter errors, review your virtual host file for typos or syntax issues. Once validated, reload Apache to apply any changes:

sudo systemctl reload apache2

With your virtual host properly configured, Certbot will automatically detect both your main domain and www subdomain when you run the certificate issuance command.

Allowing HTTPS Through the Firewall

If you have the UFW firewall enabled, you’ll need to adjust the settings of your firewall to allow HTTPS traffic to your server. Upon installation, Apache registers a few different UFW application profiles. We can use the Apache Full profile to allow both HTTP and HTTPS traffic on your server.

To verify what kind of traffic is currently allowed on your server, you can use:

sudo ufw status

If you followed our Apache installation guides, your output should show only HTTP traffic (port 80) is allowed:

Output
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Apache ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Apache (v6) ALLOW Anywhere (v6)

The “Apache” profile only allows HTTP on port 80. To enable HTTPS, switch to the “Apache Full” profile which allows both HTTP and HTTPS:

sudo ufw allow 'Apache Full'
sudo ufw delete allow 'Apache'

Verify the change by using:

sudo ufw status
Output
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Apache Full ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Apache Full (v6) ALLOW Anywhere (v6)

Note: If you’re using iptables directly instead of UFW, ensure ports 80 and 443 are open. You can check with sudo iptables -L -n and add rules if needed: sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT and sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT.

Your firewall is now configured to allow HTTPS traffic. You’re ready to obtain your SSL certificate.

Obtaining and Installing a Let’s Encrypt SSL Certificate

Certbot’s Apache plugin automates certificate issuance, installation, and Apache configuration in a single interactive command. Run certbot --apache to start the process:

sudo certbot --apache

Certbot will prompt you through several configuration steps:

Step 1: Email Address

Enter a valid email address for renewal notifications and security notices:

Output
Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator apache, Installer apache Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): you@your_domain

Step 2: Terms of Service

Agree to Let’s Encrypt’s terms of service by pressing A and then ENTER:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

Step 3: Domain Selection

Certbot automatically detects domains from your Apache virtual hosts. Select which domains to secure:

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: your_domain
2: www.your_domain
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 

Leave the prompt blank and press ENTER to secure all listed domains (recommended).

Step 4: Certificate Issuance

Certbot performs the HTTP-01 challenge to verify domain ownership:

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for your_domain
http-01 challenge for www.your_domain
Enabled Apache rewrite module
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/apache2/sites-available/your_domain-le-ssl.conf
Enabled Apache socache_shmcb module
Enabled Apache ssl module
Deploying Certificate to VirtualHost /etc/apache2/sites-available/your_domain-le-ssl.conf
Enabling available site: /etc/apache2/sites-available/your_domain-le-ssl.conf
Deploying Certificate to VirtualHost /etc/apache2/sites-available/your_domain-le-ssl.conf

Step 5: HTTP to HTTPS Redirect

Choose whether to redirect all HTTP traffic to HTTPS:

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Select option 2 to enable automatic HTTP to HTTPS redirects (recommended for security).

Certificate Installation Complete

After successful installation, Certbot displays certificate details:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://your_domain and
https://www.your_domain

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=your_domain
https://www.ssllabs.com/ssltest/analyze.html?d=www.your_domain
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/your_domain/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/your_domain/privkey.pem
   Your cert will expire on 2020-07-27. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Certbot has created a new SSL virtual host configuration file at /etc/apache2/sites-available/your_domain-le-ssl.conf and enabled it. Your certificates are stored in /etc/letsencrypt/live/your_domain/.

Configuring Apache Virtual Hosts for HTTPS

Certbot automatically creates and configures an SSL virtual host, but understanding the configuration helps with troubleshooting and customization. The SSL virtual host file contains your certificate paths and basic SSL settings.

View your SSL virtual host configuration:

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

A typical Certbot-generated SSL virtual host looks like this:

/etc/apache2/sites-available/your_domain-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName your_domain
    ServerAlias www.your_domain
    DocumentRoot /var/www/your_domain

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/your_domain/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/your_domain/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Key directives:

  • SSLEngine on: Enables SSL/TLS for this virtual host
  • SSLCertificateFile: Path to the full certificate chain (leaf + intermediate certificates). On Apache 2.4.8+ (including Ubuntu 20.04), fullchain.pem already contains the complete chain, so the deprecated SSLCertificateChainFile directive is not used or needed.
  • SSLCertificateKeyFile: Path to the private key
  • Include /etc/letsencrypt/options-ssl-apache.conf: Includes Certbot’s recommended SSL configuration

If you enabled HTTP to HTTPS redirects, Certbot also modified your HTTP virtual host to include redirect rules. Verify the redirect is working by checking your HTTP virtual host:

sudo cat /etc/apache2/sites-available/your_domain.conf

You should see redirect rules similar to:

/etc/apache2/sites-available/your_domain.conf
<VirtualHost *:80>
    ServerName your_domain
    ServerAlias www.your_domain
    
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =your_domain [OR]
    RewriteCond %{SERVER_NAME} =www.your_domain
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

This configuration redirects all HTTP requests to their HTTPS equivalents using a 301 permanent redirect.

Testing HTTPS and SSL Configuration

Verify your SSL certificate installation using browser checks, command-line tools, and external SSL analyzers. Multiple verification methods ensure your certificate is correctly installed and trusted.

Browser Verification

Visit your domain using HTTPS in a web browser:

https://your_domain

Your browser should display:

  • A lock icon in the address bar
  • No security warnings
  • The certificate details showing Let’s Encrypt as the issuer

Click the lock icon to view certificate details, including expiration date and certificate chain.

Command-Line Testing

Test HTTPS connectivity and certificate details using curl:

curl -I https://your_domain

You should see HTTP headers confirming the HTTPS connection. For more detailed SSL information:

curl -vI https://your_domain 2>&1 | grep -i ssl

Verify the certificate chain using OpenSSL:

openssl s_client -connect your_domain:443 -servername your_domain < /dev/null 2>/dev/null | openssl x509 -noout -dates -issuer

This displays the certificate’s validity dates and issuer information.

External SSL Analysis

Use SSL Labs Server Test to get a comprehensive security analysis:

  1. Visit https://www.ssllabs.com/ssltest/analyze.html?d=your_domain
  2. Wait for the analysis to complete (may take a few minutes)
  3. Review the grade (aim for A or A+) and recommendations

SSL Labs tests:

  • Certificate validity and trust chain
  • Protocol support (TLS 1.2, TLS 1.3)
  • Cipher suite strength
  • Key exchange security
  • Overall configuration security

Note: If you encounter SSL connection errors during testing, refer to our guide on How to Fix SSL Connect Errors: Causes and Solutions for troubleshooting steps.

Verify HTTP to HTTPS Redirect

Test that HTTP requests redirect to HTTPS:

curl -I http://your_domain

You should see a 301 Moved Permanently response with a Location header pointing to the HTTPS URL:

HTTP/1.1 301 Moved Permanently
Location: https://your_domain/

If all tests pass, your SSL certificate is correctly installed and configured.

Setting Up Automatic Certificate Renewal

Let’s Encrypt certificates expire after 90 days, but Certbot’s systemd timer automatically renews certificates twice daily when they’re within 30 days of expiration. This ensures continuous HTTPS coverage without manual intervention.

Verify Auto-Renewal Service Status

Check that the Certbot renewal timer is active:

sudo systemctl status certbot.timer

You should see output indicating the service is active and enabled:

Output
● certbot.timer - Run certbot twice daily Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-04-28 17:57:48 UTC; 17h ago Trigger: Wed 2020-04-29 23:50:31 UTC; 12h left Triggers: ● certbot.service Apr 28 17:57:48 fine-turtle systemd[1]: Started Run certbot twice daily.

The timer runs certbot.service twice daily. If the service isn’t active, enable it:

sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

Test Certificate Renewal

Perform a dry run to verify the renewal process works without actually renewing certificates:

sudo certbot renew --dry-run

Successful output indicates renewal will work when certificates are due:

Output
Processing /etc/letsencrypt/renewal/your_domain.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Important: If the dry run fails, investigate the error messages. Common issues include DNS misconfiguration, firewall blocking, or Apache configuration problems. Fix these before your certificate expires to avoid service interruption.

Manual Renewal (If Needed)

While automatic renewal should handle certificate updates, you can manually renew certificates:

sudo certbot renew

This command only renews certificates that are within 30 days of expiration. To force renewal of all certificates regardless of expiration date:

sudo certbot renew --force-renewal

Note: Let’s Encrypt has rate limits (50 certificates per registered domain per week). Avoid unnecessary renewals to prevent hitting these limits. The automatic renewal process respects these limits and only renews when necessary.

Renewal Notifications

Let’s Encrypt sends email notifications to the address you provided during setup when:

  • Certificates are approaching expiration
  • Automatic renewal fails
  • Rate limits are approached

Monitor these emails to catch renewal issues early. You can update your email address:

sudo certbot update_account --email new_email@example.com

Hardening TLS Settings and Enabling HSTS

After obtaining your SSL certificate, harden your Apache TLS configuration by disabling legacy protocols, configuring strong cipher suites, and enabling security headers like HSTS. These changes reduce exposure to older protocol weaknesses and help keep Apache aligned with current TLS defaults.

Review Current SSL Configuration

Certbot includes a recommended SSL configuration file. View it:

sudo cat /etc/letsencrypt/options-ssl-apache.conf

This file contains Certbot’s default SSL settings. While generally secure, you can enhance it further.

Customize TLS Configuration

Edit your SSL virtual host to add enhanced security settings:

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

Add or modify SSL directives within the <VirtualHost *:443> block:

/etc/apache2/sites-available/your_domain-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName your_domain
    ServerAlias www.your_domain
    DocumentRoot /var/www/your_domain

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/your_domain/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/your_domain/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    # Disable legacy SSL/TLS protocols
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2 +TLSv1.3

    # Prefer server cipher order
    SSLHonorCipherOrder on

    # Disable SSL compression (mitigates CRIME attack)
    SSLCompression off

    # Enable OCSP stapling for improved performance
    SSLUseStapling on
    SSLStaplingCache "shmcb:/var/cache/apache2/ssl_stapling(32768)"

    # Security headers
    Header always set Strict-Transport-Security "max-age=15552000"
    Header always set X-Frame-Options DENY
    Header always set X-Content-Type-Options nosniff
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
</VirtualHost>
</IfModule>

Key security enhancements:

  • SSLProtocol: Disables insecure SSLv2, SSLv3, TLS 1.0, and TLS 1.1; enables only TLS 1.2 and TLS 1.3
  • SSLHonorCipherOrder: Server chooses cipher order, preferring stronger ciphers
  • SSLCompression: Disabled to prevent CRIME attack vulnerabilities
  • SSLUseStapling: Enables OCSP stapling for faster certificate validation
  • Strict-Transport-Security (HSTS): Instructs browsers to prefer HTTPS for a defined period (for example, 15552000 seconds / 180 days). The configuration example above intentionally uses a minimal header: Strict-Transport-Security "max-age=15552000". After you have confirmed that HTTPS works reliably across all hosts, you can strengthen it to Strict-Transport-Security "max-age=15552000; includeSubDomains" and, if you meet the requirements below, optionally to Strict-Transport-Security "max-age=15552000; includeSubDomains; preload".

Important: If you choose to add the HSTS preload directive (for example, Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"), it requires submission to the HSTS Preload List. Only include preload if you’ve submitted your domain and it’s been accepted; otherwise, do not add preload to your HSTS header.

Enable Required Apache Modules

Ensure required Apache modules are enabled:

sudo a2enmod headers
sudo a2enmod ssl
sudo systemctl reload apache2

Verify Configuration

Test your Apache configuration for syntax errors:

sudo apache2ctl configtest

If the test passes, reload Apache:

sudo systemctl reload apache2

Test Enhanced Security

Re-run SSL Labs Server Test to verify your security improvements:

https://www.ssllabs.com/ssltest/analyze.html?d=your_domain

Your grade should improve, and you should see:

  • Only TLS 1.2 and TLS 1.3 supported
  • Strong cipher suites preferred
  • HSTS header present
  • OCSP stapling enabled

Note: For more information on TLS configuration and security best practices, see our guide on TLS vs. SSL: What’s the Difference?.

Handling Multiple Domains and Virtual Hosts

Certbot can secure multiple domains and subdomains in a single certificate or issue separate certificates for each domain. The approach depends on your hosting setup and security requirements.

Single Certificate for Multiple Domains

When you run certbot --apache, Certbot detects all domains from your virtual hosts and can include them in one certificate. This is efficient but means all domains share the same certificate.

To add additional domains to an existing certificate:

sudo certbot --apache -d your_domain -d www.your_domain -d api.your_domain -d mail.your_domain

Certbot will:

  1. Detect the existing certificate
  2. Add the new domains to the certificate
  3. Update all relevant virtual hosts

Separate Certificates for Each Domain

For better security isolation, issue separate certificates for each domain:

sudo certbot --apache -d your_domain -d www.your_domain
sudo certbot --apache -d api.your_domain
sudo certbot --apache -d mail.your_domain

Each domain gets its own certificate and virtual host configuration.

Wildcard Certificates

For subdomain-heavy setups, use DNS-01 challenge to obtain wildcard certificates:

sudo certbot certonly --manual --preferred-challenges=dns -d "*.your_domain" -d your_domain

This requires manual DNS TXT record creation during issuance. Wildcard certificates cover all subdomains but require DNS access for renewal.

Note: Wildcard certificates are more complex to set up and renew. Consider whether multiple individual certificates or a wildcard certificate better fits your use case. For most scenarios, individual certificates per domain are simpler to manage.

Managing Multiple Virtual Hosts

When you have multiple virtual hosts, Certbot creates separate SSL configuration files for each:

  • /etc/apache2/sites-available/domain1-le-ssl.conf
  • /etc/apache2/sites-available/domain2-le-ssl.conf

Each SSL virtual host is independent, allowing different security configurations per domain if needed.

List all your certificates:

sudo certbot certificates

This displays all certificates, their domains, expiration dates, and certificate file paths.

Common Issues and Troubleshooting

Certificate issuance and renewal can fail due to DNS misconfiguration, firewall rules, Apache configuration errors, or Let’s Encrypt rate limits. Understanding common issues helps resolve problems quickly.

Issue 1: HTTP-01 Challenge Failure

Symptom: Certbot fails with “Failed to verify domain ownership” or “Connection refused” errors.

Causes:

  • DNS records not pointing to your server
  • Firewall blocking port 80
  • Apache not running or misconfigured
  • Incorrect virtual host ServerName

Solutions:

  1. Verify DNS resolution:

    dig your_domain +short
    nslookup your_domain
    

    Ensure the A record points to your server’s IP address.

  2. Check firewall rules:

    sudo ufw status
    

    Port 80 must be open for HTTP-01 challenges. Verify with:

    sudo ufw allow 80/tcp
    
  3. Verify Apache is running:

    sudo systemctl status apache2
    
  4. Test HTTP accessibility:

    curl -I http://your_domain
    

    You should receive an HTTP response. If not, check Apache configuration and virtual host settings.

Issue 2: Certificate Renewal Failures

Symptom: certbot renew fails or certificates expire unexpectedly.

Causes:

  • DNS changes breaking validation
  • Firewall rules changed
  • Apache configuration errors
  • Rate limiting from too many renewal attempts

Solutions:

  1. Check renewal logs:

    sudo tail -50 /var/log/letsencrypt/letsencrypt.log
    
  2. Test renewal manually:

    sudo certbot renew --dry-run -v
    

    The -v flag provides verbose output showing exactly where renewal fails.

  3. Verify DNS and firewall haven’t changed:

    dig your_domain +short
    sudo ufw status
    
  4. Check rate limits: Let’s Encrypt limits certificates to 50 per registered domain per week. If you’ve hit the limit, wait before retrying or use the staging environment for testing:

    sudo certbot --apache --staging
    

Issue 3: Apache SSL Configuration Errors

Symptom: Apache fails to start or SSL connections fail after certificate installation.

Causes:

  • Missing SSL module
  • Incorrect certificate file paths
  • Syntax errors in virtual host configuration

Solutions:

  1. Enable SSL module:

    sudo a2enmod ssl
    sudo systemctl restart apache2
    
  2. Verify certificate files exist:

    sudo ls -la /etc/letsencrypt/live/your_domain/
    

    You should see fullchain.pem, privkey.pem, chain.pem, and cert.pem.

  3. Test Apache configuration:

    sudo apache2ctl configtest
    

    Fix any syntax errors reported.

  4. Check Apache error logs:

    sudo tail -50 /var/log/apache2/error.log
    

Issue 4: Mixed Content or Redirect Loops

Symptom: Website loads but shows security warnings or redirects fail.

Causes:

  • HTTP resources loaded over HTTPS (mixed content)
  • Incorrect redirect rules
  • Proxy or load balancer misconfiguration

Solutions:

  1. Check browser console for mixed content warnings: Update all HTTP resource URLs to HTTPS in your website’s HTML, CSS, and JavaScript.

  2. Verify redirect configuration:

    sudo cat /etc/apache2/sites-available/your_domain.conf
    

    Ensure redirect rules are correct and not causing loops.

  3. Test redirect:

    curl -I http://your_domain
    

    Should return 301 Moved Permanently with Location: https://your_domain/.

Issue 5: Certificate Not Trusted by Browsers

Symptom: Browsers show “Not Secure” or certificate warnings.

Causes:

  • Incomplete certificate chain
  • System time incorrect
  • Certificate expired or revoked

Solutions:

  1. Verify certificate chain:

    openssl s_client -connect your_domain:443 -servername your_domain
    

    Check for “Verify return code: 0 (ok)” in the output.

  2. Check system time:

    date
    timedatectl status
    

    Incorrect system time can cause certificate validation failures. Sync time if needed:

    sudo timedatectl set-ntp true
    
  3. Verify certificate validity:

    sudo certbot certificates
    

    Check expiration dates. Renew if certificates are expired.

Note: For more detailed troubleshooting of SSL/TLS issues, see our comprehensive guide on How to Fix SSL Connect Errors: Causes and Solutions.

FAQs

How do I secure Apache with Let’s Encrypt on Ubuntu?

Install Certbot and the Apache plugin, then run sudo certbot --apache. Certbot will guide you through certificate issuance, automatically configure your Apache virtual hosts for HTTPS, and set up automatic renewal. Ensure your domain’s DNS records point to your server and ports 80/443 are open in your firewall before running Certbot.

What is Certbot and how does it work?

Certbot is the official ACME client for Let’s Encrypt that automates SSL certificate management. The Apache plugin (python3-certbot-apache) integrates with Apache’s configuration system to detect virtual hosts, obtain certificates via HTTP-01 challenges, install certificates, and configure SSL settings automatically. It handles certificate renewal through a systemd timer service.

How do I enable HTTPS for multiple domains or subdomains?

Run certbot --apache with multiple -d flags: sudo certbot --apache -d domain1.com -d www.domain1.com -d domain2.com. Certbot can include multiple domains in one certificate or issue separate certificates. For wildcard certificates covering all subdomains, use the DNS-01 challenge: sudo certbot certonly --manual --preferred-challenges=dns -d "*.your_domain".

How can I automatically renew Let’s Encrypt certificates?

Certbot includes a systemd timer (certbot.timer) that automatically renews certificates twice daily when they’re within 30 days of expiration. Verify it’s active with sudo systemctl status certbot.timer. Test renewal with sudo certbot renew --dry-run. Manual renewal: sudo certbot renew.

How do I test if my SSL certificate is installed correctly?

Use multiple verification methods: visit https://your_domain in a browser (check for lock icon), run curl -I https://your_domain, verify with OpenSSL (openssl s_client -connect your_domain:443), and test with SSL Labs Server Test for a comprehensive security analysis.

What are the best TLS settings for Apache?

Disable legacy protocols (SSLv2, SSLv3, TLS 1.0, TLS 1.1) and enable only TLS 1.2 and TLS 1.3. Configure strong cipher suites, disable SSL compression, enable OCSP stapling, and add security headers including HSTS. Certbot’s default configuration in /etc/letsencrypt/options-ssl-apache.conf provides a good baseline that you can enhance further.

How do I redirect HTTP traffic to HTTPS?

Certbot can automatically configure HTTP to HTTPS redirects when you select option 2 during certbot --apache. This adds RewriteRule directives to your HTTP virtual host. To manually configure, add redirect rules to your port 80 virtual host or use Apache’s Redirect directive: Redirect permanent / https://your_domain/.

What to do if Let’s Encrypt certificate issuance fails?

Common causes include DNS misconfiguration, firewall blocking ports 80/443, incorrect Apache virtual host ServerName, or Let’s Encrypt rate limits. Verify DNS resolution (dig your_domain), check firewall rules (sudo ufw status), ensure Apache is running and accessible on port 80, and review Certbot logs (sudo tail -50 /var/log/letsencrypt/letsencrypt.log) for specific error messages.

Conclusion

In this tutorial, you enabled HTTPS on an Apache server using a free Let’s Encrypt certificate on Ubuntu. You installed Certbot and the Apache plugin, issued a certificate for your virtual host, and confirmed that Apache is serving TLS traffic on port 443.

To keep the certificate current, verify that certbot.timer is enabled and run sudo certbot renew --dry-run periodically so you can catch renewal issues before expiration. If you customized your SSL virtual host, re-run sudo apache2ctl configtest after changes and validate the final configuration with your browser, curl, and an external SSL checker.

With HTTPS working end-to-end and renewal automated, you can review the hardening options in this guide (protocol settings, OCSP stapling, and HSTS) and apply them based on your site’s requirements.

Further Learning

Expand your knowledge with these helpful resources:

If you have questions about using Certbot, the Certbot documentation provides comprehensive guides and troubleshooting resources.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Erika Heidi
Erika Heidi
Author
Developer Advocate
See author profile

Dev/Ops passionate about open source, PHP, and Linux. Former Senior Technical Writer at DigitalOcean. Areas of expertise include LAMP Stack, Ubuntu, Debian 11, Linux, Ansible, and more.

Vinayak Baranwal
Vinayak Baranwal
Editor
Technical Writer II
See author profile

Building future-ready infrastructure with Linux, Cloud, and DevOps. Full Stack Developer & System Administrator. Technical Writer @ DigitalOcean | GitHub Contributor | Passionate about Docker, PostgreSQL, and Open Source | Exploring NLP & AI-TensorFlow | Nailed over 50+ deployments across production environments.

Still looking for an answer?

Was this helpful?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

can you make it for ngnix? getting code An unexpected error occurred: AttributeError: module ‘acme.challenges’ has no attribute ‘TLSSNI01’

The original Ubuntu 20.04 package have this bugs it did not install the right python3-certbot-nginx

So the only solution for ubuntu (AMD64) are via snap

  1. sudo snap install certbot --beta --classic

or

sudo add-apt-repository ppa:ahasenack/certbot-tlssni01-1875471
sudo apt-get update

Thanks to Andreas for making his PPA available temporarily to fixed the problem

I hope this will help people who want to upgrade to 20.04

You can re-run “certbot --apache” so that the script can automatically redirect http to https. In case you originally chose to not auto-configure this.

I can confirm that this works like a charm on Ubuntu 20.04. Simple! Thanks.

Step 3 /etc/apache2/sites-available/your_domain.conf

… ServerName your_domain ServerAlias www.your_domain …

do I need to change the name like this if my domain name is examplesite

/etc/apache2/sites-available/examplesite.conf

… ServerName examplesite ServerAlias www.examplesite …

Thanks a lot, everything works fine. All I had to do was enter sudo a2dissite default-ssl.conf

Fantastic tutorial! Thank you 🤩

Hi, thanks for your guide.

One question, can I follow this guide with a subdomain? So that I don’t have to purchase and maintain another domain name?

Im trying to increase the security of the access of phpmyadmin of my server.

Thanks.

Just do it step by step. Thank you very much!

E: Package ‘python-virtualenv’ has no installation candidate when I execute sudo certbot --apache Anyone else facing this?

:~# sudo certbot --apache
Bootstrapping dependencies for Debian-based OSes... (you can skip this with --no-bootstrap)
Ign:1 http://ppa.launchpad.net/certbot/certbot/ubuntu focal InRelease
Hit:2 http://archive.ubuntu.com/ubuntu focal InRelease
Err:3 http://ppa.launchpad.net/certbot/certbot/ubuntu focal Release
  404  Not Found [IP: 2001:67c:1560:8008::15 80]
Hit:4 https://repos.insights.digitalocean.com/apt/do-agent main InRelease
Get:5 http://mirrors.digitalocean.com/ubuntu focal InRelease [265 kB]
Hit:6 http://mirrors.digitalocean.com/ubuntu focal-updates InRelease
Hit:7 http://mirrors.digitalocean.com/ubuntu focal-backports InRelease
Hit:8 http://security.ubuntu.com/ubuntu focal-security InRelease
Reading package lists... Done
E: The repository 'http://ppa.launchpad.net/certbot/certbot/ubuntu focal Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
apt-get update hit problems but continuing anyway...
Reading package lists... Done
Building dependency tree
Reading state information... Done
Note, selecting 'python-is-python2' instead of 'python'
Note, selecting 'python-dev-is-python2' instead of 'python-dev'
Package python-virtualenv is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package 'python-virtualenv' has no installation candidate
Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.