Nginx doesn’t actually do HTTPS; it just speaks the TLS protocol really, really well.

Let’s see Nginx in action. Imagine you’ve got a web server and you want to serve encrypted traffic. Here’s a minimal nginx.conf snippet to get HTTPS rolling:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    location / {
        proxy_pass http://localhost:8080;
    }
}

This tells Nginx to listen on port 443 for SSL/TLS connections, use the specified certificate and key files, and then proxy requests to a backend running on port 8080. Simple enough, but the real magic is in hardening.

The problem Nginx solves with TLS is enabling secure, encrypted communication over an otherwise insecure network like the internet. Without it, anyone sniffing traffic could see sensitive data like login credentials or credit card numbers in plain text. TLS creates a secure tunnel using public-key cryptography and symmetric encryption.

Internally, Nginx handles the TLS handshake. This is a multi-step process where the client (your browser) and the server (Nginx) negotiate the encryption parameters. First, the client requests a connection. Nginx then sends its certificate, proving its identity. The client verifies this certificate against trusted Certificate Authorities (CAs). Next, they agree on a cipher suite (the specific algorithms for encryption, authentication, and key exchange) and generate a shared secret key for symmetric encryption of the actual data. This handshake is crucial; if it fails, no secure connection is established.

The levers you control in Nginx are primarily within the ssl_ directives. ssl_certificate and ssl_certificate_key are fundamental, pointing to your server’s identity. But beyond that, you can fine-tune security with:

  • ssl_protocols: This dictates which versions of the TLS protocol Nginx will accept. Modern configurations should disable older, vulnerable versions.
  • ssl_ciphers: This is a list of acceptable cipher suites. Nginx will try to negotiate the strongest one supported by both client and server.
  • ssl_prefer_server_ciphers: When set to on, Nginx will prioritize its own cipher suite preference list over the client’s.
  • ssl_session_cache: Stores previously negotiated session parameters, allowing clients to resume sessions faster without a full handshake.
  • ssl_session_timeout: How long these cached sessions remain valid.

Here’s an example of a more hardened ssl block:

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off; # Consider disabling for Perfect Forward Secrecy
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
}

This configuration enables HTTP/2, specifies only TLS 1.2 and 1.3 (disabling older, insecure versions), and uses a strong, modern cipher suite. ssl_session_cache with 10m allows for 10 megabytes of shared session data, and ssl_session_timeout 10m means sessions are valid for 10 minutes. ssl_session_tickets off is a common recommendation for maximizing Perfect Forward Secrecy (PFS), although it means more full handshakes. ssl_stapling and ssl_stapling_verify improve performance and security by allowing Nginx to cache OCSP responses from the CA, reducing the client’s need to query the CA directly. The resolver directives are for DNS lookups, critical for stapling.

The most surprising thing most people don’t realize is that Nginx doesn’t just use the certificate and key; it actively participates in the cryptographic negotiation based on those credentials. It’s not a passive holder of keys. It’s the engine driving the secure connection, making choices about algorithms, and verifying the client’s trust in its identity.

The next step is often understanding how to manage certificate renewals automatically.

Want structured learning?

Take the full Tls-ssl course →