Tengine-3.2.0-rc3
Pre-releaseChinese changelog: CHANGES.cn
This is the third release candidate of Tengine 3.2.0, the first release since 3.1.0 (October 2023). Relative to RC2 the server code carries one health-check fix and a refreshed xquic baseline; the packaging side fixes the deb file names so sha256sum -c now works straight out of the box. Please do not use it in production yet.
What to test
We are especially interested in reports about the distribution packages and container images, HTTP/3 over xquic on lossy networks, upstream health checks with check_keepalive_requests, and the load-balancing changes. Please open an issue with the output of tengine -V, the relevant configuration, and the platform.
New in RC3
- Health-check keepalive actually reuses the connection now. The discard handler never tracked the response body boundary, so
recv_body_pendingstayed set and every check closed and reconnected whenever the body did not arrive together with the header — keepalive was effectively off. The handler now drains the body according to its framing (Content-Length and chunked), and an illegal chunk or a surplus byte after the body closes the connection instead of reusing it @lianglli - The deb file names no longer need renaming before verification.
collect-release.shreplaces the~in deb file names with.at release time, which is the same substitution GitHub applies to asset names, soSHA256SUMSand the downloaded file finally agree. TheVersion:field inside the package keeps its~<codename>, soaptordering is unchanged @lianglli - xquic integration baseline moved to v1.9.5.
modules/ngx_http_xquic_module/README.mdnow documents which xquic version each Tengine release was verified against: 3.2.0 and master are API compatible with the v1.8.0 to v1.9.5 generation, while 3.1.0 needs the pre-v1.8.0 API. The packages, the container images and CI all build against v1.9.5 @Yanmei-Liu - The legacy-install warning covers custom prefixes. It previously fired only when both
--prefixand--sbin-pathwere left at their defaults, so anyone upgrading with a custom prefix got no hint thatmake installwould leave the oldnginx-named tree in place and the new binary would look for atengine.confthat does not exist @lianglli
Security
- fixed CVE-2026-49975, HPACK/QPACK header decompression bomb in HTTP/1, HTTP/2 and HTTP/3 @lianglli
- fixed CVE-2026-9256, heap buffer overflow with overlapping captures in ngx_http_rewrite_module @lianglli
- fixed CVE-2026-42945, escaping issue and possible buffer overrun in ngx_http_rewrite_module @drawing
- fixed CVE-2026-42946, buffer overread when parsing a split status line in ngx_http_scgi_module and ngx_http_uwsgi_module @drawing
- fixed CVE-2026-42934, buffer overread in recode_from_utf8() of ngx_http_charset_module @drawing
- fixed CVE-2026-40701, use-after-free in the OCSP resolver of ngx_http_ssl_module @drawing
- fixed CVE-2026-1642, a premature plain text response from an SSL backend was parsed before the handshake @drawing
- fixed an out-of-bounds read in mod_dubbo @orbisai0security
Highlights
- core updated to nginx 1.31.3 @lianglli
- HTTP/3 connection management and multiplexing, for lower latency and higher resilience to packet loss on unstable networks, with BBR as the default congestion control [xquic] @lianglli @lurker-Chen
- distribution packages (rpm, deb and apk) and multi-arch container images, all built with the full feature set — Tongsuo, xquic and Lua @lianglli
- all packages are signed: RPMs carry an in-band GPG signature, and both checksum files are signed detached. Key fingerprint:
8F5B 4D9F CA8E 2BFF 3E5E E958 25F0 7CF8 36E3 EC6A@lianglli - new module
ngx_zstdfor Zstandard response compression and serving pre-compressed static files @lianglli - new module
ngx_http_upstream_iwrr_module, a weighted round-robin with O(1) time and O(n) memory @jizhuozhi - request and upstream timing statistics variables, e.g.
$request_recv_time,$response_send_time,$server_rtand$upstream_first_pkg_time@lianglli - dynamically configure failover to a backup upstream or a redirect by response status code [tengine-ingress] @lianglli
ngx_http_lua_moduleupdated to 0.10.29, which adds PCRE2 support @liangllingx_http_upstream_rbtree_lookup()is now a public API, so third-party modules can look up an upstream by name @lhanjian
50 changes in total: 18 features, 17 bugfixes, 8 security fixes and 7 changes — the complete list is in CHANGES.te.
Which image tags to use
Use the version-pinned tags (3.2.0-rc3, 3.2.0-rc3-alpine, and their -perl variants). Tags matching *-dev-* are throwaway builds from manual CI runs used to verify the publishing path; they are unannounced and may be removed at any time. A pre-release does not move latest, alpine, 3.2 or 3, so a plain docker pull ghcr.io/alibaba/tengine still gives you 3.1.0.
Known limitations in RC3
ngx_http_tunnel_moduleis optional and off by default — it conflicts withngx_http_proxy_connect_moduleon the CONNECT method.least_timeandstickyare disabled in the HTTP/2 rework and are being revisited.- The package file names carry no
rc3marker; artifacts here are named3.2.0-<timestamp>. rpm'sVersion:and Alpine'spkgverdo not allow-, and dpkg would rank3.2.0-rc3above the final3.2.0. - Packages are built for x86_64 and aarch64 only.
- The
tengine-module-perl-dbgsympackages are listed inSHA256SUMSrather than inSHA256SUMS.debug, unlike every other debug package. Both files are signed and the checksums are correct, so this only affects which list you find them in.
Every artifact here is built with the full feature set: Tongsuo (NTLS / TLCP, Chinese cryptography), xquic (QUIC and HTTP/3) and the LuaJIT scripting stack, all from the versions pinned in packages/build/deps.env. Tongsuo is linked statically, so these builds do not follow the system OpenSSL.
The server installs as /usr/sbin/tengine, configured through /etc/tengine/tengine.conf, and can coexist with a distro nginx.
Install
RPM (RHEL / Rocky / Alma / Anolis / openEuler / SLES) — replace el9 with your platform's tag (el7, el8, el10, an8, an23, oe2203, oe2403, sles15, sles16):
rpm --import https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/tengine-packaging-key.asc
dnf install https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/tengine-3.2.0-20260811140937.el9.x86_64.rpmDEB (Debian / Ubuntu) — replace bookworm with your codename (bullseye, trixie, jammy, noble, resolute):
curl -fLO https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/tengine_3.2.0-20260811140937.bookworm_amd64.deb
apt install ./tengine_3.2.0-20260811140937.bookworm_amd64.debAlpine — replace alpine324 with your release (alpine321, alpine322, alpine323):
curl -fLo /etc/apk/keys/tengine-packaging.rsa.pub \
https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/tengine-packaging.rsa.pub
curl -fLO https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/tengine-3.2.0_p20260811140937-r0.alpine324.x86_64.apk
apk add ./tengine-3.2.0_p20260811140937-r0.alpine324.x86_64.apkDropping the public key first is what lets apk add work without --allow-untrusted.
Container images
docker pull ghcr.io/alibaba/tengine:3.2.0-rc3
docker pull ghcr.io/alibaba/tengine:3.2.0-rc3-alpineBoth are multi-arch (amd64 + arm64). A -perl variant of each adds ngx_http_perl_module (3.2.0-rc3-perl, 3.2.0-rc3-alpine-perl); the module is already loaded in the shipped configuration, so perl, perl_set and perl_modules work out of the box. Base-suffixed variants (3.2.0-rc3-trixie, 3.2.0-rc3-alpine3.24, and their -perl forms) are published as well.
Perl module
In the packages, ngx_http_perl_module is a separate subpackage (tengine-module-perl, tengine-mod-perl on Alpine) so the base install does not pull in libperl. It is dynamic and not loaded by default; add
load_module /usr/lib/tengine/modules/ngx_http_perl_module.so;to the main context (/usr/lib64 on the RHEL family).
Debug symbols
The -debuginfo / -debugsource (rpm), -dbgsym (deb) and -dbg (apk) packages are listed alongside the runtime packages and are only needed to read a core dump or attach a debugger. They have their own checksum file, SHA256SUMS.debug.
Verify
Checksums — --ignore-missing restricts the check to the files you actually downloaded:
curl -fLO https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMSOn Alpine the busybox sha256sum has no such flag — use grep <filename> SHA256SUMS | sha256sum -c there, or install coreutils.
Unlike RC2, the deb file names need no renaming: SHA256SUMS now records the same names the assets are published under.
The checksum file itself is signed, which is what covers the deb packages — they carry no in-band signature, since Debian's trust model signs a repository rather than individual files:
curl -fLO https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/SHA256SUMS.asc
curl -fLO https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/tengine-packaging-key.asc
gpg --import tengine-packaging-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMSThe imported key must show the fingerprint 8F5B4D9FCA8E2BFF3E5EE95825F07CF836E3EC6A.
The rpm packages are signed in-band with the same key, so once it is imported into rpm they verify individually:
rpm --import https://github.com/alibaba/tengine/releases/download/3.2.0-rc3/tengine-packaging-key.asc
rpm --checksig tengine-3.2.0-20260811140937.el9.x86_64.rpmWhat's Changed
- Docs: record the xquic session ticket key warning in the changelogs by @lianglli in #2085
- Packaging: rename the tilde out of the deb file names at release time by @lianglli in #2086
- Bugfix: drain leftover health-check body so keepalive reuse works by @lianglli in #2088
- Build: warn about a legacy nginx-named install under any prefix by @lianglli in #2090
- XQUIC: update integration baseline to v1.9.5 by @Yanmei-Liu in #2091
- Docs: record the xquic v1.9.5 baseline in the changelogs by @lianglli in #2092
Full Changelog: 3.2.0-rc2...3.2.0-rc3