yum upgrades for production use, this is the repository for you.
Active subscription is required.
Technical Briefing: RFC 8879 Certificate Compression in NGINX
Problem Statement
The TLS 1.3 certificate chain dominates the server’s first flight and competes with the initial congestion window and QUIC’s 3x amplification limit. RFC 8879 certificate compression shrinks that chain on every fresh handshake — a tested production chain dropped from 4735 to 3750 bytes (20.8% saving).
NGINX supports this via a single directive:
ssl_certificate_compression on;
It is valid in http, server, and stream blocks (not location), defaults to off, and requires NGINX 1.29.1 or newer (released July 2025).
Two Packaging Problems Block Adoption
- Most distribution NGINX builds are too old to have the directive.
- Distribution OpenSSL builds are compiled without the compression algorithms browsers request. This failure is silent —
nginx -tpasses while Chrome still receives an uncompressed certificate.
RFC 8879 defines three algorithms, and browsers don’t converge:
| Browser | Offered algorithm(s) |
|---|---|
| Chrome | brotli only |
| Safari | zlib only |
| Firefox | all three |
Whether OpenSSL supports brotli or zstd is fixed at compile time via enable-brotli and enable-zstd, and no distribution enables them. Distro OpenSSL therefore supports zlib only — serving Safari but not Chrome.
Being on OpenSSL 3.5 is not sufficient. Rocky Linux 10’s system OpenSSL 3.5.1 links only libz.so.1, while the GetPageSpeed build links libz, libbrotlienc, libbrotlidec, and libzstd.
Client-side check: openssl s_client -trace shows the compress_certificate extension length — length=3 means one algorithm (distro), length=7 means three (GetPageSpeed’s openssl35).
Hard Conflict with OCSP Stapling
ssl_certificate_compression is incompatible with ssl_stapling. NGINX compresses the chain once at configuration time and caches the blob, but OCSP stapling injects a per-response staple into the Certificate message, invalidating the precomputed blob. Upstream rejects the combination outright — NGINX will not start.
You must pick one. For most sites OCSP stapling is already doing nothing, so delete ssl_stapling (and ssl_stapling_verify) and enable compression. Check with:
openssl x509 -noout -ocsp_uri
Empty output means stapling has nothing to staple. If your CA still runs OCSP and you rely on stapling, keep stapling, since revocation checking is a security control.
Verification
openssl35 s_client -trace should show CompressedCertificate, Length=... instead of Certificate, Length=.... Add -no_rx_cert_comp for the uncompressed baseline.
A stock s_client offers every algorithm and shows only the winner, so it can’t confirm zstd works or that Chrome specifically is served. Restrict the offer to one algorithm (via SSL_CTX_set1_cert_comp_preference) for per-algorithm testing.
Brotli wins on both test and production measurements — convenient since Chrome speaks only brotli; when a client offers all three, the servers pick brotli.
Honest Limits
- Compression applies only to full handshakes; resumed sessions skip it, arguing for a healthy
ssl_session_cache. - It does nothing for TLS 1.2 clients, since the extension doesn’t exist there.
Installation
RHEL/clones:
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install nginx
Upgrade in place with:
sudo dnf upgrade nginx openssl35-libs
Debian/Ubuntu: set up the APT repo, then:
sudo apt-get update
sudo apt-get install nginx
Both pull in openssl35-libs, an ABI-isolated OpenSSL 3.5 LTS build. Confirm with:
nginx -V 2>&1 | grep "built with"
which should report built with OpenSSL 3.5.8+gps.
Packages ship both halves (NGINX new enough plus OpenSSL with all three algorithms) on RHEL 7 through 10 and clones, Amazon Linux, and Ubuntu 20.04/22.04/24.04 LTS plus Debian 12 and 13. For RHEL 7, zstd is packaged by GetPageSpeed itself since libzstd lives only in EPEL there.
Because the algorithms are a property of the OpenSSL build, upgrading openssl35-libs unlocks them for an existing NGINX binary with no rebuild — but it needs systemctl restart nginx, not a reload, since workers fork from the master which keeps the old library mapped. A reload leaves the old algorithm set with no error message.
Troubleshooting
| Symptom | Cause |
|---|---|
"ssl_stapling" is incompatible with "ssl_certificate_compression" |
Remove one of the two |
unknown directive "ssl_certificate_compression" |
NGINX predates 1.29.1 |
Config accepted but client still gets Certificate |
Client isn’t TLS 1.3; client offers only algorithms your OpenSSL lacks (the Chrome-on-distro case); or a CDN/load balancer in front is terminating TLS |
"ssl_certificate_compression" is not supported on this platform, ignored |
NGINX is linked against a TLS library with no compression support |
Additional Notes
- The configuration passes gixy, the NGINX static analyser, with no findings.
- The broader OpenSSL 3.5 stack also covers Encrypted Client Hello and post-quantum key exchange, and an SSL test audits a live host across all of it.
Read the full article: NGINX Certificate Compression: RFC 8879 for Every Browser
