# curl https://devtools.krishanchawla.com/raw/letsencrypt-advanced.txt LET'S ENCRYPT - ADVANCED Advanced Let's Encrypt features including Docker, monitoring, best practices, and production deployment Category: Certificate · Type: cheatsheet Official docs: https://letsencrypt.org/ ──────────────────────────────────────────────────────────── ## What is Let's Encrypt? **Let's Encrypt** is a free, automated, and open certificate authority that provides SSL/TLS certificates to enable HTTPS on websites. This guide covers advanced features including Docker deployment, monitoring, and production best practices. **⚡ Key Features** - Docker container support - Certificate monitoring - OCSP stapling - HSTS security headers - Production-ready configs **🎯 Use Cases** - Containerized deployments - Automated monitoring - Load balancer SSL - Multi-server setups - Enterprise security --- ## 🐳 Docker - Standalone Mode Run Certbot in Docker container for certificate issuance. ```bash docker run -it --rm \ -v /etc/letsencrypt:/etc/letsencrypt \ -v /var/lib/letsencrypt:/var/lib/letsencrypt \ -p 80:80 \ certbot/certbot certonly --standalone -d example.com ``` **Note:** Port 80 must be available on host. ## 🐳 Docker - Compose Setup Docker Compose configuration for automatic renewal. ```yaml services: certbot: image: certbot/certbot volumes: - /etc/letsencrypt:/etc/letsencrypt - /var/lib/letsencrypt:/var/lib/letsencrypt command: renew ``` **Run renewal:** ```bash docker-compose run --rm certbot renew ``` ## 🐳 Docker - Nginx with Certbot Complete setup with Nginx and automated renewals. ```yaml services: nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - /etc/letsencrypt:/etc/letsencrypt:ro - ./nginx.conf:/etc/nginx/nginx.conf:ro restart: unless-stopped certbot: image: certbot/certbot volumes: - /etc/letsencrypt:/etc/letsencrypt - /var/lib/letsencrypt:/var/lib/letsencrypt - ./webroot:/var/www/certbot entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" ``` ## 🔧 Advanced - Custom Key Size Generate certificate with 4096-bit RSA key. ```bash sudo certbot certonly --rsa-key-size 4096 -d example.com ``` **Options:** - 2048 (default, recommended) - 4096 (more secure, slower) ## 🔐 Advanced - Elliptic Curve Keys Use ECDSA instead of RSA for better performance. ```bash sudo certbot certonly --key-type ecdsa --elliptic-curve secp384r1 -d example.com ``` **Curves available:** - secp256r1 (default) - secp384r1 (recommended) - secp521r1 ## 📌 Advanced - OCSP Stapling Enable OCSP stapling for better SSL performance. **Nginx configuration:** ```nginx ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; ``` **Apache configuration:** ```apache SSLUseStapling on SSLStaplingCache "shmcb:logs/ssl_stapling(32768)" ``` ## 🛡️ Advanced - HSTS Headers Enable HTTP Strict Transport Security. **Nginx:** ```nginx add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; ``` **Apache:** ```apache Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" ``` **Note:** Only enable after confirming HTTPS works perfectly. ## ✅ Best Practices - Security Checklist Production SSL security checklist. **Certificate:** - [ ] Use fullchain.pem (not cert.pem alone) - [ ] Enable OCSP stapling - [ ] Test with SSL Labs (A+ rating) **Web Server:** - [ ] Set strong SSL ciphers - [ ] Disable SSLv3, TLS 1.0, TLS 1.1 - [ ] Enable HSTS headers - [ ] Redirect all HTTP to HTTPS **Testing:** ```bash # Test SSL configuration sudo nginx -t sudo apachectl configtest # Test HTTPS curl -I https://example.com ``` ## 🔄 Best Practices - Renewal Strategy Automatic renewal best practices. **Checklist:** - [ ] Enable auto-renewal timer (systemctl enable certbot.timer) - [ ] Monitor certificate expiry (renew at 60 days) - [ ] Set up email/Slack alerts - [ ] Test renewal monthly with --dry-run - [ ] Keep logs for at least 90 days **Schedule:** - Let's Encrypt certs valid for 90 days - Auto-renewal runs twice daily - Renewal triggers at 30 days before expiry ## 💡 Best Practices - Production Tips Production deployment recommendations. **Load Balancers:** - Install certificates on origin servers - Terminate SSL at load balancer OR origin (not both) - Use health checks on port 443 **Cloudflare:** - Use "Full" or "Full (Strict)" SSL mode - Install origin certificate on server - Ensure port 80 reachable for HTTP challenge **Multi-Server:** - Use DNS-01 challenge (no port 80 needed) - Share certificates via NFS or copy manually - Consider centralized certificate management **Rate Limits:** - Max 50 certificates per registered domain/week - Plan domain naming accordingly - Use staging for testing ## 📊 Monitoring - Certificate Expiry Check certificate expiration from command line. ```bash echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate ``` **Output:** `notAfter=Dec 13 12:00:00 2025 GMT` ## 📅 Monitoring - Days Until Expiry Calculate days remaining until expiration. ```bash echo $(( ($(date -d "$(openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -enddate | cut -d= -f2)" +%s) - $(date +%s)) / 86400 )) ``` **Output:** Number of days (e.g., `60`) ## 🚨 Monitoring - Alert Script Automated monitoring script for certificate expiry. ```bash #!/bin/bash DOMAIN="example.com" CERT_PATH="/etc/letsencrypt/live/$DOMAIN/cert.pem" ALERT_DAYS=30 # Calculate days until expiry EXPIRY_DATE=$(openssl x509 -in $CERT_PATH -noout -enddate | cut -d= -f2) EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s) CURRENT_EPOCH=$(date +%s) DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 )) # Alert if expiring soon if [ $DAYS_LEFT -lt $ALERT_DAYS ]; then echo "WARNING: Certificate for $DOMAIN expires in $DAYS_LEFT days" # Send alert (email, Slack, etc.) fi ``` ## 💬 Monitoring - Slack Webhook Alert Send Slack notifications for expiring certificates. ```bash #!/bin/bash DOMAIN="example.com" SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" DAYS_LEFT=$(echo $(( ($(date -d "$(openssl x509 -in /etc/letsencrypt/live/$DOMAIN/cert.pem -noout -enddate | cut -d= -f2)" +%s) - $(date +%s)) / 86400 ))) if [ $DAYS_LEFT -lt 30 ]; then curl -X POST -H 'Content-type: application/json' \ --data "{\"text\":\"⚠️ SSL certificate for $DOMAIN expires in $DAYS_LEFT days\"}" \ $SLACK_WEBHOOK fi ``` **Schedule with cron (daily check):** ```bash 0 9 * * * /path/to/cert-monitor.sh ``` ## 📈 Monitoring - Prometheus Exporter Monitor certificates with Prometheus. **Install ssl_exporter:** ```bash docker run -d -p 9219:9219 ribbybibby/ssl-exporter:latest ``` **Prometheus config:** ```yaml scrape_configs: - job_name: 'ssl' metrics_path: /probe static_configs: - targets: - example.com:443 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: localhost:9219 ``` ## ⏱️ Advanced - Rate Limit Management Understand and work with Let's Encrypt rate limits. **Main limits:** - 50 certificates per registered domain per week - 5 duplicate certificates per week - 300 new orders per account per 3 hours - 10 accounts per IP per 3 hours **Check current usage:** ```bash # List all certificates sudo certbot certificates # Count certificates for a domain sudo certbot certificates | grep -c "example.com" ``` **Strategies:** - Use staging environment for testing (`--staging`) - Plan domain structure carefully - Renew before 30-day window - Delete unused certificates ## ⭐ Advanced - Wildcard Best Practices Optimize wildcard certificate usage. **Single wildcard covers all subdomains:** ```bash sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \ -d example.com -d '*.example.com' ``` **Benefits:** - One certificate for unlimited subdomains - Easier management - Lower rate limit usage **Considerations:** - Requires DNS-01 challenge - Root domain must be included separately - More sensitive (secure private key carefully) ## 📍 Advanced - Certificate Pinning Implement HTTP Public Key Pinning (deprecated, use with caution). **Extract public key:** ```bash openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -pubkey -noout | \ openssl pkey -pubin -outform der | \ openssl dgst -sha256 -binary | \ base64 ``` **Note:** HPKP is deprecated. Use Certificate Transparency monitoring instead. ──────────────────────────────────────────────────────────── Full page: https://devtools.krishanchawla.com/devtools/letsencrypt-advanced More tools: https://devtools.krishanchawla.com