Configuring the Server

Chapter 10
Configuring HTTPS on a Server
nginx/Apache TLS config, redirects, HSTS, OCSP stapling, and grading with SSL Labs

You have a certificate (Chapter 9). Now you wire it into a web server correctly — not just "it works," but configured so the grading tools give you an A. This chapter is the practical payoff: the handful of directives that matter, the mistakes that cost a grade, and how to verify the result.

The Minimum: Certificate, Key, and Protocols

A basic TLS server block needs three things: the certificate chain, the private key, and which protocols/ciphers to allow. Here's an nginx example carrying everything from the last two chapters:

server { listen 443 ssl; server_name example.com www.example.com; # full chain = leaf + intermediates (Chapter 5!), NOT just the leaf ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # only modern protocols (Chapter 8) ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; # let 1.3 pick; fine for modern suites }
Use fullchain.pem, not cert.pem — the missing-intermediate trap
Certbot writes several files; the two that matter are fullchain.pem (leaf plus intermediates) and privkey.pem. Point ssl_certificate at fullchain.pem. If you accidentally use cert.pem (the leaf alone), you recreate exactly the Chapter 5 "missing intermediate" bug: it works in some browsers (which cache the intermediate) and fails on other clients with "unable to get local issuer certificate." This is the single most common server-config TLS mistake — get this one line right.

Redirect HTTP → HTTPS

Serving HTTPS isn't enough if visitors can still reach plain HTTP. Add a second server block on port 80 that redirects everything to HTTPS, so no one accidentally uses the insecure version:

server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; # permanent redirect to HTTPS }

A 301 (permanent) redirect tells browsers and search engines the HTTPS URL is canonical. But a redirect alone has a subtle gap — which is exactly what HSTS closes.

HSTS — Don't Even Try HTTP Next Time

A plain redirect still involves one insecure HTTP request first (the one that gets redirected) — and an active attacker could intercept that initial request before the redirect happens (an "SSL stripping" attack, Chapter 11). HSTS (HTTP Strict Transport Security) fixes this with a response header that tells the browser: for the next N seconds, never use HTTP for this domain at all — go straight to HTTPS yourself.

# sent over HTTPS; browser remembers it and auto-upgrades future requests add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

After the first secure visit, the browser refuses to make any plaintext request to the domain for a year (max-age=31536000), eliminating the vulnerable first hop on every subsequent visit. includeSubDomains extends the rule to all subdomains.

HSTS is a commitment — test before you set a long max-age
Once a browser has seen the HSTS header, it will refuse to connect over HTTP (or to a cert it can't validate) for the full max-age — there's no clickthrough. If your HTTPS later breaks (expired cert, misconfiguration), users are locked out, not merely warned, until you fix it or the max-age elapses. So roll it out gradually: start with a short max-age (e.g. 300), confirm everything's solid, then raise it to a year. The preload list (hardcoded into browsers) is even more permanent — only submit once you're certain.

OCSP Stapling — Faster, More Private Revocation Checks

Browsers want to know a cert hasn't been revoked (Chapter 11). The old way: the browser separately contacts the CA's OCSP responder — which is slow and leaks to the CA which sites you visit. OCSP stapling flips this: the server periodically fetches a fresh, CA-signed "this cert is still valid" proof and staples it to the TLS handshake, so the browser gets it instantly without contacting the CA.

ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

It's a win on every axis: faster handshakes (no extra round trip to the CA), better privacy (the CA doesn't see each visitor), and less load on the CA. It's a standard part of a well-tuned config.

The Apache Equivalent

PurposenginxApache
Cert (full chain)ssl_certificate fullchain.pemSSLCertificateFile fullchain.pem
Private keyssl_certificate_key privkey.pemSSLCertificateKeyFile privkey.pem
Protocolsssl_protocols TLSv1.2 TLSv1.3SSLProtocol -all +TLSv1.2 +TLSv1.3
HSTSadd_header Strict-Transport-Security ...Header always set Strict-Transport-Security ...
OCSP staplingssl_stapling on;SSLUseStapling on

The concepts are identical — only the directive names differ. Certbot's --nginx / --apache plugins generate much of this for you, but knowing what each line does is what lets you debug and harden it.

Verify: Grade It with SSL Labs

Don't guess whether your config is good — measure it. Qualys SSL Labs (ssllabs.com/ssltest) runs a deep audit and assigns a letter grade, checking everything from this course: protocol versions, cipher suites, chain completeness, HSTS, key strength, and known vulnerabilities.

What an A/A+ requires — a checklist of this whole course
To score A+: serve the full chain (Ch. 5), support only TLS 1.2 + 1.3 with strong AEAD/ECDHE suites (Ch. 8), use a 2048-bit+ RSA or 256-bit EC key, enable HSTS with a long max-age, and have no known-vulnerable settings. The A+ specifically rewards HSTS. Notice the grade is essentially a checklist of everything you've learned — SSL Labs is a great way to see the theory reflected in a real score. (For automation/CI, testssl.sh gives similar results from the command line.)

Hands-On Exercises

Exercise 1

Write a complete nginx configuration for example.com that: serves the full chain + key, supports only TLS 1.2/1.3, redirects HTTP→HTTPS with a 301, and sets a one-year HSTS header with includeSubDomains. Annotate which line prevents the missing-intermediate bug and why.

📄 View solution
Exercise 2

Explain the gap that a plain HTTP→HTTPS redirect leaves open, then explain precisely how HSTS closes it. Include why HSTS only protects after the first secure visit, and what the preload list does about that residual first-visit gap.

📄 View solution
Exercise 3

Describe what OCSP stapling is and the three problems it solves versus a browser doing its own OCSP lookup. Then list what an SSL Labs A+ grade requires, mapping each requirement back to the chapter that introduced it.

📄 View solution

Chapter 10 Quick Reference

  • Minimum config: ssl_certificate (full chain) + ssl_certificate_key + ssl_protocols TLSv1.2 TLSv1.3
  • Use fullchain.pem, never cert.pem — the leaf-only file recreates the missing-intermediate bug
  • Redirect HTTP→HTTPS with a 301 on a port-80 server block
  • HSTS (Strict-Transport-Security) — browser auto-upgrades to HTTPS, closing the redirect's insecure first hop (SSL-stripping defence)
  • HSTS is a commitment: long max-age locks users out if HTTPS breaks — start short, then raise; preload is near-permanent
  • OCSP stapling — server staples a fresh CA-signed validity proof: faster handshake, better privacy, less CA load
  • Apache uses the same concepts with SSLCertificateFile, SSLProtocol, SSLUseStapling, etc.
  • Verify with SSL Labs (or testssl.sh) — an A+ is a checklist of this whole course
  • Next chapter: common problems & attacks — expired/mismatched certs, mixed content, downgrade & SSL-stripping, revocation