Short answer

A secure nginx TLS setup points ssl_certificate at the fullchain (not just the leaf), allows only TLSv1.2 and TLSv1.3, uses a short list of strong cipher suites, enables OCSP stapling and sets HSTS. After changes you run nginx -t and then nginx -s reload to put it into use with zero downtime.

The complete server block

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com www.example.com;

    # Fullchain (leaf + intermediates), not just cert.pem
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;

    # Modern protocols only
    ssl_protocols TLSv1.2 TLSv1.3;

    # Let the server decide cipher order (only relevant for 1.2)
    ssl_prefer_server_ciphers on;
    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;

    # Session resumption (no tickets => better forward secrecy)
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/example.com/chain.pem;
    resolver 1.1.1.1 8.8.8.8 valid=300s;
    resolver_timeout 5s;

    # HSTS (only add preload once you are sure)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    root /var/www/example.com;
}

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

Why fullchain, not cert.pem

If you point ssl_certificate at the leaf certificate only, the server does not send the intermediate — and curl, Java and mobile apps fail with "unable to get local issuer certificate", even though the browser works. Always use fullchain.pem (certbot's default file) so the whole certificate chain is served.

Protocols and ciphers

TLS 1.0 and 1.1 are retired; allow only 1.2 and 1.3. For TLS 1.3 the client chooses the cipher and the list is fixed and strong — you only need to set ssl_ciphers for 1.2. Keep the list short and restricted to AEAD ciphers with forward secrecy (ECDHE). Read more about the best cipher suites.

OCSP stapling and HSTS

OCSP stapling lets the server attach a fresh proof of the certificate's validity itself, so the client does not have to contact the CA — faster and more private. ssl_trusted_certificate must point at the issuer chain. HSTS forces the browser to always use HTTPS. Details in OCSP stapling explained and what is HSTS.

Test and reload

# Validate config BEFORE reloading
sudo nginx -t

# Graceful reload — no downtime
sudo nginx -s reload

# Confirm what is actually served
openssl s_client -connect example.com:443 -servername example.com

More on swapping the certificate without dropping connections in certificate rotation without downtime, and how to keep the certificate renewed automatically in the ACME pillar.

How CertControl verifies your nginx endpoints

A configuration that looks right in the file is not necessarily what is served — a forgotten reload, a wrong path or an expired stapling chain makes the difference. CertControl scans your nginx endpoints from the outside, confirms that the full chain, the allowed protocols and the active ciphers match your intent, and warns before the certificate expires.

Frequently asked questions

Should I use fullchain.pem or cert.pem in ssl_certificate?

Always fullchain.pem. cert.pem contains only your own certificate without intermediates, which makes non-browser clients fail. fullchain.pem contains the leaf plus the required intermediates.

Which TLS protocols should nginx allow?

Only TLSv1.2 and TLSv1.3. TLS 1.0 and 1.1 are retired and rejected by modern clients, so they should be disabled entirely.

Why don't I set ssl_ciphers for TLS 1.3?

In TLS 1.3 the cipher suites are fixed and strong, and the client chooses. ssl_ciphers in nginx only affects TLS 1.2. So you only configure ciphers for 1.2.

What does OCSP stapling do?

The server fetches a fresh proof of validity (OCSP response) for its certificate itself and attaches it during the handshake, so the client does not have to contact the CA. It is faster and more privacy-friendly.

How do I apply changes without downtime?

Run nginx -t to validate, then nginx -s reload. The reload starts new workers with the new configuration while old connections finish — no connections are dropped.