Skip to main content
Certbot is the recommended client for obtaining free SSL/TLS certificates from Let’s Encrypt. This guide covers installation, certificate issuance for Apache and Nginx, standalone mode, wildcard certificates, and automated renewal.
This guide is for VPS and Bare Metal customers managing their own web servers. Web Hosting (Plesk) and WordPress Hosting customers have Let’s Encrypt built into their control panels and do not need Certbot.

Installation

apt update
apt install certbot -y

# For Nginx integration
apt install python3-certbot-nginx -y

# For Apache integration
apt install python3-certbot-apache -y

Obtaining a Certificate

Nginx Plugin

The Nginx plugin automatically configures SSL in your Nginx server blocks:
certbot --nginx -d example.com -d www.example.com
Certbot will modify your Nginx configuration to add SSL directives, obtain the certificate, and reload Nginx.

Apache Plugin

The Apache plugin automatically configures SSL in your Apache virtual hosts:
certbot --apache -d example.com -d www.example.com
Certbot will modify your Apache configuration, obtain the certificate, and reload Apache.

Standalone Mode

If you are not running a web server, or prefer not to let Certbot modify your configuration, use standalone mode. Certbot temporarily starts its own web server on port 80 to complete the HTTP-01 challenge.
# Stop your web server first if it is using port 80
systemctl stop nginx  # or apache2 / httpd

certbot certonly --standalone -d example.com -d www.example.com

# Start your web server again
systemctl start nginx  # or apache2 / httpd
Standalone mode only obtains the certificate — you must configure your web server to use it manually. Certificates are stored in /etc/letsencrypt/live/example.com/.
FilePurpose
fullchain.pemCertificate + intermediate chain (use this for ssl_certificate in Nginx or SSLCertificateFile in Apache)
privkey.pemPrivate key (use this for ssl_certificate_key in Nginx or SSLCertificateKeyFile in Apache)

Wildcard Certificates

Wildcard certificates (*.example.com) require DNS-01 validation instead of HTTP-01. This means Certbot needs to create a TXT record in your DNS zone to prove ownership.
certbot certonly --manual --preferred-challenges dns -d example.com -d "*.example.com"
Certbot will prompt you to create a TXT record at _acme-challenge.example.com with a specific value. Add the record in your DNS provider, wait for propagation, then press Enter to continue.
Wildcard certificates require manual DNS intervention on each renewal unless you automate it with a DNS plugin (e.g., certbot-dns-cloudflare, certbot-dns-route53). If you cannot automate DNS challenges, consider using individual certificates per subdomain instead.

Automated DNS Validation (Cloudflare Example)

If your DNS is managed by Cloudflare, you can automate wildcard renewals:
apt install python3-certbot-dns-cloudflare -y
Create a credentials file:
mkdir -p /etc/letsencrypt
cat > /etc/letsencrypt/cloudflare.ini << 'EOF'
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
EOF
chmod 600 /etc/letsencrypt/cloudflare.ini
Issue the wildcard certificate:
certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d example.com \
  -d "*.example.com"
This method supports fully automated renewal.

Automatic Renewal

Let’s Encrypt certificates expire after 90 days. Certbot installs a systemd timer (or cron job) that automatically renews certificates before expiration.

Verify the Timer

systemctl status certbot.timer
If the timer is active, renewal is handled automatically. To test renewal without making changes:
certbot renew --dry-run

Manual Cron (If No Systemd Timer)

If the systemd timer is not available or not active, add a cron job:
crontab -e
Add the following line to attempt renewal twice daily:
0 3,15 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"
Replace nginx with apache2 or httpd depending on your web server. The --deploy-hook only runs when a certificate is actually renewed.

Post-Renewal Hooks

Certbot supports hooks that run after a successful renewal. This is useful for reloading your web server or restarting services that depend on the certificate.
# Reload Nginx after renewal
certbot renew --deploy-hook "systemctl reload nginx"

# Reload Apache after renewal
certbot renew --deploy-hook "systemctl reload apache2"

# Run a custom script
certbot renew --deploy-hook "/opt/scripts/post-renew.sh"
To make a deploy hook permanent, create a script in /etc/letsencrypt/renewal-hooks/deploy/:
cat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << 'EOF'
#!/bin/bash
systemctl reload nginx
EOF
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Managing Certificates

CommandDescription
certbot certificatesList all managed certificates and their expiration dates
certbot renewRenew all certificates due for renewal
certbot renew --dry-runTest renewal without making changes
certbot delete --cert-name example.comRemove a certificate
certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pemRevoke a certificate

Troubleshooting

  • “Problem binding to port 80” — Another service is already using port 80. Stop your web server before using standalone mode, or use the Nginx/Apache plugin instead.
  • “DNS problem: NXDOMAIN” — The domain does not resolve to your server. Verify your A/AAAA records point to the correct IP and that DNS has propagated.
  • “Too many certificates already issued” — Let’s Encrypt has rate limits of 50 certificates per registered domain per week. Use --staging for testing to avoid hitting production limits.
  • “Unauthorized” during renewal — If your server is behind Cloudflare with proxying enabled, ensure HTTP-01 challenges can reach your origin server. Alternatively, switch to DNS-01 validation.