Learning nginx - Securing NGINX with SSL/TLS (HTTPS) & Let's Encrypt
Episode 9 of 21

Learning nginx - Securing NGINX with SSL/TLS (HTTPS) & Let's Encrypt

This episode explains the concepts of SSL/TLS and HTTPS, manual HTTPS server blocks, free certificate automation with Certbot and Let's Encrypt, auto-renewal, and HTTP to HTTPS redirects.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

A website without HTTPS is an invitation to eavesdroppers. The data being sent can be read and modified in transit. This Episode 9 covers SSL/TLS and HTTPS on NGINX, from basic concepts to free certificate automation with Let's Encrypt.

You'll write a manual HTTPS server block, create free certificates with Certbot, set up automatic renewal, and redirect all HTTP traffic to HTTPS. By the end of this episode, your domain will be secure with a security rating worth showing off.

The Concepts: SSL/TLS & HTTPS

Encryption Between Client and Server

HTTPS is HTTP on top of a TLS layer. Before any data is sent, the client and server perform a TLS handshake: they exchange keys, verify the server's identity through a certificate, and establish an encrypted channel. After that, all traffic data can't be read or modified by third parties.

Certificates are issued by a Certificate Authority (CA) trusted by browsers. Browsers verify that the certificate is valid for the domain being visited, so clients are confident they're communicating with the right server.

Manual HTTPS Server Block Configuration

Certificate and Key

First, prepare the certificate and private key. For production, use a certificate from a trusted CA. For local experiments, you can create a self-signed certificate:

Create a self-signed certificate for testing
sudo openssl req -x509 -nodes -newkey rsa:2048 \
    -keyout /etc/ssl/private/example.key \
    -out /etc/ssl/certs/example.crt \
    -days 365 -subj "/CN=example.com"

The 443 Server Block

The HTTPS server block uses the ssl_certificate and ssl_certificate_key directives:

Manual HTTPS server block
server {
    listen 443 ssl;
    server_name example.com;
 
    ssl_certificate /etc/ssl/certs/example.crt;
    ssl_certificate_key /etc/ssl/private/example.key;
 
    root /var/www/example;
    index index.html;
}

listen 443 ssl; enables TLS on port 443. After editing, run nginx -t and reload.

Free SSL Automation with Certbot

Installing Certbot and the NGINX Plugin

Let's Encrypt provides free certificates valid for 90 days. Certbot automates the issuance and installation:

Install certbot on Ubuntu
sudo apt install certbot python3-certbot-nginx -y

Make sure the domain's DNS already points to the server's IP and that port 80 is reachable from the internet, because the verification process needs HTTP access.

Issuing a Certificate in One Command

Run certbot with the NGINX plugin:

Issue a Let's Encrypt certificate
sudo certbot --nginx -d example.com -d www.example.com

Certbot will verify domain ownership, issue the certificate, modify the NGINX configuration automatically, and add an HTTP to HTTPS redirect. The certbot --nginx command also stores the settings for automatic renewal.

Automating Certificate Renewal

Auto-Renewal with the systemd Timer

Let's Encrypt certificates last 90 days, so renewal must be automatic. Certbot provides a systemd timer:

Enable auto-renewal
sudo systemctl enable --now certbot.timer
sudo systemctl list-timers certbot.timer

certbot.timer runs renewal twice a day and only renews certificates with fewer than 30 days left. After a successful renewal, Certbot automatically reloads NGINX.

To test the renewal flow without actually renewing:

Simulate renewal
sudo certbot renew --dry-run

certbot renew --dry-run makes sure the whole renewal pipeline works before it's truly needed.

Redirecting HTTP to HTTPS

The Port 80 Server Block

Every domain using HTTPS must also handle HTTP requests. The most common approach:

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

The return 301 https://$host$request_uri; directive moves all HTTP requests to HTTPS with a permanent status. The $host and $request_uri variables keep the domain and path intact. This is also what Certbot does automatically when you use --nginx.

Verifying the Security Setup

Checking the Handshake and Headers

Once the configuration is active, verify from the client side:

Verify HTTPS
curl -I https://example.com
curl -I http://example.com

The HTTPS response should show HTTP/2 200, and the HTTP request should be redirected with 301. All traffic is now encrypted.

Conclusion

Episode 9 closed the biggest security gap: you understand TLS concepts, write manual HTTPS server blocks, issue free certificates with Certbot and Let's Encrypt, set up auto-renewal, and redirect all traffic to HTTPS.

Key takeaways:

  • HTTPS is HTTP encrypted with TLS, proven through certificates.
  • listen 443 ssl; together with ssl_certificate and ssl_certificate_key creates manual HTTPS.
  • Certbot issues free Let's Encrypt certificates with certbot --nginx.
  • Auto-renewal runs automatically through the certbot.timer timer.
  • certbot renew --dry-run tests the renewal pipeline.
  • Redirect HTTP to HTTPS with return 301 https://$host$request_uri;.

In the next episode we'll discuss SSL/TLS security hardening and protocols — enabling HTTP/2 and HTTP/3, restricting ssl_protocols and ssl_ciphers, turning on HSTS, OCSP stapling, and custom DH parameters.