đź“… Updated: August 25, 2026 (Originally published: April 26, 2026)
If you’ve tried to build aws-lc NGINX in the last two years and gave up because of header collisions, missing OCSP stapling, or general handwaving about “BoringSSL forks aren’t ready” – the situation has changed. NGINX upstream landed aws-lc support in 1.29.2, OCSP stapling stopped being a real production requirement, and the only remaining obstacle to a packaged NGINX-MOD-AWS-LC is one we can name precisely. Here’s the honest current state of TLS for NGINX on Enterprise Linux in 2026.
Updated 25 August 2026: we made the move. NGINX-MOD and EDGE now link against OpenSSL 3.5 LTS instead of quictls – shipping on the testing channel today, stable to follow. The reasoning below still stands, and it is why we waited. See the update immediately following.
Update, 25 August 2026: NGINX-MOD is on OpenSSL 3.5 LTS
This article closed by calling plain OpenSSL “the direction of travel, not a dated promise”. That travel is done.
NGINX-MOD and EDGE now link against openssl35, our ABI-isolated build of OpenSSL 3.5 LTS, with a CVE stream tracked to April 2030. EDGE has shipped it since 25 August 2026; for NGINX-MOD it is on the testing channel while it earns its way to stable, so dnf install nginx-mod from the default repo still gives you the quictls build for now. Everything the piece below says about quictls remains true, and it is exactly why we stayed as long as we did: an archived 3.1.7 line we were backporting ourselves was a better bet than a fork with no release process. It was never a good permanent answer.
What the move bought, beyond getting off the backport treadmill:
- Native OpenSSL QUIC API with real 0-RTT, instead of the BoringSSL-style API quictls carried.
- Post-quantum key exchange, X25519MLKEM768.
- Encrypted Client Hello (RFC 9849). We backported the DEfO implementation onto 3.5 LTS rather than shipping a brand new OpenSSL major to get it, which would have thrown away the LTS commitment that made 3.5 worth picking.
ssl_ech_file,$ssl_ech_statusand$ssl_ech_outer_server_namework today, with key rotation packaged innginx-mod-echandedge-ech. There is a live demo at ech-test.getpagespeed.com.
The honest cost we named below – that swapping the TLS backend is a real port plus a rebuild of every TLS-touching dynamic module – was accurate. It is what the work consisted of.
None of this changes the aws-lc analysis. aws-lc remains a fine standalone library on Enterprise Linux, NGINX upstream still supports it, and whether we ship a packaged NGINX-MOD-AWS-LC variant still comes down to demand.
The rest of this article is preserved as published on 4 August 2026, apart from the “what to install today” section, which now reflects the change above.
Why we packaged aws-lc on EL
We ship aws-lc-libs and aws-lc-devel in the GetPageSpeed extras repo so users can run aws-lc on Enterprise Linux without compiling from source. The packages install isolated under /usr/lib64/aws-lc with their own SONAMEs (libcrypto-aws-lc.so.0, libssl-aws-lc.so.0), so they coexist with system OpenSSL without conflict. Builds cover EL 6/7/8/9/10, Amazon Linux 2/2023, Fedora, and openSUSE.
aws-lc is AWS’s general-purpose crypto library, derived from BoringSSL and OpenSSL. It’s the TLS stack behind a chunk of AWS infrastructure and, increasingly, third-party servers. The natural follow-up question every subscriber eventually asks is whether we’ll ship an aws-lc NGINX variant for HTTP/3. This post answers that directly. However, the path through the answer matters: most published commentary on aws-lc NGINX is two years out of date and points at problems that have since been solved.
Will GetPageSpeed ship NGINX-MOD linked against aws-lc?
Short answer: not today, but for very different reasons than you’d guess. The objections that historically blocked this combination have closed or are closing. What’s left is a maintenance and demand calculation, not a technical wall.
The big news: NGINX upstream supports aws-lc as of 1.29.2
For years, the answer to “can I build NGINX with aws-lc?” was: “only with downstream patches.” That changed in December 2025.
NGINX upstream issue #185 was closed by pluknet with a one-liner: “Closing this as AWS-LC is now supported starting with nginx 1.29.2.” Our NGINX-MOD package already builds on top of NGINX 1.30.0, so the upstream aws-lc NGINX support is sitting in the source tree we ship – it just isn’t wired up at build time.
The compile-time header collision errors people remember from 2024 (e.g. aws-lc issue #1827, where enum ssl_encryption_level_t and struct ssl_quic_method_st were redefined between aws-lc and NGINX’s old QUIC compatibility shim) are resolved upstream. Therefore, if you tried this two years ago and gave up, the situation has changed.
If you want to verify yourself today, the recipe is roughly:
# Build aws-lc with shared libraries enabled
cmake -GNinja -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/opt/aws-lc ..
ninja install
# Configure NGINX 1.29.2+ against the installed aws-lc
./configure --with-cc-opt="-I/opt/aws-lc/include"
--with-ld-opt="-L/opt/aws-lc/lib64 -Wl,-rpath,/opt/aws-lc/lib64"
--with-http_v3_module
make
The compatibility shim no longer fights aws-lc’s native QUIC headers, and the resulting binary speaks HTTP/3 against modern clients.
The other historical objection (OCSP stapling) is also fading
The standard line for a decade was: “BoringSSL and aws-lc don’t implement server-side OCSP stapling, so NGINX behind it can’t ssl_stapling on;” – see Apache Traffic Server issue #3748 from 2018. Still technically true.
However, OCSP itself is being decommissioned across the public web:
- The CA/Browser Forum made OCSP optional for publicly trusted CAs as of March 15, 2024 (ballot SC-063). CRLs are the only required revocation channel now.
- Let’s Encrypt completely shut down its OCSP responder on August 6, 2025. Must-Staple support was removed in January 2025.
- Chrome never performed live OCSP checks. Firefox is transitioning away.
For the majority of subscribers using Let’s Encrypt certificates, ssl_stapling on; has been a no-op since August 2025. There’s nothing to staple.
There’s still a long tail of paid CAs publishing OCSP responses, plus some compliance regimes that mandate stapling. Those users would notice if NGINX couldn’t staple. Even so, this is no longer the universal blocker for aws-lc NGINX adoption that it used to be. For most production sites, removing ssl_stapling on; from your config and switching to the CRL-based revocation that browsers actually consult costs nothing.
What aws-lc does well in 2026
To be fair, the library is solid:
- TLS 1.3 including 0-RTT/early data. HAProxy ships aws-lc 1.65.1 in production with this enabled.
- BoringSSL-style QUIC API. Works for HAProxy today and for NGINX 1.29.2+.
- FIPS mode (separate aws-lc-fips track upstream).
- Strong throughput under contention. The HAProxy “State of SSL Stacks” survey (May 2025) measured 183k connections/sec for aws-lc, notably better than OpenSSL 3.x in multi-threaded benchmarks.
Additionally, the AWS team is responsive on integration issues. They run aws-lc as their own production crypto library at AWS’s scale, so the underlying code gets serious adversarial use every day. Stability concerns about aws-lc are usually really concerns about API stability (covered below), not about the library crashing or producing wrong output.
What aws-lc drops by design
aws-lc inherits BoringSSL’s removal of legacy ciphers, including DHE and CCM cipher suites. For server administrators, this matters only if you must serve clients without ECDHE – practically OpenSSL versions before 1.0.0 (RHEL/CentOS 5, Windows XP, Java 6 era).
EL6 ships OpenSSL 1.0.1 and EL7 ships OpenSSL 1.0.2 (after 7.4). Both have ECDHE and negotiate ECDHE-RSA-AES256-GCM-SHA384 against modern NGINX configurations without issue. Therefore, if your audience is anything more recent than RHEL 5, dropping DHE costs you nothing. Worth checking your access logs for the $ssl_cipher field if you’re unsure – in practice, almost every modern client picks an ECDHE suite first.
For a quick audit, log the cipher in use and grep:
log_format ssl_audit '$remote_addr "$ssl_protocol/$ssl_cipher" "$request"';
access_log /var/log/nginx/ssl-audit.log ssl_audit;
sudo awk -F'"' '{print $2}' /var/log/nginx/ssl-audit.log | sort | uniq -c | sort -rn | head
If you see no DHE-* entries in the top results, switching to aws-lc would not change anything client-visible on cipher negotiation.
So why aren’t we shipping NGINX-MOD-AWS-LC today?
The honest current bottleneck for aws-lc NGINX packaging isn’t a technical principle – it’s maintenance overhead:
Module rebuild matrix. aws-lc is API-compatible with OpenSSL but explicitly NOT ABI-compatible. Every TLS-touching dynamic module we ship – lua-nginx-module, ModSecurity, JWT validators, OpenTelemetry, and others – needs rebuilding against aws-lc headers, with per-module source patches. The sk_X509_NAME_find argument-count difference between aws-lc and OpenSSL, documented in our aws-lc-rpm README, is one example among several. Each module’s patch needs maintaining for as long as we ship it.
API churn. aws-lc inherits BoringSSL’s “no stable API” stance. Module patches need ongoing maintenance across aws-lc releases. There’s no STABILITY.md or semver guarantee published. For a packaging shop maintaining out-of-tree patches across many distros, this is a real ongoing cost. Moreover, when aws-lc rotates a function signature, every consumer rebuilds and re-tests – including ours.
Customer-demand check. Subscribers haven’t been asking for aws-lc-backed NGINX specifically. quictls plus HTTP/3 covers production needs today. We’re not going to invest in maintaining a parallel module-rebuild matrix ahead of demand.
Translation: this is now a commercial decision (build vs. wait for demand), not a technical one. The technical path for aws-lc NGINX is open.
What about quictls itself?
A reasonable follow-up: NGINX-MOD currently links against quictls 3.1.7, which is OpenSSL 3.1.x plus the QUIC API patches. The original quictls/openssl repository was archived on April 10, 2025 – it only ever tracked through OpenSSL 3.1.7. There’s a successor project at quictls/quictls (a full fork from OpenSSL 3.3, jointly maintained by Akamai and Microsoft, with plans to land at the Apache Software Foundation).
As of August 2026 the successor is still not a production option, and the gap has not narrowed since we first published this in April:
- Still zero tagged releases. The only tags in the repository predate the fork’s own versioning. In issue #318 the project lead wrote “We haven’t thought about a release process or policies yet” back in October 2025, and ten months later that is still where things stand. No release line means no version to package, track, or scan against.
- The open reports we flagged in April – the
ssl3_dispatch_alertinfinite loop (#338), ARM assembler build failures (#319), missing packager documentation (#318) – are all still open, most without a single comment since they were filed. - A new memory-safety report landed in July 2026 on exactly the code path a packager would be adopting: issue #352, an out-of-bounds read in QUIC key export.
The repository is active, but the activity is static-analysis cleanup and test fixes – hygiene, not release engineering. So we stay on the archived 3.1.7 line: it’s a known quantity and its QUIC API behaves correctly under production load. Staying does raise an obvious objection, though, and it deserves a straight answer.
An archived repo on an EOL branch – so who patches it?
We do. OpenSSL 3.1 went end-of-life in March 2025, and the archived quictls repository will never take another commit. Upstream’s CHANGES.md for the 3.1 branch still reads “Changes between 3.1.8 and 3.1.9 – none yet”, and always will. Security fixes for this base are ours to carry now. In August 2026 we shipped the first batch: quictls-3.1.7-7, carrying three backports.
Which three is the interesting part. We audited every OpenSSL security advisory published since 3.1.7 came out in September 2024. Roughly 29 issues technically reach the 3.1 code base. Almost none of them are reachable in an NGINX build:
- Both High-severity CVEs in that window live in CMS/PKCS#7 – message-signing code that NGINX never calls. These are exactly the ones vulnerability scanners scream about, and they are unreachable in practice.
- Most of the rest sit in PKCS#12, CMP, RFC 3161 timestamping, the
opensslcommand-line tool, the built-in HTTP client, or OpenSSL’s native QUIC transport stack – which quictls does not even have. - We build with
no-ec2m no-sm2 no-sm4, which structurally removes several more: an SM2 CVE cannot apply to a library with no SM2 in it.
The one that actually mattered has no CVE
The genuinely dangerous issue in that audit is nicknamed “HollowByte”, and you will not find it in any CVE database. A TLS peer declares a large handshake message and then simply never sends the body; OpenSSL pre-grew its receive buffer to the full declared size up front. The attack is pre-authentication, remotely triggerable, and was demonstrated against NGINX: Okta’s red team OOM-killed a server with 1 GB of RAM at 547 MB of frozen, fragmented allocations, and locked up a quarter of the RAM on a 16 GB box. Because glibc never returns the fragmented arenas to the OS, the memory stays gone even after the attacker disconnects.
OpenSSL classified it as “bug or hardening” rather than a vulnerability. No CVE, no security advisory. The fix went quietly into 3.0.21, 3.4.6, 3.5.7, 3.6.3 and 4.0.1; the 3.1 branch never got it, because 3.1 was already dead. The details are in the oss-security disclosure and SecurityWeek’s write-up.
Sit with the consequence for a second: no vulnerability scanner will ever flag this issue – not on our packages, not on anyone’s. The scanner-loud CVEs in our audit were the irrelevant ones, and the one that can actually take a server down is invisible to every scanner on the market. A clean vulnerability scan is not the same thing as not being exposed.
What we shipped
quictls-3.1.7-7 carries:
- The HollowByte fix, adapted for our tree from the upstream openssl-3.0 backport (openssl/openssl#30794). The buffer now grows incrementally as handshake data actually arrives.
- CVE-2024-13176, an ECDSA nonce timing side-channel that runs on every handshake with an EC certificate. Applied verbatim from the openssl-3.1 branch.
- CVE-2024-9143, an out-of-bounds write in
BN_GF2m_poly2arr. Also verbatim from openssl-3.1. Belt and braces in our case, sinceno-ec2malready removes the vector.
Both CVE fixes were released upstream in OpenSSL 3.1.8 – a version quictls never tagged. A pleasant side effect of sitting at 3.1.7: CVE-2025-9232 does not apply to us at all, because that bug was introduced in 3.1.8.
To be precise about the claim: we are not “maintaining OpenSSL 3.1”. We carry a small, audited set of backports for the code paths an NGINX build actually executes, and we leave the rest untouched because it is unreachable in our packages. That is a much smaller promise than “we patch everything”, and it is one we can keep.
One more payoff, this time from the packaging design: NGINX links quictls’s libssl/libcrypto dynamically from a private libdir. The fixes shipped in quictls-libs with the ABI unchanged, so subscribers picked them up with dnf update quictls-libs plus an NGINX restart. No NGINX rebuild, no module rebuilds.
Where the field is heading
The real exit from the backport treadmill is not quictls/quictls – it’s plain OpenSSL. NGINX now recommends OpenSSL 3.5.1 or later for QUIC and lists quictls as merely an alternative. OpenSSL 3.5 is an LTS release, supported until April 2030, and its native QUIC API supports 0-RTT.
The honest cost of that move: OpenSSL’s QUIC API is incompatible with the BoringSSL-style API that quictls, aws-lc, ngtcp2 and quiche share. Swapping the TLS backend under NGINX-MOD is a real port, plus a rebuild of every TLS-touching dynamic module against the new headers. So that is the direction of travel, not a dated promise. We’ll make the move when it’s ready to carry production traffic, and until then the backport arrangement above keeps 3.1.7 safe to run.
aws-lc, meanwhile, continues to gain integration support: HAProxy 2.9+, NGINX 1.29.2+, more on the way.
What’s clearer is that aws-lc NGINX is no longer the “doesn’t work” combination it was. It works. Whether it makes sense to ship as a packaged variant is a different question, and the answer depends on how many subscribers need it.
What to install today
For HTTP/3 NGINX on Enterprise Linux: install NGINX-MOD from extras. It runs in production and supports HTTP/3 today. The stable channel is still quictls-backed; the OpenSSL 3.5 LTS build – with 0-RTT, post-quantum key exchange and Encrypted Client Hello – is on the testing channel now and moves to stable once it has soaked.
For aws-lc as a standalone library on EL: dnf install aws-lc-libs aws-lc-devel from extras.getpagespeed.com. Use it for curl, AWS SDK consumers, your own custom NGINX builds against aws-lc, or anything else that wants BoringSSL-API compatibility without disturbing system OpenSSL.
For a hardened TLS configuration in either case, see our NGINX TLS 1.3 hardening guide.
If you’re a subscriber who actively wants NGINX-MOD-AWS-LC as a shipped variant – tell us. That demand signal is what tips the build-vs-wait calculus.
TLS drift is silent. A working cipher list today, an A- grade tomorrow. GetPageSpeed Amplify runs scheduled gixy scans across every host and ties findings to live NGINX runtime metrics. Drop-in compatible with the deprecated nginx-amplify-agent (EOL January 2026).

