MervCodes

Tech Reviews From A Programmer

SSL/TLS Certificates Explained for Developers: HTTPS, Let's Encrypt and More

1 min read

Why Every Developer Needs to Understand SSL/TLS

If you've ever deployed a web application, you've dealt with SSL/TLS certificates. That green padlock in the browser bar isn't just a cosmetic detail — it represents a chain of cryptographic trust that protects your users' data in transit. Yet many developers treat certificates as a "DevOps problem" and only engage with them when something breaks at 2 AM.

Understanding how SSL/TLS works will make you a better developer. You'll debug connection issues faster, architect more secure systems, and avoid the kind of misconfigurations that lead to data breaches. Let's break it all down.

SSL vs TLS: Clearing Up the Terminology

SSL (Secure Sockets Layer) is technically dead. The last version, SSL 3.0, was deprecated in 2015 due to the POODLE vulnerability. What we actually use today is TLS (Transport Layer Security), currently at version 1.3.

Despite this, the industry still says "SSL certificates" out of habit. When someone says SSL, they almost always mean TLS. The certificates themselves are the same — it's the protocol that changed. In this article, we'll use "TLS" when referring to the protocol and "SSL/TLS certificate" when talking about the certificates themselves, since that's what you'll encounter in documentation and tooling.

How the TLS Handshake Works

When a client (browser) connects to your server over HTTPS, a TLS handshake occurs before any application data is exchanged. Here's the simplified flow for TLS 1.3:

  1. Client Hello — The client sends supported cipher suites and a key share.
  2. Server Hello — The server selects a cipher suite, sends its key share and its certificate.
  3. Certificate Verification — The client verifies the server's certificate against trusted Certificate Authorities (CAs).
  4. Finished — Both sides derive session keys and begin encrypted communication.

TLS 1.3 completes this in a single round trip (1-RTT), a major improvement over TLS 1.2's two round trips. For repeat visitors, 0-RTT resumption makes it even faster.

The critical takeaway: your certificate is what proves to the client that your server is who it claims to be. Without a valid certificate, the handshake fails and the user sees a security warning.

Anatomy of an SSL/TLS Certificate

A certificate is essentially a signed document containing:

  • Subject — The domain name(s) the certificate covers (e.g., example.com)
  • Public Key — Used during the key exchange
  • Issuer — The Certificate Authority that signed it
  • Validity Period — Start and expiration dates
  • Signature — The CA's cryptographic signature proving authenticity
  • Subject Alternative Names (SANs) — Additional domains or subdomains covered

You can inspect any site's certificate with OpenSSL:

openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text

Or more concisely, to check expiration:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

Types of Certificates

By Validation Level

  • Domain Validation (DV) — Proves you control the domain. Issued in minutes. This is what Let's Encrypt provides and what most applications need.
  • Organization Validation (OV) — Verifies your organization's identity. Takes days. Adds the organization name to the certificate.
  • Extended Validation (EV) — Rigorous vetting of the legal entity. Historically displayed the company name in the browser bar, but most browsers have dropped this UI distinction.

For the vast majority of developers, DV certificates are sufficient. OV and EV certificates don't provide stronger encryption — the cryptographic protection is identical.

By Scope

  • Single Domain — Covers one domain (e.g., example.com)
  • Wildcard — Covers a domain and all its subdomains (e.g., *.example.com). Note: this does NOT cover the apex domain itself or nested subdomains like *.sub.example.com.
  • Multi-Domain (SAN) — Covers multiple unrelated domains in a single certificate.

Let's Encrypt: Free Certificates for Everyone

Let's Encrypt revolutionized web security by providing free, automated DV certificates. Before its launch in 2015, certificates cost money and required manual renewal — leading many sites to skip HTTPS entirely.

How It Works

Let's Encrypt uses the ACME (Automatic Certificate Management Environment) protocol. The most popular ACME client is Certbot, but alternatives like acme.sh, Caddy's built-in ACME, and Traefik's integration also exist.

Getting a Certificate with Certbot

# Install certbot
sudo apt install certbot python3-certbot-nginx

# Obtain and install a certificate for Nginx
sudo certbot --nginx -d example.com -d www.example.com

# Or standalone mode (useful for non-web servers)
sudo certbot certonly --standalone -d example.com

Automatic Renewal

Let's Encrypt certificates expire every 90 days — intentionally short to encourage automation. Certbot installs a systemd timer or cron job automatically:

# Test renewal
sudo certbot renew --dry-run

# The actual renewal runs automatically via systemd timer
systemctl list-timers | grep certbot

Using Caddy for Zero-Config HTTPS

If you want the simplest possible setup, Caddy handles certificates automatically with zero configuration:

example.com {
    reverse_proxy localhost:3000
}

That's it. Caddy obtains, installs, and renews certificates from Let's Encrypt without any additional setup.

Certificate Management in Production

The Certificate Chain

Your server must send not just its own certificate, but the full chain up to (but not including) the root CA. A common misconfiguration is serving only the leaf certificate, which causes validation failures on some clients.

The chain looks like:

Root CA (trusted, pre-installed in browsers/OS)
  └── Intermediate CA (signed by Root)
        └── Your Certificate (signed by Intermediate)

You can verify your chain is correctly configured:

openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | grep -A 2 "Certificate chain"

Or use an online tool like SSL Labs' SSL Test for a comprehensive audit.

Storing Private Keys Securely

Your private key is the crown jewel. If it's compromised, an attacker can impersonate your server.

  • Never commit private keys to version control. Use .gitignore and scan for accidental commits.
  • Restrict file permissions: chmod 600 privkey.pem and ensure only the web server user can read it.
  • Use secrets management in cloud environments (AWS Secrets Manager, HashiCorp Vault, etc.) rather than storing keys on disk.
  • Consider hardware security modules (HSMs) for high-security applications.

Certificate Pinning — Mostly Don't

Certificate pinning (hardcoding expected certificates in your app) was once recommended but is now widely discouraged. It causes brittle deployments — if you need to rotate a certificate and your pinning config is stale, your app breaks. Google removed support for HTTP Public Key Pinning (HPKP) from Chrome in 2018. Use Certificate Transparency monitoring instead.

Common Pitfalls and How to Fix Them

Mixed Content Warnings

Your page loads over HTTPS but references HTTP resources (images, scripts, stylesheets). Fix by using protocol-relative URLs or, better, absolute HTTPS URLs. Set the Content-Security-Policy: upgrade-insecure-requests header as a safety net.

Certificate Expiration

The number one cause of certificate-related outages. Even large companies have suffered this. Set up monitoring:

# Simple expiry check script
EXPIRY=$(echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
echo "Certificate expires: $EXPIRY"

Use monitoring tools like Uptime Robot, Datadog, or a simple cron job that alerts you 30 days before expiration.

SNI (Server Name Indication) Issues

If you host multiple domains on one IP, you need SNI — the client sends the hostname during the TLS handshake so the server knows which certificate to present. Very old clients (Windows XP, Android 2.x) don't support SNI, but this is rarely a concern today.

Self-Signed Certificates in Development

For local development, use tools like mkcert to create locally-trusted certificates:

# Install mkcert
brew install mkcert   # macOS
mkcert -install       # Install local CA

# Create a certificate for localhost
mkcert localhost 127.0.0.1 ::1

This avoids the browser security warnings you'd get with raw self-signed certificates and is far better than disabling certificate verification in your code.

TLS Configuration Best Practices

When configuring your server, follow these guidelines:

  • Use TLS 1.2 or 1.3 only. Disable TLS 1.0 and 1.1 — they are deprecated.
  • Use strong cipher suites. Prefer AEAD ciphers like AES-256-GCM and CHACHA20-POLY1305.
  • Enable HSTS (HTTP Strict Transport Security) to tell browsers to always use HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • Enable OCSP Stapling to speed up certificate validation.
  • Use Mozilla's SSL Configuration Generator to produce secure configs for Nginx, Apache, HAProxy, and others.

FAQ

Do I still need to pay for SSL/TLS certificates?

For most use cases, no. Let's Encrypt provides free DV certificates that are trusted by all major browsers. You'd only pay for OV/EV certificates if your organization specifically requires them for compliance or policy reasons.

Does HTTPS make my site slower?

Not meaningfully. TLS 1.3's 1-RTT handshake adds minimal latency, and session resumption (0-RTT) eliminates it for returning visitors. The computational overhead of encryption is negligible on modern hardware. HTTP/2 and HTTP/3 actually require HTTPS and deliver significant performance improvements.

Can I use a wildcard certificate with Let's Encrypt?

Yes. You need to use DNS-01 challenge validation instead of HTTP-01. Example with Certbot:

sudo certbot certonly --manual --preferred-challenges dns -d "*.example.com" -d "example.com"

Many DNS providers have plugins for automated DNS challenge completion.

What happens when a certificate expires?

Browsers display a full-page security warning, and most users will leave immediately. APIs and services making HTTPS calls will get connection errors. Search engines may also drop your rankings. In short: automate renewal and monitor expiration.

How do I handle certificates in containerized environments?

Use a reverse proxy (Nginx, Caddy, Traefik) at the edge to terminate TLS, and communicate over plain HTTP internally within your container network. Tools like cert-manager in Kubernetes automate certificate lifecycle management with Let's Encrypt.

What is Certificate Transparency?

Certificate Transparency (CT) is a public logging system where CAs must publish all issued certificates. You can monitor CT logs (via services like crt.sh or Facebook's CT monitoring) to detect unauthorized certificates issued for your domains.

Wrapping Up

SSL/TLS certificates are a foundational piece of web security that every developer should understand beyond the surface level. The ecosystem has matured enormously — between Let's Encrypt's free automation and modern web servers that handle certificates out of the box, there's no excuse for running anything over plain HTTP.

Start with Let's Encrypt and Certbot for straightforward setups, consider Caddy if you want zero-config HTTPS, and always monitor your certificate expiration dates. Keep your private keys secure, serve the full certificate chain, and stay on TLS 1.2+ with strong cipher suites. Your users — and your 2 AM self — will thank you.

Related Articles