Securing Apache with Certbot
HTTPS (HyperText Transfer Protocol Secure) is what turns the padlock icon on in your browser. It encrypts the traffic between a visitor and your server so nobody in between can read or tamper with it. If you run a website on the Apache web server (one of the oldest and most widely used web servers on Linux), the easiest way to get HTTPS is Certbot — a free tool that talks to Let’s Encrypt, gets you a real SSL/TLS certificate, and rewrites your Apache config for you. This page walks through doing exactly that on Ubuntu, end to end.
What Certbot does for Apache
A certificate is a small file that proves your server really owns your domain. Without one, browsers show a scary “Not Secure” warning. Certbot automates the whole certificate lifecycle: it proves you control the domain, downloads the certificate, and — with the Apache plugin — edits your Apache virtual host (a “vhost” is Apache’s config block for one website) so the site serves HTTPS immediately.
The key piece is the Apache plugin, a package called python3-certbot-apache. It knows how to read and write Apache config files, so Certbot doesn’t just hand you a certificate and leave you to wire it up by hand. It creates a new SSL vhost and can add an automatic redirect from http:// to https://.
When to use this: you have an Apache site already serving plain HTTP on a real domain (not an IP address) and you want HTTPS with the least effort. When NOT to use this: if you sit behind a separate load balancer or CDN (Content Delivery Network) that already terminates TLS for you, or if you use Nginx instead — in that case see the Nginx Certbot page.
Before you start
You need three things in place:
- A domain name (for example
example.com) with a DNS A record (the record that maps a name to an IPv4 address) pointing at your server’s public IP. - Apache already installed and serving the site on port 80 (HTTP).
- The firewall allowing HTTP and HTTPS.
Check Apache is running and open the firewall:
sudo systemctl status apache2
sudo ufw allow 'Apache Full'
sudo ufw status
ufw is the Uncomplicated Firewall, Ubuntu’s simple front end for managing firewall rules. The Apache Full profile opens both port 80 (HTTP) and port 443 (HTTPS).
Output:
Status: active
To Action From
-- ------ ----
Apache Full ALLOW Anywhere
Apache Full (v6) ALLOW Anywhere (v6)
Certbot proves you own the domain by briefly serving a file over port 80. If your DNS A record is wrong or port 80 is blocked, the challenge fails and you get no certificate. Fix DNS first.
Install Certbot and the Apache plugin
On Ubuntu 22.04 and 24.04 the recommended way to install Certbot is via snap, the universal package format that ships with Ubuntu. This gives you the newest Certbot version. Install the core tool, then make the certbot command available system-wide:
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
The Apache plugin ships inside the snap, so no separate install is needed. If you prefer the older apt route instead, you would run sudo apt install certbot python3-certbot-apache — but snap is preferred in 2026 because it stays current automatically.
Verify it works:
certbot --version
Output:
certbot 3.1.0
Run Certbot for Apache
This is the one command that does everything. The --apache flag tells Certbot to use the Apache plugin: get the certificate and edit your Apache config.
sudo certbot --apache -d example.com -d www.example.com
The -d flag lists each domain name the certificate should cover. Include www if people reach your site that way.
The first time, Certbot asks for an email (used for expiry warnings) and to agree to the terms. Then it works through the challenge and offers the redirect choice:
Output:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and www.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2026-09-13.
Deploying certificate
Successfully deployed certificate for example.com to /etc/apache2/sites-available/example-le-ssl.conf
Successfully deployed certificate for www.example.com to /etc/apache2/sites-available/example-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.com
Notice Certbot created a brand-new file ending in -le-ssl.conf. That is the SSL vhost it built for you.
The SSL vhost Certbot creates
Certbot copies your original vhost, switches it to port 443, and points it at the new certificate files. The result in /etc/apache2/sites-available/example-le-ssl.conf looks like this:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
The Include line pulls in modern, secure TLS settings (protocols and ciphers) that Certbot maintains, so you do not have to tune them yourself.
The HTTP to HTTPS redirect
If you chose the redirect, Certbot edits your original port 80 vhost to forward everyone to HTTPS. It adds rewrite rules like this to /etc/apache2/sites-available/example.conf:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
R=permanent sends an HTTP 301 status, telling browsers and search engines the move to HTTPS is permanent. Certbot also enables the needed modules (ssl and rewrite) and reloads Apache automatically.
| Certbot choice | What happens | When to pick it |
|---|---|---|
| Redirect (recommended) | All HTTP traffic forwarded to HTTPS | Almost always — you want every visitor on HTTPS |
| No redirect | HTTP and HTTPS both served separately | Only during migration or special API needs |
Verify it worked
Test the redirect and the certificate from the command line:
curl -I http://example.com
Output:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
curl -I https://example.com
Output:
HTTP/2 200
server: Apache/2.4.58 (Ubuntu)
A 301 on HTTP and 200 on HTTPS means the redirect and certificate are both live. You can also open the site in a browser and click the padlock.
Renewal happens automatically
Let’s Encrypt certificates last 90 days. The Certbot snap installs a systemd timer (systemd is Ubuntu’s service manager; a timer is its built-in scheduler) that renews them in the background. Confirm it is active and do a dry run that simulates renewal without changing anything:
sudo systemctl list-timers | grep certbot
sudo certbot renew --dry-run
Output:
Congratulations, all simulations of the renewal succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
If the dry run passes, you never have to think about renewals again.
Best Practices
- Always pick the redirect option so no visitor is ever left on insecure HTTP.
- Run
sudo certbot renew --dry-runafter setup to confirm auto-renewal works before you forget about it. - Include every hostname (
example.com,www.example.com, any subdomains) in one-dlist so a single certificate covers them all. - Let Certbot manage the
-le-ssl.conffile; edit your original vhost for app changes and re-run Certbot if you change domains. - Keep
ufwrules tight: allowApache Full(ports 80 and 443) but close anything else. - Check
/var/log/letsencrypt/letsencrypt.logif a renewal or issuance ever fails — it explains exactly what went wrong.