Skip to main content

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​

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.