What TLS Certificates Actually Do
TLS (Transport Layer Security, formerly SSL) certificates serve two critical purposes:
- Encryption: All traffic between client and server is encrypted, preventing eavesdropping on sensitive data.
- Identity verification: Certificates prove that the server you're connecting to is who it claims to be, preventing man-in-the-middle attacks.
A certificate is essentially a public key signed by a trusted authority (CA) that vouches for the identity of the server owner.
Certificate Types
- Domain Validated (DV): CA only verifies domain ownership. Fast issuance, free options available (Let's Encrypt). Sufficient for most homelab uses.
- Organization Validated (OV): CA verifies organization identity. Shows company name in certificate details. Not needed for homelabs.
- Extended Validation (EV): Strict identity verification, green bar in older browsers. Expensive, not relevant for homelabs.
- Self-signed: You create and sign your own certificate. Free, instant, but browsers will show security warnings unless you manually trust it.
- Internal CA: Your own certificate authority for LAN services. Trust it once on your devices, then issue unlimited certificates.
Let's Encrypt with Certbot
Let's Encrypt provides free, automated DV certificates. Here are the main methods:
HTTP-01 Challenge (Port 80)
The simplest method. Certbot places a file at /.well-known/acme-challenge/and Let's Encrypt verifies it via HTTP.
- Requires port 80 open to the internet (at least temporarily)
- Works with standalone mode or webroot mode behind Nginx/Apache
- Cannot issue wildcard certificates
# Standalone mode (stops existing web server)
sudo certbot certonly --standalone -d example.com
# Webroot mode (web server keeps running)
sudo certbot certonly --webroot -w /var/www/html -d example.comDNS-01 Challenge
Proves domain ownership by creating a DNS TXT record. Required for wildcard certificates.
- No open ports needed; works behind NAT or firewalls
- Supports wildcard certificates (
*.example.com) - Requires DNS provider API access for automation
# Manual DNS challenge
sudo certbot certonly --manual --preferred-challenges dns -d "*.example.com"
# Automated with Cloudflare plugin
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d example.com -d "*.example.com"Renewal
Let's Encrypt certificates expire after 90 days. Certbot sets up automatic renewal:
# Test renewal
sudo certbot renew --dry-run
# Force renewal
sudo certbot renew --force-renewal
# Check timer (systemd)
systemctl list-timers | grep certbotCloudflare Origin Certificates
If you use Cloudflare as your DNS and proxy, Origin Certificates are an excellent option:
- Valid for up to 15 years (no renewal headaches)
- Free with any Cloudflare plan
- Only valid between Cloudflare edge and your origin server
- Requires Cloudflare proxy (orange cloud) to be active
Generate from Cloudflare Dashboard → SSL/TLS → Origin Server → Create Certificate. Install the certificate and private key on your origin server (Nginx Proxy Manager, Traefik, etc.).
Cloudflare Tunnel + Origin Certs
For homelabs using Cloudflare Tunnel, you get automatic HTTPS:
- Tunnel handles encryption from Cloudflare to your server
- No ports open, no origin certificates needed
- Backend services can run on HTTP; tunnel encrypts in transit
- Optional: Add origin cert for end-to-end encryption even within tunnel
Internal PKI for LAN Services
For services that never touch the internet (internal dashboards, APIs, dev tools), run your own Certificate Authority:
mkcert (Simple)
Zero-config tool that creates a local CA and generates trusted certificates:
# Install mkcert
brew install mkcert # macOS
apt install mkcert # Debian/Ubuntu
# Install local CA (adds to system trust store)
mkcert -install
# Generate certificate
mkcert homelab.local "*.homelab.local" 192.168.1.100Copy the CA certificate to other devices and import into their trust stores for seamless HTTPS on your LAN.
step-ca (Enterprise-grade)
For more complex needs, step-ca provides a full-featured internal CA:
- ACME protocol support (auto-renewal like Let's Encrypt)
- Short-lived certificates for zero-trust architectures
- Integration with Kubernetes, SSH, and more
Troubleshooting Common Issues
Certificate chain incomplete
Browser shows "certificate not trusted" but cert looks valid. Usually missing intermediate certificates.
- Use SSL Labs test:
ssllabs.com/ssltest - Ensure your server sends the full chain (cert + intermediates)
- Let's Encrypt: Use
fullchain.pem, not justcert.pem
Certificate expired
- Check renewal timer/cron is running
- Verify DNS still points to correct server (for DNS-01)
- Check certbot logs:
/var/log/letsencrypt/letsencrypt.log - Manual renewal:
certbot renew --force-renewal
Wrong hostname / SAN mismatch
Certificate is valid but browser warns about hostname. The certificate's Subject Alternative Names (SANs) must include the exact hostname you're accessing.
- Check SANs:
openssl x509 -in cert.pem -text | grep -A1 "Subject Alternative" - Reissue certificate including all needed hostnames
- For wildcards:
*.example.comcoverssub.example.combut notexample.comitself
Mixed content warnings
Page loads over HTTPS but includes HTTP resources (images, scripts). Not a certificate issue but often appears alongside HTTPS setup.
- Update hardcoded
http://URLs tohttps://or protocol-relative// - Check browser dev tools for specific resources
Certificate Monitoring
Don't let certificates expire unexpectedly:
- Use the SSL Checker tool on this site to inspect certificates and check expiration dates.
- Set up monitoring with Uptime Kuma, Prometheus blackbox exporter, or commercial services like cert-manager alerts.
- Subscribe to Let's Encrypt expiration emails (they notify at 20 days remaining).
Best Practices Summary
- Use Let's Encrypt for public-facing services; it's free and automated
- Use Cloudflare Origin Certificates if you're already proxying through Cloudflare
- Use mkcert or step-ca for internal LAN services
- Always serve the full certificate chain
- Monitor expiration dates and set up alerts
- Test certificates with SSL Labs and browser dev tools
- Keep private keys secure; never commit them to git
- Use wildcard certificates sparingly; they're powerful but increase risk if compromised
Validation Checklist
- All public services show padlock in browser without warnings
- SSL Labs test shows A or A+ rating
- Automatic renewal is configured and tested
- Internal services use trusted internal CA certificates
- Monitoring alerts are set up for expiration warnings
- Private keys are stored securely with appropriate permissions