Table of Contents
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.
[info]
Deploy your frontend applications from GitHub using an app platform. Let the cloud provider 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.
[warning]
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.
- Both of the following DNS records set up for your server. You can follow this introduction to DNS hosting documentation for details on how to add them.
- An A record with
your_domainpointing to your server's public IP address.
- An A record with
www.your_domainpointing 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.confas an example.
[warning]
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:
[secondary_label 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
[secondary_label 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:
[secondary_label 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:
[label /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.pemalready contains the complete chain, so the deprecatedSSLCertificateChainFiledirective 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:
[label /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:
- Visit
https://www.ssllabs.com/ssltest/analyze.html?d=your_domain
- Wait for the analysis to complete (may take a few minutes)
- 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:
[secondary_label 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:
[secondary_label 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)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[warning]
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:
[label /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 toStrict-Transport-Security "max-age=15552000; includeSubDomains"and, if you meet the requirements below, optionally toStrict-Transport-Security "max-age=15552000; includeSubDomains; preload".
[warning]
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:
- Detect the existing certificate
- Add the new domains to the certificate
- 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:
- Verify DNS resolution:
dig your_domain +short
nslookup your_domain
Ensure the A record points to your server's IP address.
- Check firewall rules:
sudo ufw status
Port 80 must be open for HTTP-01 challenges. Verify with:
sudo ufw allow 80/tcp
- Verify Apache is running:
sudo systemctl status apache2
- 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:
- Check renewal logs:
sudo tail -50 /var/log/letsencrypt/letsencrypt.log
- Test renewal manually:
sudo certbot renew --dry-run -v
The -v flag provides verbose output showing exactly where renewal fails.
- Verify DNS and firewall haven't changed:
dig your_domain +short
sudo ufw status
- 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:
- Enable SSL module:
sudo a2enmod ssl
sudo systemctl restart apache2
- Verify certificate files exist:
sudo ls -la /etc/letsencrypt/live/your_domain/
You should see fullchain.pem, privkey.pem, chain.pem, and cert.pem.
- Test Apache configuration:
sudo apache2ctl configtest
Fix any syntax errors reported.
- 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:
- Check browser console for mixed content warnings:
Update all HTTP resource URLs to HTTPS in your website's HTML, CSS, and JavaScript.
- Verify redirect configuration:
sudo cat /etc/apache2/sites-available/your_domain.conf
Ensure redirect rules are correct and not causing loops.
- 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:
- Verify certificate chain:
openssl s_client -connect your_domain:443 -servername your_domain
Check for "Verify return code: 0 (ok)" in the output.
- Check system time:
date
timedatectl status
Incorrect system time can cause certificate validation failures. Sync time if needed:
sudo timedatectl set-ntp true
- 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:
- How To Secure Apache with Let's Encrypt on Ubuntu – Comprehensive guide for securing Apache on additional Ubuntu versions.
- How To Secure Apache with Let's Encrypt on Debian 11 – Step-by-step instructions tailored for Debian systems.
- How To Secure Nginx with Let's Encrypt on Ubuntu 22.04 – Learn how to configure HTTPS using Nginx instead of Apache.
- OpenSSL Essentials: Working with SSL Certificates, Private Keys, and CSRs – A comprehensive guide to managing certificates using OpenSSL.
- How to Fix SSL Connect Errors: Causes and Solutions – Solutions for resolving common SSL/TLS connection issues.
- TLS vs. SSL: What's the Difference? – An overview of TLS and SSL protocols and their key differences.
If you have questions about using Certbot, the Certbot documentation provides comprehensive guides and troubleshooting resources.