Let's Encrypt
01 / 02

Certbot, ACME Protocol & Certificate Issuance

Let's Encrypt: Certbot & ACME

Let's Encrypt is a free, automated Certificate Authority. Certificates are issued via the ACME protocol — no manual validation or payment. Certificates last 90 days and are designed to be auto-renewed.

How ACME Works

ACME (Automatic Certificate Management Environment — RFC 8555):

1. Client generates a key pair, registers with Let's Encrypt CA
2. Client requests a certificate for domain.com
3. CA issues a challenge — prove you control domain.com:

   HTTP-01 challenge: serve a token at
     http://domain.com/.well-known/acme-challenge/<token>
     Requires: port 80 open, no CDN blocking the path
     Works for: single domains

   DNS-01 challenge: add a TXT record
     _acme-challenge.domain.com = <token>
     Requires: DNS API access (or manual)
     Works for: wildcards (*.domain.com), private servers, no port 80

   TLS-ALPN-01: serve challenge via TLS on port 443
     Requires: port 443 open

4. CA validates the challenge, issues signed certificate
5. Client stores certificate + private key

Rate limits (free tier):
  50 certificates per registered domain per week
  5 duplicate certificates per week
  5 failures per hour (use --staging for testing!)

Certbot Installation

# Ubuntu/Debian
sudo apt install snapd
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

# macOS (testing/dev only)
brew install certbot

# CentOS/RHEL
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx

Issuing Certificates

# Nginx plugin — auto-configures Nginx, handles HTTP-01 challenge
sudo certbot --nginx -d example.com -d www.example.com

# Apache plugin
sudo certbot --apache -d example.com

# Standalone (temporary HTTP server — stop nginx/apache first)
sudo certbot certonly --standalone -d example.com

# Webroot (nginx/apache keeps running, serves challenge files)
sudo certbot certonly --webroot   --webroot-path /var/www/html   -d example.com -d www.example.com

# DNS-01 (for wildcards — requires DNS plugin or manual)
sudo certbot certonly --manual   --preferred-challenges dns   -d '*.example.com' -d example.com

# TEST FIRST with staging (avoids hitting rate limits)
sudo certbot certonly --staging --nginx -d example.com

# Non-interactive (for scripts/CI)
sudo certbot certonly --nginx   --non-interactive   --agree-tos   --email admin@example.com   -d example.com   -d www.example.com

Certificate Files

# Certificates stored in: /etc/letsencrypt/live/example.com/
ls /etc/letsencrypt/live/example.com/

# cert.pem      — server certificate only (leaf)
# chain.pem     — intermediate certificates
# fullchain.pem — cert.pem + chain.pem (use this for ssl_certificate)
# privkey.pem   — private key (KEEP PRIVATE)

# Check certificate details
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -text

# Check expiry
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem   -noout -dates

# Check which domains are covered
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem   -noout -ext subjectAltName

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free