Let’s Encrypt issues free, trusted certificates that browsers accept everywhere. Certbot is the tool that requests them and configures your web server. Certificates last 90 days and renew automatically.
Before you start: your domain must already point to this server, and port 80 must be open. Let’s Encrypt checks both.
1. Install Certbot
On Ubuntu and Debian with Nginx:
sudo apt install certbot python3-certbot-nginx
On AlmaLinux, Rocky Linux and other RHEL-based systems, enable EPEL first:
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx
For Apache, install python3-certbot-apache instead and use --apache below.
2. Request the certificate
sudo certbot --nginx -d example.com -d www.example.com
Certbot asks for an email address for account notices, then proves you control the domain, installs the certificate and updates your Nginx configuration. When it asks, choose to redirect HTTP to HTTPS.
3. Check renewal
Certbot installs a timer that renews certificates before they expire. Confirm it works:
sudo certbot renew --dry-run
systemctl list-timers | grep certbot
4. Check the result
Visit https://example.com. Then check the details:
curl -sI https://example.com | head -1
sudo certbot certificates
What Certbot changed
With --nginx, Certbot edits your server block. Afterwards it contains lines like these, marked # managed by Certbot:
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
It also adds a second server block that redirects HTTP to HTTPS. You can edit around these lines freely; leave the paths as they are, because renewals update the files they point to.
Renewal, in more detail
Certificates last 90 days, and Certbot renews any that have less than 30 days left. The timer runs twice a day, so a renewal that fails once is retried long before expiry.
For Nginx and Apache installs, Certbot reloads the web server after renewing. If you use the certificate elsewhere, such as a mail server, add a deploy hook so it reloads too:
sudo certbot renew --deploy-hook "systemctl reload postfix dovecot"
Let’s Encrypt no longer emails expiry reminders, so monitor certificates yourself. An uptime monitor that checks certificate expiry, or a weekly look at sudo certbot certificates, catches a renewal that has been quietly failing.
Other ways to prove control
| Method | Command | Use when |
|---|---|---|
| Nginx or Apache plugin | --nginx or --apache | The normal case |
| Webroot | certonly --webroot -w /var/www/example.com/public -d example.com | Another web server, or you do not want Certbot editing the configuration |
| Standalone | certonly --standalone -d example.com | No web server running yet; Certbot briefly runs its own on port 80 |
| DNS challenge | certonly --manual --preferred-challenges dns -d example.com | Port 80 cannot be opened, behind a CDN, or for wildcard certificates |
The DNS challenge asks you to add a TXT record named _acme-challenge. Done by hand, it cannot renew automatically. For automatic DNS renewals, use the Certbot plugin for your DNS provider, such as python3-certbot-dns-cloudflare.
Wildcard certificates
A wildcard certificate covers every subdomain, such as *.example.com. It needs the DNS challenge:
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/cloudflare.ini -d example.com -d "*.example.com"
A wildcard covers one level only: a.example.com, but not a.b.example.com or example.com itself, which is why the bare domain is listed separately.
When it fails
| Error mentions | Usual cause |
|---|---|
| DNS problem: NXDOMAIN | The domain does not exist in DNS, or has a typo |
| Timeout during connect | Port 80 is blocked by a firewall |
| Invalid response / 404 | The domain points to a different server |
| too many certificates already issued | Rate limit hit; wait or use --dry-run while testing |
Let’s Encrypt limits how many certificates you can request: 50 per registered domain each week, and 5 identical certificates each week. While testing, add --dry-run or --staging, which use a test system without those limits.
Behind a proxy or CDN, or when port 80 cannot be opened, use a DNS challenge instead, which proves ownership with a TXT record.
Related
Something out of date? Software changes. If a step no longer works, tell us and we will check it and update the page.
