← Knowledge base

Verify hybrid TLS in nginx

nginx negotiates TLS through the SSL library linked to its deployed binary. Your shell's OpenSSL executable can be different. Start by identifying where TLS terminates, then test that endpoint and use nginx's selected-group telemetry when you need evidence for an origin connection.

Before you start

You need read access to the deployment's version information, a hostname you operate, and the OpenSSL check prerequisites on the checking machine. Changing nginx requires the usual deployment privileges and a staging or canary endpoint. A supported nginx package linked to a PQ-capable SSL library is required; an nginx version number alone cannot establish that combination.

Validation scope: commands and variables were reviewed against official nginx documentation. Configuration snippets are examples to adapt and test, not a claim that every packaged nginx build supports them.

1. Find the deployed binary and TLS boundary

command -v nginx
nginx -V 2>&1

Compare this binary with the executable in your service manager, container image, or ingress deployment. If they differ, run -V on the deployed executable. Keep the build/library information in your private inventory. The nginx command reference explains -V and configuration testing.

Read the relevant configuration in your normal configuration repository: locate the listener, certificate hostname, inherited ssl_ecdh_curve, and any ssl_conf_command settings. A full configuration dump can contain credentials; do not publish it in a support issue.

2. Test the right endpoint

Run the verified hybrid handshake against the public hostname. If a CDN or load balancer terminates TLS, that checks the intermediary. For a separately authorized origin check, connect to the origin while preserving its correct SNI and certificate name:

# Example reserved address: substitute your authorized origin IP and hostname.
openssl s_client -connect 192.0.2.10:443 -servername origin.example.com \
  -verify_hostname origin.example.com -verify_return_error \
  -tls1_3 -groups X25519MLKEM768 -brief -no_ign_eof </dev/null

A firewall-restricted origin should remain restricted. Run the check from an allowed network; for a private CA use its approved trust bundle. A successful direct test shows origin capability from that client, while actual CDN-to-origin negotiation still needs origin telemetry.

3. Observe the selected group

$ssl_curve is the negotiated group; $ssl_curves lists client offers. nginx documents $ssl_curve from 1.21.5 with OpenSSL 3.0 or newer, and it may return a hexadecimal identifier for an unfamiliar group. Those minimums enable the variable, not ML-KEM support. See the SSL variables reference.

If your existing private telemetry lacks the group, the following is an optional configuration change for a controlled test. Limit its duration and access, send a known request through the intended route, and remove it after collecting evidence.

# Optional temporary diagnostic format in the http {} context.
# It intentionally omits IPs, URLs, cookies, and headers.
log_format pqc_check '$time_iso8601 $ssl_protocol $ssl_curve';

# In a controlled test server/location that actually receives the request:
access_log /var/log/nginx/pqc-check.log pqc_check;

Illustrative log line:

2026-09-25T12:00:00+00:00 TLSv1.3 X25519MLKEM768

That records hybrid key exchange on the connection nginx received. An empty field remains unknown; X25519 is classical. A cached CDN response might never reach your origin. Use a controlled uncached request and correlate its timing without collecting unnecessary visitor information.

4. Stage supported changes

  1. Save the known-working configuration and package/image version, and define the rollback before changing the listener.
  2. If the deployed SSL library lacks the group, use a vendor-supported nginx/library build. Installing a different command-line OpenSSL is insufficient.
  3. If an old explicit group list is blocking newer defaults, review whether your deployment can use the library's defaults. Preserve required certificate/client compatibility and policy.
# In the existing TLS server block, after reviewing inherited policy.
# Uses the linked library's supported defaults.
ssl_ecdh_curve auto;

nginx documents this directive; auto does not guarantee a hybrid result. Avoid conflicting group settings at inherited levels. If you require an explicit list, use your linked library's supported group configuration and retain needed classical/certificate curves.

Run nginx -t with the exact deployed binary and configuration arguments. Only after it succeeds, reload using your service manager or deployment platform. nginx's reload procedure validates the new configuration before replacing workers.

5. Retest, troubleshoot, and roll back

Repeat hybrid and classical client checks, then normal application requests through each CDN/load balancer path. Record certificate validation, selected group, latency, and errors. Test fresh connections so an older pooled session does not obscure the change.

Documentation reviewed 25 September 2026. No nginx package matrix or production configuration is certified by this guide.