The client and server share no TLS version or cipher. Usually an ancient server, an ancient client, or a cipher list that excludes everything modern browsers need.
TLS 1.0/1.2-only appliances, NULL/3DES-only cipher lists, or RC4-era configs rejected by modern clients. Test: openssl s_client -connect host:443 -tls1_3 then -tls1_2.
A hardening edit that removed ECDHE or AES-GCM suites leaves nothing modern clients accept. nginx -T | grep ssl_ciphers shows the active list.
Old Java 6/7, Python <2.7.9, or embedded stacks can't do TLS 1.2+. Server sees an unsupported ClientHello and errors.
for p in tls1 tls1_1 tls1_2 tls1_3; do echo -n "$p: "; openssl s_client -connect host:443 -$p </dev/null 2>/dev/null | grep -c 'Protocol' ; done
# 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;
sudo nginx -t && sudo systemctl reload nginx
# upgrade the Java/Python stack; if truly stuck, serve a separate TLS-1.0 endpoint for that device only, isolated and monitored
Mozilla's SSL Configuration Generator (ssl-config.mozilla.org) gives maintained 'modern/intermediate/old' profiles — don't hand-roll cipher lists. Scan with testssl.sh or SSL Labs to see the negotiated suite matrix from an external view.
Client TLS capability varies by OS/browser/runtime. Modern browsers demand TLS 1.2+/strong ciphers; older embedded clients may need the legacy suites your hardened config removed. Pick an 'intermediate' profile to cover both.
You shouldn't: NULL/RC4/3DES suites have real vulnerabilities and modern clients flag them. Use the intermediate profile — it keeps compatibility without the weak suites.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.