Hi, HAProxy 3.2-dev11 was released on 2025/04/18. It added 107 new commits after version 3.2-dev10.
I'm particularly satisfied with the fact that the last batch of non- trivial updates was merged in time. Of course there's still some work to be done before the release, but it will mostly consist in small adjustments, bug fixes, cleanups and optimizations, nothing putting pressure on those who have to switch their focus to the forthcoming HaproxyConf (3-5 June) to prepare their slides and their talk. This will also let the code stabilize and should offer us a really good 3.2. What's in this version ? Hmmm again quite a bunch of good stuff.: - the ACME patches were merged, bringing most of the long awaited features. It goes as far as implementing the "acme renew" command on the CLI, which can entirely handle the sequencing of a renewal. For now it focused on implementing the required infrastructure inside haproxy, so at the moment it only implements the HTTP-01 challenge that was needed to validate the whole chain, but the rest is coming. It is designed to support interacting with external agents for more complicated challenges (e.g. DNS-01). For this one, it will communicate with the dataplane API over the CLI to offload the complex operations. The communication will happen over a dedicated event ring ("dpapi") which was already created. The renewal status (success or failure) is emitted to the logs. From this point, both the core team and the dpapi team will be able to make progress in parallel as all the building blocks are there. Those interested should have a look at section 3.13 in the config manual for more info and examples. - the master CLI now supports a bidirectional mode to enter workers. While "@1" enters the worker for a single command (and possibly passes one command at a time when in front of a pipeline), the new "@@1" passes the whole line and payload at once and stays in the worker in interactive mode until it exits or until the command completes. This will typically be used by the dataplane API to subscribe to notifications from the "dpapi" event ring. In practice one will just have to send "@@1 show events dpapi -w -0" and watch what comes from it. - HTTP/3 now delivers absolute URIs internally (like HTTP/2), not relative ones. The difference is only visible on rules that extract the "url" sample, which will now begin with the scheme since it's what the client sends. The two had diverged because this point was addressed in H2 while H3 was being developed about 2 years ago, it was about time to resync. - "bind" and "server" lines now offer a new "idle-ping" directive to enable checking of idle HTTP/2 connections to make sure they're still usable. While the first use case definitely is for reverse HTTP in order to kill dead connections, this can be convenient for long connections going through firewalls to get rid of dead ones instead of experiencing failures when sending requests on them. It can even be useful on frontends dealing with lots of mobile devices. - the roundrobin load balancer was reworked to better scale with large number of threads. It could show a lot of contention on big machines. Now there's in fact one load balancer per thread group. A test run on a 64-core EPYC with "cpu-policy performance" showed a 150% performance increase thanks to no longer accessing the same variables and locks from distant cores! Yes, that's 2.5 times faster :-) - the watchdog and thread dump signal handlers were reworked to address some of the remaining cases of deadlocks that some had met in 3.1 and 3.2. In addition the new approach focused on minimizing inter-thread synchronization, resulting in much less CPU overhead when displaying a warning. I've tortured it with many warnings, "show threads" and panics and it now looks rock solid. By the way during these tests, I've been running tests with "warn-blocked-traffic-after" set to one millisecond with 50k checks per second in which servers were constantly going up and down, and I was impressed to see that the warnings very rarely triggered. This means that even during high loads we now managed to maintain a low overall latency. - the backtraces are now enabled on musl, so that we'll have a bit more indications in the future from reports of Docker instances. Also, the x86 "call" and arm64 "bl" instructions preceeding the return address are decoded to display the called point, which often gives a few more hints about what was happening and even code locations. - 4 new sample fetch functions permit to retrieve some elements from the TLS client hello: req.ssl_cipherlist, req.ssl_keyshare_groups, req.ssl_sigalgs, req.ssl_supported_groups. This is in relation with github issue 2532 (thanks to Mariam John for working on this year-old task). - DEBUG_GLITCHES no longer exists, it was replaced with DEBUG_COUNTERS which takes values 0/1/2 (defaults to one), to decide whether to report nothing, only glitches, or also COUNT_IF(). When not zero, it's also possible to enable or disable them at boot time using the global "debug.counters" setting. The rest is essentially bug fixes that were already backported to 3.1.7 and mentioned there. I'm not going to rehash that since bug fixes is not the feature that attracts most users of a dev version. As usual, there were doc updates (particularly the new section 3.13 about ACME), some CI updates and cleanups. For what remains before the release, first I'd like some more tests and reports (even if it's just to say "nothing to say after 3 days in prod", that's very helpful). I know that there are some users of end-of-cycle versions, I'll ping a few in case they're busy and don't think about reading this announce. Some more ACME stuff should be merged to smooth certain steps and provide more info about what's going on. Then the low hanging fruits will be worked on. Some of that stuff could concern the CLI's buffer management that will permit to implement more interactive commands in the future without hacks like "wait"/"show events" are relying on, as well as a possibily we're seeing to reduce the cost of updating stick-tables keys when peers are enabled. For now let's test and have a nice week-end! Please find the usual URLs below : Site index : https://www.haproxy.org/ Documentation : https://docs.haproxy.org/ Wiki : https://github.com/haproxy/wiki/wiki Discourse : https://discourse.haproxy.org/ Slack channel : https://slack.haproxy.org/ Issue tracker : https://github.com/haproxy/haproxy/issues Sources : https://www.haproxy.org/download/3.2/src/ Git repository : https://git.haproxy.org/git/haproxy.git/ Git Web browsing : https://git.haproxy.org/?p=haproxy.git Changelog : https://www.haproxy.org/download/3.2/src/CHANGELOG Dataplane API : https://github.com/haproxytech/dataplaneapi/releases/latest Pending bugs : https://www.haproxy.org/l/pending-bugs Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs Code reports : https://www.haproxy.org/l/code-reports Latest builds : https://www.haproxy.org/l/dev-packages Willy --- Complete changelog : Amaury Denoyelle (16): BUG/MEDIUM: h3: trim whitespaces when parsing headers value BUG/MEDIUM: h3: trim whitespaces in header value prior to QPACK encoding BUG/MINOR: h3: filter upgrade connection header BUG/MINOR: h3: reject invalid :path in request BUG/MINOR: h3: reject request URI with invalid characters MEDIUM: h3: use absolute URI form with :authority BUG/MINOR: mux-h2: prevent past scheduling with idle connections BUG/MINOR: rhttp: fix reconnect if timeout connect unset BUG/MINOR: rhttp: ensure GOAWAY can be emitted after reversal BUG/MINOR: mux-h2: do not apply timer on idle backend connection MINOR: mux-h2: refactor idle timeout calculation MINOR: mux-h2: prepare to support PING emission MEDIUM: server/mux-h2: implement idle-ping on backend side MEDIUM: listener/mux-h2: implement idle-ping on frontend side MINOR: mux-h2: do not emit GOAWAY on idle ping expiration MINOR: mux-h2: handle idle-ping on conn reverse Aurelien DARRAGON (1): BUG/MEDIUM: hlua: fix hlua_applet_{http,tcp}_fct() yield regression (lost data) Christopher Faulet (2): BUG/MINOR: http-ana: Properly detect client abort when forwarding the response BUG/MEDIUM: http-ana: Report 502 from req analyzer only during rsp forwarding Ilia Shipitsin (1): CI: fedora rawhide: enable unit tests Ilya Shipitsin (1): CI: enable weekly QuicTLS build Mariam John (2): MINOR: sample: add 4 new sample fetches for clienthello parsing REGTEST: add new reg-test for the 4 new clienthello fetches Olivier Houchard (8): MINOR: servers: Move the per-thread server initialization earlier MINOR: proxies: Initialize the per-thread structure earlier. MINOR: servers: Provide a pointer to the server in srv_per_tgroup. MINOR: lb_fwrr: Move the next weight out of fwrr_group. MINOR: proxies: Add a per-thread group lbprm struct. MEDIUM: lb_fwrr: Use one ebtree per thread group. MEDIUM: lb_fwrr: Don't start all thread groups on the same server. MINOR: proxies: Do stage2 initialization for sinks too Valentine Krasnobaeva (1): BUG/MINOR: thread: protect thread_cpus_enabled_at_boot with USE_THREAD William Lallemand (42): MEDIUM: ssl/ckch: add filename and linenum argument to crt-store parsing MINOR: acme: add the acme section in the configuration parser MINOR: acme: add configuration for the crt-store MINOR: acme: add private key configuration MINOR: acme/cli: add the 'acme renew' command MINOR: acme: the acme section is experimental MINOR: acme: get the ACME directory MINOR: acme: handle the nonce MINOR: acme: check if the account exist MINOR: acme: generate new account MINOR: acme: newOrder request retrieve authorizations URLs MINOR: acme: allow empty payload in acme_jws_payload() MINOR: acme: get the challenges object from the Auth URL MINOR: acme: send the request for challenge ready MINOR: acme: implement a check on the challenge status MINOR: acme: generate the CSR in a X509_REQ MINOR: acme: finalize by sending the CSR MINOR: acme: verify the order status once finalized MINOR: acme: implement retrieval of the certificate BUG/MINOR: acme: ckch_conf_acme_init() when no filename MINOR: ssl/ckch: handle ckch_conf in ckchs_dup() and ckch_conf_clean() MINOR: acme: copy the original ckch_store MEDIUM: acme: replace the previous ckch instance with new ones MINOR: acme: schedule retries with a timer BUILD: acme: enable the ACME feature when JWS is present BUG/MINOR: acme: key not restored upon error in acme_res_certificate() MINOR: acme: default to 2048bits for RSA DOC: acme: explain how to configure and run ACME BUG/MINOR: acme: fix possible NULL deref CLEANUP: acme: stored value is overwritten before it can be used BUILD: incompatible pointer type suspected with -DDEBUG_UNIT DOC: configuration: fix a typo in ACME documentation MEDIUM: sink: add a new dpapi ring buffer Revert "BUG/MINOR: acme: key not restored upon error in acme_res_certificate()" BUG/MINOR: acme: key not restored upon error in acme_res_certificate() V2 BUG/MINOR: acme: fix the exponential backoff of retries DOC: configuration: specify limitations of ACME for 3.2 MINOR: acme: emit logs instead of ha_notice MINOR: acme: add a success message to the logs BUG/MINOR: acme/cli: fix certificate name in error message MINOR: acme: register the task in the ckch_store MINOR: acme: free acme_ctx once the task is done Willy Tarreau (33): DOC: management: slightly clarify the prefix role of the '@' command DOC: management: add a paragraph about the limitations of the '@' prefix MINOR: master/cli: support bidirectional communications with workers BUG/MINOR: cpu-topo: check the correct variable for NULL after malloc() BUG/MINOR: debug: remove the trailing \n from BUG_ON() statements DOC: config: add the missing "profiling.memory" to the global kw index DOC: config: add the missing "force-cfg-parser-pause" to the global kw index DEBUG: init: report invalid characters in debug description strings DEBUG: rename DEBUG_GLITCHES to DEBUG_COUNTERS and enable it by default DEBUG: counters: make COUNT_IF() only appear at DEBUG_COUNTERS>=1 DEBUG: counters: add the ability to enable/disable updating the COUNT_IF counters MINOR: tools: let dump_addr_and_bytes() support dumping before the offset MINOR: debug: in call traces, dump the 8 bytes before the return address, not after MINOR: debug: detect call instructions and show the branch target in backtraces BUILD: makefile: enable backtrace by default on musl BUG/MINOR: threads: set threads_idle and threads_harmless even with no threads BUG/MINOR debug: fix !USE_THREAD_DUMP in ha_thread_dump_fill() BUG/MINOR: wdt/debug: avoid signal re-entrance between debugger and watchdog BUG/MINOR: debug: detect and prevent re-entrance in ha_thread_dump_fill() MINOR: debug: do not statify a few debugging functions often used with wdt/dbg MINOR: tools: also protect the library name resolution against concurrent accesses MINOR: tools: protect dladdr() against reentrant calls from the debug handler MINOR: debug: protect ha_dump_backtrace() against risks of re-entrance MINOR: tinfo: keep a copy of the pointer to the thread dump buffer MINOR: debug: always reset the dump pointer when done MINOR: debug: remove unused case of thr!=tid in ha_thread_dump_one() MINOR: pass a valid buffer pointer to ha_thread_dump_one() MEDIUM: wdt: always make the faulty thread report its own warnings MINOR: debug: make ha_stuck_warning() only work for the current thread MINOR: debug: make ha_stuck_warning() print the whole message at once CLEANUP: debug: no longer set nor use TH_FL_DUMPING_OTHERS MINOR: sched: add a new function is_sched_alive() to report scheduler's health MINOR: wdt: use is_sched_alive() instead of keeping a local ctxsw copy ---