Why HTTPS Matters
HTTP is plaintext. Every request and response travels across the network readable by anyone positioned between the client and the server — ISPs, coffee shop routers, government surveillance infrastructure, or an attacker on the same Wi-Fi network. This isn't theoretical; it's trivial to intercept with tools like Wireshark.
HTTPS wraps the connection in TLS. The content is encrypted, the server's identity is verified via its certificate, and tampering is detected. For a personal site with no login forms, this might seem unnecessary — but HTTPS also prevents content injection by middleboxes (some ISPs inject ads into HTTP traffic) and is required for many modern browser features.
Nginx Configuration
Nginx is configured with separate server blocks loaded from conf.d/ via the include directive. Same principle as sudoers.d: one file per site, isolated from the main config. Adding or removing a site means adding or removing a file, not editing a monolithic configuration. This is easier to audit and harder to break by accident.
The server block defines which domain to respond to, where to find the site files, and how to handle requests. For now it serves static files directly; later it will proxy to an application server.
Let's Encrypt and Certbot
I used Let's Encrypt with certbot's nginx plugin to obtain a free TLS certificate. Certbot handles the entire process: it proves domain ownership to Let's Encrypt, retrieves the certificate, configures nginx to use it, and sets up HTTP-to-HTTPS redirection automatically.
The result: requests to port 80 are permanently redirected to port 443. There is no way to access the site over plaintext HTTP. The redirect is a 301 (permanent), which tells browsers and search engines to always use HTTPS going forward.
Automated Renewal
Let's Encrypt certificates expire after 90 days. This is intentional — short lifetimes limit the damage window if a certificate's private key is compromised. But it means renewal must be automated.
Certbot installs a systemd timer (certbot-renew.timer) that runs the renewal check twice daily. If the certificate is within 30 days of expiry, it renews automatically. I verified the pipeline works:
sudo certbot renew --dry-run
This simulates the renewal process without actually replacing the certificate. If it succeeds, the automation will work when the time comes.
The Trust Chain
When a browser connects to my site, the TLS handshake involves several steps: the server presents its certificate, the browser verifies it was signed by a trusted Certificate Authority (Let's Encrypt), and they negotiate an encrypted session. All of this happens before a single byte of content is transferred.
The certificate doesn't just encrypt — it proves identity. Without it, an attacker could impersonate the server (a man-in-the-middle attack) and the browser would have no way to detect the substitution. HTTPS solves both problems: confidentiality and authenticity.