Certificate Types and Issuance: Let's Encrypt Complete Guide
An SSL/TLS certificate is a digital document that proves domain ownership and carries the encryption keys. Understanding certificate types and issuance methods lets you pick the best option for your service.
Certificate Typesβ
DV (Domain Validation)β
Verifies only domain ownership. The cheapest and fastest to obtain.
- Validates: Domain ownership (DNS record or file-based challenge)
- Issuance time: Minutes to hours
- Cost: Free (Let's Encrypt) to tens of dollars
- Browser display: Padlock icon
- Best for: Personal blogs, startups, internal services
OV (Organization Validation)β
Validates domain ownership plus the legal existence of the organization.
- Validates: Domain + business registration, legal entity
- Issuance time: 1β5 business days
- Cost: Hundreds of dollars/year
- Browser display: Padlock icon (company name in the certificate)
- Best for: Corporate websites, B2B services
EV (Extended Validation)β
The most rigorous validation. Historically showed the company name in green in the address bar; modern browsers have removed that indicator.
- Validates: Domain + legal entity + operating address + phone confirmation
- Issuance time: 5β14 business days
- Cost: Hundreds to thousands of dollars/year
- Best for: Financial institutions, major e-commerce sites
Wildcard Certificateβ
A *.example.com certificate covers all subdomains.
*.example.com β covers shop.example.com, api.example.com, blog.example.com
Note: example.com itself or sub.sub.example.com require separate certificates
Multi-Domain (SAN, Subject Alternative Name)β
Multiple domains in a single certificate.
example.com, example.co.uk, www.example.com β one certificate
Let's Encrypt: Free DV Certificatesβ
Let's Encrypt is a non-profit CA that issues free DV certificates via an automated process. Certificates are valid for 90 days and certbot handles automatic renewal.
Install Certbotβ
# Ubuntu 22.04+
sudo apt update
sudo apt install certbot python3-certbot-nginx # Nginx plugin
sudo apt install certbot python3-certbot-apache # Apache plugin
# CentOS/RHEL
sudo dnf install certbot python3-certbot-nginx
Issuing a Let's Encrypt Certificate with Nginxβ
Method 1: Nginx Plugin (recommended)β
Certbot automatically edits the Nginx configuration.
# Single or multiple domains
sudo certbot --nginx -d example.com -d www.example.com
# Enter email, accept terms β certificate issued immediately
# Certificate location: /etc/letsencrypt/live/example.com/
Nginx config is updated automatically:
# Certbot auto-appends these lines
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;
Method 2: Standalone (stop Nginx first)β
Certbot binds to port 80 directly.
sudo systemctl stop nginx
sudo certbot certonly --standalone -d example.com -d www.example.com
sudo systemctl start nginx
Method 3: Webrootβ
Issues the certificate without any downtime. Nginx stays running.
# Nginx needs the webroot path pre-configured
sudo certbot certonly --webroot \
-w /var/www/html \
-d example.com \
-d www.example.com
# Required Nginx config (add before issuing)
server {
listen 80;
server_name example.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
}
Wildcard Certificate (DNS challenge required)β
Wildcards must be validated via a DNS TXT record.
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.example.com" -d example.com
# Certbot will ask you to add a TXT record:
# _acme-challenge.example.com β "random-value"
# Add it in your DNS console, then press Enter
Issuing a Let's Encrypt Certificate with Apacheβ
# Auto-issue and configure with Apache plugin
sudo certbot --apache -d example.com -d www.example.com
# Certificate files
ls /etc/letsencrypt/live/example.com/
# cert.pem β server certificate
# chain.pem β intermediate CA certificate
# fullchain.pem β server + intermediate CA (use this one)
# privkey.pem β private key
Automatic Renewalβ
Let's Encrypt certificates expire every 90 days. Certbot automatically sets up a systemd timer or cron job.
# Check the auto-renewal timer
sudo systemctl list-timers | grep certbot
# Test renewal (dry-run, no actual renewal)
sudo certbot renew --dry-run
# On success, Nginx/Apache is automatically reloaded
Manual cron fallbackβ
# /etc/cron.d/certbot
0 0,12 * * * root certbot renew --quiet --post-hook "systemctl reload nginx"
Check Issued Certificatesβ
# List all issued certificates
sudo certbot certificates
# Output:
# Found the following certs:
# Certificate Name: example.com
# Domains: example.com www.example.com
# Expiry Date: 2024-05-20 00:00:00+00:00 (VALID: 89 days)
# Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
# Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
# Certificate details
openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -text -noout \
| grep -E "Subject|Not After|DNS"
Applying a Paid Certificateβ
Enterprise and financial services use paid certificates from Sectigo, DigiCert, GlobalSign, etc.
# 1. Generate a CSR (Certificate Signing Request)
openssl req -new -newkey rsa:2048 -nodes \
-keyout example.com.key \
-out example.com.csr \
-subj "/C=US/ST=California/L=San Francisco/O=My Company/CN=example.com"
# 2. Submit the CSR to the CA β validate β receive certificate files
# 3. Received files:
# example.com.crt β server certificate
# example.com.ca.crt β intermediate CA certificate
# example.com.key β private key
# 4. Build the certificate chain
cat example.com.crt example.com.ca.crt > fullchain.crt
# 5. Apply to Nginx/Apache
Certificate Expiry Monitoringβ
# Check certificate expiry date
echo | openssl s_client -servername example.com \
-connect example.com:443 2>/dev/null \
| openssl x509 -noout -dates
# notBefore=Jan 15 00:00:00 2024 GMT
# notAfter=Apr 14 23:59:59 2024 GMT
# Check if certificate is valid for at least 30 more days
echo | openssl s_client -servername example.com \
-connect example.com:443 2>/dev/null \
| openssl x509 -noout -checkend $((30 * 86400)) && \
echo "OK: valid for 30+ days" || echo "WARNING: expires within 30 days!"
Automated expiry monitoring is covered in pro-tips.md.