Nginx SSL & HTTPS Configuration: The Complete Guide

By G.Bharat Kumar

Running an unencrypted web server on port 80 is no longer an option. In modern web deployment, configuring Nginx SSL/HTTPS is mandatory for security, user trust, and SEO. However, getting a green padlock is only the first step.

In this comprehensive guide, we will cover exactly how to configure an impenetrable Nginx HTTPS setup. From automating Let's Encrypt Nginx certificates to configuring modern Cipher Suites, Diffie-Hellman parameters, HTTP/2, and strict security headers, this 3000+ word tutorial covers everything a DevOps engineer needs to know.

Quick Solution: The Modern SSL Block

Need a secure Nginx configuration right now? Use this block to redirect HTTP to HTTPS and apply modern TLSv1.2/1.3 standards.

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

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

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    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 off;
    
    # HSTS (requires preloading)
    add_header Strict-Transport-Security "max-age=63072000" always;
}

1. Understanding the Authority Triangle

Before we dive into generating certificates, it's essential to understand where SSL fits into the broader Nginx ecosystem. This article is part of our ZeroData Nginx Authority Triangle:

2. Automating Let's Encrypt in Nginx

Historically, obtaining an SSL certificate meant generating a CSR (Certificate Signing Request), paying a Certificate Authority (CA) hundreds of dollars, and manually placing .pem files on your server.

Today, Let's Encrypt has revolutionized this process by providing free, automated certificates. The standard tool for this is certbot.

Installing Certbot

On Ubuntu/Debian systems, you can install Certbot and the Nginx plugin with a single command:

sudo apt update
sudo apt install certbot python3-certbot-nginx

Obtaining the Certificate

Ensure you have a basic Nginx server block listening on port 80 for your domain:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/html;
}

Then, simply run Certbot. The Nginx plugin will automatically parse your config files, perform the ACME challenge, and rewrite your configuration to include the SSL directives.

sudo certbot --nginx -d example.com -d www.example.com

Certbot automatically sets up a cron job (or systemd timer) to renew these certificates before their 90-day expiration window closes.

3. Deep Dive into ssl_certificate Directives

If you look closely at the Nginx configuration generated by Certbot, you will notice two critical directives:

  • ssl_certificate: Points to the fullchain.pem file. This file contains not just your domain's public key certificate, but also the intermediate certificates required to establish a chain of trust back to a root CA.
  • ssl_certificate_key: Points to the privkey.pem file. This is your server's private key. It must remain completely secret. If this key is compromised, attackers can impersonate your server and decrypt traffic.

4. Hardening TLS Protocols and Ciphers

By default, old versions of Nginx might enable outdated protocols like TLSv1.0 or TLSv1.1, which are vulnerable to attacks like BEAST and POODLE. In 2026, you should strictly enforce TLSv1.2 and TLSv1.3.

ssl_protocols TLSv1.2 TLSv1.3;

Furthermore, you must define which encryption ciphers are acceptable. We strongly recommend using Mozilla's "Intermediate" or "Modern" cipher recommendations.

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;
ssl_prefer_server_ciphers off;

Notice ssl_prefer_server_ciphers off;. In TLSv1.3, it is generally recommended to let the client dictate the cipher suite from the secure list you provide, especially to take advantage of ChaCha20-Poly1305 on mobile devices without hardware AES acceleration.

5. Perfect Forward Secrecy and Diffie-Hellman

Perfect Forward Secrecy (PFS) ensures that even if your server's private key is compromised in the future, past traffic cannot be decrypted. This is achieved using the Diffie-Hellman (DH) key exchange.

Nginx defaults to a 1024-bit DH prime, which is vulnerable to the Logjam attack. You must generate a custom, highly secure 2048 or 4096-bit prime:

sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096

Then, instruct Nginx to use it:

ssl_dhparam /etc/nginx/dhparam.pem;

6. Enabling HTTP/2 for Performance

HTTP/2 introduces multiplexing, allowing multiple requests to share a single TCP connection, drastically improving load times for sites with many assets. Nginx makes this trivial to enable, provided you are using SSL (browsers require HTTPS for HTTP/2).

listen 443 ssl http2;

Note: If you are using Nginx 1.25.1 or later, the http2 parameter has been deprecated inside the listen directive in favor of a standalone http2 on; directive.

7. Security Headers: HSTS

Even if you redirect HTTP to HTTPS, a user typing `example.com` into their browser initially makes an insecure HTTP request. An attacker on the same network could intercept this initial request and strip the redirect (SSL Stripping).

HTTP Strict Transport Security (HSTS) solves this. It tells the browser "For the next X seconds, never attempt to connect to this site using insecure HTTP."

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

Use our Security Headers Builder to visually construct and validate your HSTS and Content-Security-Policy headers before deploying them.

Conclusion

Configuring an Nginx SSL/HTTPS server goes far beyond simply turning on port 443. By combining Let's Encrypt automation, strict cipher suites, custom DH parameters, HTTP/2, and HSTS headers, you ensure your application meets the highest standards of modern cryptographic security.

Always remember to continuously test your endpoints. When diagnosing complex certificate chains, do not paste your private keys or sensitive certs into remote servers. Instead, utilize client-side tools like the X.509 Certificate Decoder to maintain absolute privacy.

Frequently Asked Questions

How do I redirect HTTP to HTTPS in Nginx?

To redirect all HTTP traffic to HTTPS, create a server block listening on port 80 and use the directive return 301 https://$host$request_uri;. This ensures all unencrypted traffic is permanently redirected.

What is Let's Encrypt and how does it work with Nginx?

Let's Encrypt is a free, automated, and open certificate authority. By installing Certbot and the python3-certbot-nginx plugin, you can automatically provision and renew trusted SSL certificates for your Nginx server.

What are the best SSL protocols and ciphers to use in 2026?

In 2026, you should exclusively use TLSv1.2 and TLSv1.3. Disable SSLv3, TLSv1.0, and TLSv1.1 entirely. Use modern AEAD ciphers like ECDHE-ECDSA-AES128-GCM-SHA256 and CHACHA20-POLY1305.

How do I enable HTTP/2 in Nginx?

To enable HTTP/2 in Nginx, simply add http2 to your listen directive (e.g., listen 443 ssl http2;). Note that in Nginx version 1.25.1 and later, the http2 on; directive is used instead if you don't append it to listen.

Why do I need a Diffie-Hellman parameter file (dhparam)?

A Diffie-Hellman parameter file ensures Perfect Forward Secrecy (PFS) using a strong, unique key exchange modulus (at least 2048-bit, preferably 4096-bit). Without it, Nginx uses a weak default 1024-bit key, making you vulnerable to Logjam attacks.