How To Secure Apache with Let's Encrypt on Ubuntu

How To Secure Apache with Let's Encrypt on Ubuntu

Source: DigitalOcean

By Erika Heidi and Vinayak Baranwal 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. 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. 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?. 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. 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. 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: You will be prompted to confirm the installation by pressing Y, then ENTER. The python3-certbot-apache plugin enables Certbot to: 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: 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: If you see a similar version number, you’re ready to continue. 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: Your virtual host should include ServerName and ServerAlias directives that match your domain. A typical configuration looks like this: 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: 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: With your virtual host properly configured, Certbot will automatically detect both your main domain and www subdomain when you run the certificate issuance command. 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: If you followed our Apache installation guides, your output should show only HTTP traffic (port 80) is allowed: The “Apache” profile only allows HTTP on port 80. To enable HTTPS, switch to the “Apache Full” profile which allows both HTTP and HTTPS: Verify the change by using: 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. Certbot’s Apache plugin automates certificate issuance, installation, and Apache configuration in a single interactive command. Run certbot --apache to start the process: Certbot will prompt you through several configuration steps: Enter a valid email address for renewal notifications and security notices: Agree to Let’s Encrypt’s terms of service by pressing A and then ENTER: Certbot automatically detects domains from your Apache virtual hosts. Select which domains to secure: Leave the prompt blank and press ENTER to secure all listed domains (recommended). Certbot performs the HTTP-01 challenge to verify domain ownership: Choose whether to redirect all HTTP traffic to HTTPS: Select option 2 to enable automatic HTTP to HTTPS redirects (recommended for security). After successful installation, Certbot displays certificate details: 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/. 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: A typical Certbot-generated SSL virtual host looks like this: 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: You should see redirect rules similar to: This configuration redirects all HTTP requests to their HTTPS equivalents using a 301 permanent redirect. 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. Visit your domain using HTTPS in a web browser: Your browser should display: Click the lock icon to view certificate details, including expiration date and certificate chain. Test HTTPS connectivity and certificate details using curl: You should see HTTP headers confirming the HTTPS connection. For more detailed SSL information: Verify the certificate chain using OpenSSL: This displays the certificate’s validity dates and issuer information. Use SSL Labs Server Test to get a comprehensive security analysis: 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. Test that HTTP requests redirect to HTTPS: You should see a 301 Moved Permanently response with a Location header pointing to the HTTPS URL: If all tests pass, your SSL certificate is correctly installed and configured. 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. Check that the Certbot renewal timer is active: You should see output indicating the service is active and enabled: The timer runs certbot.service twice daily. If the service isn’t active, enable it: Perform a dry run to verify the renewal process works without actually renewing certificates: Successful output indicates renewal will work when certificates are due: 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. While automatic renewal should handle certificate updates, you can manually renew certificates: This command only renews certificates that are within 30 days of expiration. To force renewal of all certificates regardless of expiration date: 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. Let’s Encrypt sends email notifications to the address you provided during setup when: Monitor these emails to catch renewal issues early. You can update your email address: 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. Certbot includes a recommended SSL configuration file. View it: This file contains Certbot’s default SSL settings. While generally secure, you can enhance it further. Edit your SSL virtual host to add enhanced security settings: Add or modify SSL directives within the <VirtualHost *:443> block: Key security enhancements: 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. Ensure required Apache modules are enabled: Test your Apache configuration for syntax errors: If the test passes, reload Apache: Re-run SSL Labs Server Test to verify your security improvements: Your grade should improve, and you should see: Note: For more information on TLS configuration and security best practices, see our guide on TLS vs. SSL: What’s the Difference?. 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. 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: For better security isolation, issue separate certificates for each domain: Each domain gets its own certificate and virtual host configuration. For subdomain-heavy setups, use DNS-01 challenge to obtain wildcard certificates: 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. When you have multiple virtual hosts, Certbot creates separate SSL configuration files for each: Each SSL virtual host is independent, allowing different security configurations per domain if needed. List all your certificates: This displays all certificates, their domains, expiration dates, and certificate file paths. 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. Symptom: Certbot fails with “Failed to verify domain ownership” or “Connection refused” errors. Verify DNS resolution: Ensure the A record points to your server’s IP address. Check firewall rules: Port 80 must be open for HTTP-01 challenges. Verify with: Verify Apache is running: Test HTTP accessibility: You should receive an HTTP response. If not, check Apache configuration and virtual host settings. Symptom: certbot renew fails or certificates expire unexpectedly. Test renewal manually: The -v flag provides verbose output showing exactly where renewal fails. Verify DNS and firewall haven’t changed: 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: Symptom: Apache fails to start or SSL connections fail after certificate installation. Verify certificate files exist: You should see fullchain.pem, privkey.pem, chain.pem, and cert.pem. Test Apache configuration: Fix any syntax errors reported. Check Apache error logs: Symptom: Website loads but shows security warnings or redirects fail. 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: Ensure redirect rules are correct and not causing loops. Should return 301 Moved Permanently with Location: https://your_domain/. Symptom: Browsers show “Not Secure” or certificate warnings. Verify certificate chain: Check for “Verify return code: 0 (ok)” in the output. Incorrect system time can cause certificate validation failures. Sync time if needed: Verify certificate validity: 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. 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. 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. 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". 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. 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. 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. 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/. 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. 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. 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 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. 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. 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 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. 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? Please complete your information! Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation. Full documentation for every DigitalOcean product. The Wave has everything you need to know about building a business, from raising funding to marketing your product. Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter. New accounts only. By submitting your email you agree to our Privacy Policy Scale up as you grow — whether you're running one virtual machine or ten thousand. Sign up and get $200 in credit for your first 60 days with DigitalOcean.* *This promotional offer applies to new accounts only.