26826 Commits

Author SHA1 Message Date
Willy Tarreau
1cdb6bf3f8 [RELEASE] Released version 3.4-dev9
Released version 3.4-dev9 with the following main changes :
    - DOC: config: fix ambiguous info in log-steps directive description
    - MINOR: filters: add filter name to flt_conf struct
    - MEDIUM: filters: add "filter-sequence" directive
    - REGTESTS: add a test for "filter-sequence" directive
    - Revert "CLEANUP: tcpcheck: Don't needlessly expose proxy_parse_tcpcheck()"
    - MINOR: tcpcheck: reintroduce proxy_parse_tcpcheck() symbol
    - BUG/MEDIUM: haterm: Move all init functions of haterm in haterm_init.c
    - BUG/MEDIUM: mux-h1: Disable 0-copy forwarding when draining the request
    - MINOR: servers: The right parameter for idle-pool.shared is "full"
    - DOC: config: Fix two typos in the server param "healthcheck" description
    - BUG/MINOR: http-act: fix a typo in the "pause" action error message
    - MINOR: tcpcheck: Reject unknown keyword during parsing of healthcheck section
    - BUG/MEDIUM: tcpcheck/server: Fix parsing of healthcheck param for dynamic servers
    - BUG/MINOR: counters: fix unexpected 127 char GUID truncation for shm-stats-file objects
    - BUG/MEDIUM: tcpcheck: Properly retrieve tcpcheck type to install the best mux
    - BUG/MEDIUM: payload: validate SNI name_len in req.ssl_sni
    - BUG/MEDIUM: jwe: fix NULL deref crash with empty CEK and non-dir alg
    - BUG/MEDIUM: jwt: fix heap overflow in ECDSA signature DER conversion
    - BUG/MEDIUM: jwe: fix memory leak in jwt_decrypt_secret with var argument
    - BUG: hlua: fix stack overflow in httpclient headers conversion
    - BUG/MINOR: hlua: fix stack overflow in httpclient headers conversion
    - BUG/MINOR: hlua: fix format-string vulnerability in Patref error path
    - BUG/MEDIUM: chunk: fix typo allocating small trash with bufsize_large
    - BUG/MEDIUM: chunk: fix infinite loop in get_larger_trash_chunk()
    - BUG/MINOR: peers: fix OOB heap write in dictionary cache update
    - CI: VTest build with git clone + cache
    - BUG/MEDIUM: connection: Wake the stconn on error when failing to create mux
    - CI: github: update to cache@v5
    - Revert "BUG: hlua: fix stack overflow in httpclient headers conversion"
    - CI: github: fix vtest path to allow correct caching
    - CI: github: add the architecture to the cache key for vtest2
    - MEDIUM: connections: Really enforce mux protocol requirements
    - MINOR: tools: Implement net_addr_type_is_quic()
    - MEDIUM: check: Revamp the way the protocol and xprt are determined
    - BUG/MAJOR: slz: always make sure to limit fixed output to less than worst case literals
    - MINOR: lua: add tune.lua.openlibs to restrict loaded Lua standard libraries
    - REGTESTS: lua: add tune.lua.openlibs to all Lua reg-tests
    - BUG/MINOR: resolvers: fix memory leak on AAAA additional records
    - BUG/MINOR: spoe: fix pointer arithmetic overflow in spoe_decode_buffer()
    - BUG/MINOR: http-act: validate decoded lengths in *-headers-bin
    - BUG/MINOR: haterm: Return the good start-line for 100-continue interim message
    - BUG/MEDIUM: samples: Fix handling of SMP_T_METH samples
    - BUG/MINOR: sample: fix info leak in regsub when exp_replace fails
    - BUG/MEDIUM: mux-fcgi: prevent record-length truncation with large bufsize
    - BUG/MINOR: hlua: fix use-after-free of HTTP reason string
    - BUG/MINOR: mux-quic: fix potential NULL deref on qcc_release()
    - BUG/MINOR: quic: increment pos pointer on QMux transport params parsing
    - MINOR: xprt_qstrm: implement Rx buffering
    - MINOR: xprt_qstrm/mux-quic: handle extra QMux frames after params
    - MINOR: xprt_qstrm: implement Tx buffering
    - MINOR: xprt_qstrm: handle connection errors
    - MEDIUM: mux-quic: implement QMux record parsing
    - MEDIUM: xprt_qstrm: implement QMux record parsing
    - MEDIUM: mux-quic/xprt_qstrm: implement QMux record emission
    - DOC: update draft link for QMux protocol
    - BUG/MINOR: do not crash on QMux reception of BLOCKED frames
    - Revert "BUG/MEDIUM: haterm: Move all init functions of haterm in haterm_init.c"
    - BUG/MEDIUM: haterm: Properly initialize the splicing support for haterm
    - BUG/MINOR: mux_quic: prevent QMux crash on qcc_io_send() error path
    - BUG/MINOR: xprt_qstrm: do not parse record length on read again
    - MEDIUM: otel: added OpenTelemetry filter skeleton
    - MEDIUM: otel: added configuration and utility layer
    - MEDIUM: otel: added configuration parser and event model
    - MEDIUM: otel: added post-parse configuration check
    - MEDIUM: otel: added memory pool and runtime scope layer
    - MEDIUM: otel: implemented filter callbacks and event dispatcher
    - MEDIUM: otel: wired OTel C wrapper library integration
    - MEDIUM: otel: implemented scope execution and span management
    - MEDIUM: otel: added context propagation via carrier interfaces
    - MEDIUM: otel: added HTTP header operations for context propagation
    - MEDIUM: otel: added HAProxy variable storage for context propagation
    - MINOR: otel: added prefix-based variable scanning
    - MEDIUM: otel: added CLI commands for runtime filter management
    - MEDIUM: otel: added group action for rule-based scope execution
    - MINOR: otel: added log-format support to the sample parser and runtime
    - MINOR: otel: test: added test and benchmark suite for the OTel filter
    - MINOR: otel: added span link support
    - MINOR: otel: added metrics instrument support
    - MINOR: otel: added log-record signal support
    - MINOR: otel: test: added full-event test config
    - DOC: otel: added documentation
    - DOC: otel: test: added test README-* files
    - DOC: otel: test: added speed test guide and benchmark results
    - DOC: otel: added cross-cutting design patterns document
    - MINOR: otel: added flt_otel_sample_eval and exposed flt_otel_sample_add_kv
    - MINOR: otel: changed log-record attr to use sample expressions
    - MINOR: otel: changed instrument attr to use sample expressions
    - DOC: otel: added README.md overview document
    - CLEANUP: ot: use the item API for the variables trees
    - BUG/MINOR: ot: removed dead code in flt_ot_parse_cfg_str()
    - BUG/MINOR: ot: fixed wrong NULL check in flt_ot_parse_cfg_group()
    - BUILD: ot: removed explicit include path when building opentracing filter
    - MINOR: ot: renamed the variable dbg_indent_level to flt_ot_dbg_indent_level
    - CI: Drop obsolete `packages: write` permission from `quic-interop-*.yml`
    - CI: Consistently add a top-level `permissions` definition to GHA workflows
    - CI: Wrap all `if:` conditions in `${{ }}`
    - CI: Fix regular expression escaping in matrix.py
    - CI: Update to actions/checkout@v6
    - CI: Simplify version extraction with `haproxy -vq`
    - CI: Merge `aws-lc.yml` and `aws-lc-fips.yml` into `aws-lc.yml`
    - CI: Merge `aws-lc-template.yml` into `aws-lc.yml`
    - CI: Consistently set up VTest with `./.github/actions/setup-vtest`
    - MINOR: mux_quic: remove duplicate QMux local transport params
    - CI: github: add bash to the musl job
    - BUG/MINOR: quic: do not use hardcoded values in QMux TP frame builder
    - BUG/MINOR: log: Fix error message when using unavailable fetch in logfmt
    - CLEANUP: log: Return `size_t` from `sess_build_logline_orig()`
    - CLEANUP: stream: Explain the two-step initialization in `stream_generate_unique_id()`
    - CLEANUP: stream: Reduce duplication in `stream_generate_unique_id()`
    - CLEANUP: http_fetch: Use local `unique_id` variable in `smp_fetch_uniqueid()`
    - CI: build WolfSSL job with asan enabled
    - MINOR: tools: memvprintf(): remove <out> check that always true
    - BUG/MEDIUM: cli: Properly handle too big payload on a command line
    - REGTESTS: Never reuse server connection in reg-tests/jwt/jwt_decrypt.vtc
    - MINOR: errors: remove excessive errmsg checks
    - BUG/MINOR: haterm: preserve the pipe size margin for splicing
    - MEDIUM: acme: implement dns-persist-01 challenge
    - MINOR: acme: extend resolver-based DNS pre-check to dns-persist-01
    - DOC: configuration: document dns-persist-01 challenge type and options
    - BUG/MINOR: acme: read the wildcard flag from the authorization response
    - BUG/MINOR: acme: don't pass NULL into format string
    - BUG/MINOR: haterm: don't apply the default pipe size margin twice
    - CLEANUP: Make `lf_expr` parameter of `sess_build_logline_orig()` const
    - MINOR: Add `generate_unique_id()` helper
    - MINOR: Allow inlining of `stream_generate_unique_id()`
    - CLEANUP: log: Stop touching `struct stream` internals for `%ID`
    - MINOR: check: Support generating a `unique_id` for checks
    - MINOR: http_fetch: Add support for checks to `unique-id` fetch
    - MINOR: acme: display the type of challenge in ACME_INITIAL_DELAY
    - MINOR: mjson: reintroduce mjson_next()
    - CI: Remove obsolete steps from musl.yml
    - CI: Use `sh` in `actions/setup-vtest/action.yml`
    - CI: Sync musl.yml with vtest.yml
    - CI: Integrate Musl build into vtest.yml
    - CI: Use `case()` function
    - CI: Generate vtest.yml matrix on `ubuntu-slim`
    - CI: Run contrib.yml on `ubuntu-slim`
    - CI: Use `matrix:` in contrib.yml
    - CI: Build `dev/haring/` as part of contrib.yml
    - MINOR: htx: Add helper function to get type and size from the block info field
    - BUG/MEDIUM: htx: Properly handle block modification during defragmentation
    - BUG/MEDIUM: htx: Don't count delta twice when block value is replaced
    - MINOR: ssl: add TLS 1.2 values in HAPROXY_KEYLOG_XX_LOG_FMT
    - EXAMPLES: ssl: keylog entries are greater than 1024
    - BUILD: Makefile: don't forget to also delete haterm on make clean
    - MINOR: stats: report the number of thread groups in "show info"
    - CLEANUP: sample: fix the comment regarding the range of the thread sample fetch
    - MINOR: sample: return the number of the current thread group
    - MINOR: sample: add new sample fetch functions reporting current CPU usage
    - BUG/MEDIUM: peers: trash of expired entries delayed after fullresync
    - DOC: remove the alpine/musl status job image
    - MINOR: mux-quic: improve documentation for qcs_attach_sc()
    - MINOR: mux-quic: reorganize code for app init/shutdown
    - MINOR: mux-quic: perform app init in case of early shutdown
    - MEDIUM: quic: implement fe.stream.max-total
    - MINOR: mux-quic: close connection when reaching max-total streams
    - REGTESTS: add QUIC test for max-total streams setting
    - MEDIUM: threads: start threads by groups
    - MINOR: acme: opportunistic DNS check for dns-persist-01 to skip challenge-ready steps
    - BUG/MINOR: acme: fix fallback state after failed initial DNS check
    - CLEANUP: acme: no need to reset ctx state and http_state before nextreq
    - BUG/MINOR: threads: properly set the number of tgroups when non using policy
v3.4-dev9
2026-04-15 17:59:00 +02:00
Willy Tarreau
d7c747b572 BUG/MINOR: threads: properly set the number of tgroups when non using policy
When nbthread is set, the CPU policies are not used and do not set
nbthread nor nbtgroups. When back into thread_detect_count(), these
are set respectively to thr_max and 1. The problem which becomes very
visible with max-threads-per-group, is that setting this one in
combination with nbthreads results in only one group with the calculated
number of threads per group. And there's not even a warning. So basically
a configuration having:

   global
       nbthread 64
       max-threads-per-group 8

would only start 8 threads.

In this case, grp_min remains valid and should be used, so let's just
change the assignment so that the number of groups is always correct.

A few ifdefs had to move because the calculations were only made for
the USE_CPU_AFFINITY case. Now these parts have been refined so that
all the logic continues to apply even without USE_CPU_AFFINITY.

One visible side effect is that setting nbthread above 64 will
automatically create the associated number of groups even when
USE_CPU_AFFINITY is not set. Previously it was silently changed
to match the per-group limit.

Ideally this should be backported to 3.2 where the issue was
introduced, though it may change the behavior of configs that were
silently being ignored (e.g. "nbthread 128"), so the backport should
be considered with care. At least 3.3 should have it because it uses
cpu-policy by default so it's only for failing cases that it would be
involved.
2026-04-15 17:47:26 +02:00
William Lallemand
794737cc8d CLEANUP: acme: no need to reset ctx state and http_state before nextreq
The nextreq label already implement setting http_state to ACME_HTTP_REQ
and setting ctx->state to st. It is only needed to set the st variable
before jumping to nextreq.
2026-04-15 16:17:39 +02:00
William Lallemand
69211b869f BUG/MINOR: acme: fix fallback state after failed initial DNS check
When the opportunistic initial DNS check (ACME_INITIAL_RSLV_READY) fails,
the state machine was incorrectly transitioning to ACME_RSLV_RETRY_DELAY
instead of ACME_CLI_WAIT. This caused the challenge to enter the DNS retry
loop rather than falling back to the normal cond_ready flow that waits for
the CLI signal.

Also reorder ACME_CLI_WAIT in the state enum and trace switch to reflect
the actual execution order introduced in the previous commit: it comes after
ACME_INITIAL_RSLV_READY, not before ACME_INITIAL_RSLV_TRIGGER.

No backport needed.
2026-04-15 16:06:59 +02:00
William Lallemand
c295a5c861 MINOR: acme: opportunistic DNS check for dns-persist-01 to skip challenge-ready steps
For dns-persist-01, the "_validation-persist.<domain>" TXT record is set once
and never changes between renewals. Add an initial opportunistic DNS check
(ACME_INITIAL_RSLV_TRIGGER / ACME_INITIAL_RSLV_READY states) that runs before
the challenge-ready conditions are evaluated. If all domains already have the
TXT record, the challenge is submitted immediately without going through the
cli/delay/dns challenge-ready steps, making renewals faster once the record is
in place.

The new ACME_RDY_INITIAL_DNS flag is automatically set for
dns-persist-01 in cond_ready.
2026-04-15 15:57:57 +02:00
Willy Tarreau
5fe0579d49 MEDIUM: threads: start threads by groups
Till now, threads were all started one at a time from thread 1. This
will soon cause us limitations once we want to reduce shared stuff
between thread groups.

Let's slightly change the startup sequence so that the first thread
starts one initial thread for each group, and that each of these
threads then starts all other threads from their group before switching
to the final task. Since it requires an intermediary step, we need to
store that threads' start function to access it from the group, so it
was put into the tgroup_info which still has plenty of room available.

It could also theoretically speed up the boot sequence, though in
practice it doesn't change anything because each thead's initialization
is made one at a time to avoid races during the early boot. However
ther is now a function in charge of starting all extra threads of a
group, and whih is called from this group.
2026-04-15 15:53:56 +02:00
Amaury Denoyelle
15a19994df REGTESTS: add QUIC test for max-total streams setting
Add a new QUIC regtest to test the new frontend stream.max-total
setting.

This test relies on two haproxy instances, as QUIC client and server.
New setting stream.max-total is set to 3 on the server side. In total, 6
requests are performed, with a check to ensure that a new connection has
been reopened for the last ones.
2026-04-15 15:18:37 +02:00
Amaury Denoyelle
e2dbcd20f2 MINOR: mux-quic: close connection when reaching max-total streams
This commit completes the previous one which implements a new setting to
limit the number of streams usable by a client on a QUIC connection.

When the connection becomes idle after reaching this limit, it is
immediately closed. This is implemented by extending checks in
qcc_is_dead(). This results in a CONNECTION_CLOSE emission, which is
useful to free resources as soon as possible.
2026-04-15 15:18:37 +02:00
Amaury Denoyelle
497cabd9e5 MEDIUM: quic: implement fe.stream.max-total
Implement a new setting to limit the total number of bidirectional
streams that the client may use on a single connection. By default, it
is set to 0 which means it is not limited at all.

If a positive value is configured, the client can only open a fixed
number of request streams per QUIC connection. Internally, this is
implemented in two steps :

* First, MAX_STREAMS_BIDI flow control advertizing will be reduced when
  approaching the limit before being completely turned off when reaching
  it. This guarantees that the client cannot exceed the limit without
  violating the flow control.

* Second, when attaching the latest stream with ID matching max-total
  setting, connection graceful shutdown is initiated. In HTTP/3, this
  results in a GOAWAY emission. This allows the remaining streams to be
  completed before the connection becomes completely idle.
2026-04-15 15:18:37 +02:00
Amaury Denoyelle
a7e1c82648 MINOR: mux-quic: perform app init in case of early shutdown
Adds a qcc_app_init() call in qcc_app_shutdown(). This is necessary if
shutdown is performed early, before any invokation of qcc_io_send().

Currently, this should never occur in practice. However, this will
become necessary with the new settings tune.quic.fe.stream.max-total.
Indeed, when using a very small value, app-ops layer may be closed early
in the connection lifetime.
2026-04-15 14:34:13 +02:00
Amaury Denoyelle
1038720675 MINOR: mux-quic: reorganize code for app init/shutdown
Refactor code related to app-layer init/shutdown operations. In short,
qcc_shutdown() is renamed to qcc_app_shutdown(). It is also moved next
to qcc_app_init() to better reflect their link.
2026-04-15 14:34:13 +02:00
Amaury Denoyelle
6c837723bf MINOR: mux-quic: improve documentation for qcs_attach_sc()
Complete function doc for qcs_attach_sc() by using the proper
terminology related to stream/stconn/sedesc. The purpose of this
function should be clearer now.
2026-04-15 14:34:13 +02:00
William Lallemand
e5619b836b DOC: remove the alpine/musl status job image
alpine/musl was merged into the VTest job, remove the status image which
does not work anymore.
2026-04-15 11:34:17 +02:00
Emeric Brun
8f06c8fda4 BUG/MEDIUM: peers: trash of expired entries delayed after fullresync
stksess_new has set the entry expire to the table expire delay,
if it is a new entry, set_entry inserts at that position in the expire
tree. There was a touch_remote updating the expire setting but the
tree's re-ordering is not designed to set back in the past resulting
to an entry that will be trashed only after a full table's expire delay
regardless the expire set on the stktsess.

This patch sets the newts expire before the call of 'set_entry'.
This way a new inserted entry is set directly at the right position
in the tree to trash the entry in time.

This patch should be backported on all supported branches and at
least v2.8
2026-04-15 10:03:17 +02:00
Willy Tarreau
90e8ccd9c2 MINOR: sample: add new sample fetch functions reporting current CPU usage
Some features can automatically turn on or off depending on CPU usage,
but it's not easy to measure it. Let's provide 3 new sample fetch functions
reporting the CPU usage as measured inside haproxy during the previous
polling loop, and reported in "idle" stats header / "show info", or used
by tune.glitches.kill.cpu-usage, or maxcompcpuusage:

  - cpu_usage_thr: CPU usage between 0 and 100 of the current thread, used
    by functions above
  - cpu_usage_grp: CPU usage between 0 and 100, averaged over all threads of
    the same group as the current one.
  - cpu_usage_proc: CPU usage between 0 and 100, averaged over all threads
    of the current process

Note that the value will fluctuate since it only covers a few tens to
hundreds of requests of the last polling loop, but it reports what is
being used to take decisions.

It could also be used to disable some non-essential debugging/processing
under too high loads for example.
2026-04-14 17:47:18 +02:00
Willy Tarreau
630ef96f92 MINOR: sample: return the number of the current thread group
Just like we have a sample fetch function that returns the number of the
current thread, let's have the same with the thread group number. This
can be useful for troubleshooting, given that certain things are currently
per thread-group (e.g. idle backend connections, certain LB algos etc).
2026-04-14 17:05:34 +02:00
Willy Tarreau
b943d2a7eb CLEANUP: sample: fix the comment regarding the range of the thread sample fetch
The comment says "between 1 and nbthread" while it's in fact between 0 and
nbthread-1 and this is also documented like this in the config manual. No
backport needed though it cannot hurt.
2026-04-14 16:59:56 +02:00
Willy Tarreau
9c6e07c43f MINOR: stats: report the number of thread groups in "show info"
Since thread groups were enabled by default in 3.3, it has become an
important element of diagnostic that we're missing in "show info". Let's
add it under "NbThreadGroups".
2026-04-14 16:48:16 +02:00
Willy Tarreau
e9fcf994ca BUILD: Makefile: don't forget to also delete haterm on make clean
haterm depends on the same source files as haproxy, yet it wasn't deleted
on "make clean", resulting in confusion when rebuilding and believing to
run the freshly built one. Let's just add it to the "clean" target. No
backport is needed since haterm is 3.4-only.
2026-04-14 16:48:16 +02:00
William Lallemand
788f57448a EXAMPLES: ssl: keylog entries are greater than 1024
Adjust the log size to 2048, the default 1024 bytes of a log line are
too small since f28dd15 ("MINOR: ssl: add TLS 1.2 values in
HAPROXY_KEYLOG_XX_LOG_FMT")
2026-04-14 16:24:28 +02:00
William Lallemand
f28dd158ed MINOR: ssl: add TLS 1.2 values in HAPROXY_KEYLOG_XX_LOG_FMT
Add the CLIENT_RANDOM line for TLS1.2 in HAPROXY_KEYLOG_FC_LOG_FMT and
HAPROXY_KEY_LOG_BC_FMT. These are useful to produce a keylog file
compatible with both TLS1.3 and TLS1.2.
2026-04-14 16:03:25 +02:00
Christopher Faulet
7270bfcff5 BUG/MEDIUM: htx: Don't count delta twice when block value is replaced
A regression was introduced by the commit a8887e55a ("BUG/MEDIUM: htx: Fix
function used to change part of a block value when defrag").

When a block value was replaced and a defragmentation was performed, the
delta between the old value and the new one was counted twice. htx_defrag()
already is responsible to set the new size for the HTX message. So it must
not be performed in htx_replace_blk_value().

This patch must be backported with the commit above. So theorically to all
stable versions.
2026-04-14 14:07:21 +02:00
Christopher Faulet
d899f23017 BUG/MEDIUM: htx: Properly handle block modification during defragmentation
A regression was introcuded by the commit 0c6f2207f ("MEDIUM: htx: Refactor
htx defragmentation to merge data blocks").

When a defragmentation is performed, it is possible to alter a block
size. The main usage is to prepare a block value replacement. However, since
the commit above, the change is no longer handled. The block info are
changed but the size of the message is not modified accordingly.

This patch depends on the commit "MINOR: htx: Add helper function to get
type and size from the block info field"

No backport needed.
2026-04-14 14:07:21 +02:00
Christopher Faulet
ebaa88a23a MINOR: htx: Add helper function to get type and size from the block info field
__htx_blkinfo_type() and __htx_blkinfo_size() function was added to return,
respectively, the type and the size from the block info field. The main
usage for these functions is internal to the htx code.
2026-04-14 14:07:21 +02:00
Tim Duesterhus
6ff659db06 CI: Build dev/haring/ as part of contrib.yml
This functionally is quite similar to `dev/flags/` and thus it makes sense to
include it.
2026-04-14 11:16:17 +02:00
Tim Duesterhus
c9067a6ed7 CI: Use matrix: in contrib.yml
This makes it much easier to add additional "smoke-tests" to contrib.yml. The
previous set-up also didn't allow to easily see all failures when a single
build fails, because it would abort after any failed step.
2026-04-14 11:16:17 +02:00
Tim Duesterhus
291d265aeb CI: Run contrib.yml on ubuntu-slim
This is sufficient for this simple "does it compile" smoke-test.
2026-04-14 11:16:17 +02:00
Tim Duesterhus
2ccd2827d4 CI: Generate vtest.yml matrix on ubuntu-slim
This runner image is more lightweight by running inside of a container rather
than a full VM. This is sufficient to run some Python.
2026-04-14 11:16:17 +02:00
Tim Duesterhus
578d971d7d CI: Use case() function
GitHub Actions introduced a new `case()` function in January that works just
like HAProxy’s `iif()` converter (just with an arbitrary number of
expressions). It is more robust than chaining strings with `&&` and `||`,
because it includes proper type-checking.

see https://github.blog/changelog/2026-01-29-github-actions-smarter-editing-clearer-debugging-and-a-new-case-function/#write-more-expressive-expressions-with-a-case-function
2026-04-14 11:16:17 +02:00
Tim Duesterhus
7640d7949f CI: Integrate Musl build into vtest.yml
With the previous sync, these two workflows perform almost the same steps and
both logically belong to "Run VTest tests". Integrate musl.yml into vtest.yml,
which will hopefully encourage future changes to consistently apply to all jobs
in that workflow.
2026-04-14 11:16:17 +02:00
Tim Duesterhus
76d1dbfb61 CI: Sync musl.yml with vtest.yml
This syncs up musl.yml with vtest.yml as much as possible by:

- Aligning indentation.
- Reordering steps.
- Aligning step names.
- Adding missing functionality to musl.yml.
2026-04-14 11:16:17 +02:00
Tim Duesterhus
edf72ac1a4 CI: Use sh in actions/setup-vtest/action.yml
Bash might not always be preinstalled and we don't make use of any
bash-specific features either. Switch to POSIX sh for simplicity.

This partly reverts the fix in 073240044e476c365242a5541c01bb0503f1e7c2, which
installed `bash` for the musl job.
2026-04-14 11:16:17 +02:00
Tim Duesterhus
716218f723 CI: Remove obsolete steps from musl.yml
These have become obsolete with the use of `./.github/actions/setup-vtest` in
6e67b59aca11e8262c424fce062a09784d3da2ba.
2026-04-14 11:16:17 +02:00
William Lallemand
3415abe56d MINOR: mjson: reintroduce mjson_next()
The lack of mjson_next() prevents to iterate easily and need to hack by
iterating on a loop of snprintf + $.field[XXX] combined with
mjson_find().

This reintroduce mjson_next() so we could iterate without having to
build the string.

The patch does not reintroduce MJSON_ENABLE_NEXT so it could be used
without having to define it.
2026-04-14 10:57:21 +02:00
William Lallemand
cf72132f22 MINOR: acme: display the type of challenge in ACME_INITIAL_DELAY
The ACME_INITIAL_DELAY state displays a message about 'dns-01', but this
state is also used for 'dns-persist-01'.

This patch displays the challenge that was configured instead of dns-01
2026-04-14 10:16:11 +02:00
Tim Duesterhus
ed0c51d2c0 MINOR: http_fetch: Add support for checks to unique-id fetch
This allows to use the `unique-id` fetch within `tcp-check` or `http-check`
ruleset. The format is taken from the checked server's backend (which is
naturally inherited from the corresponding `defaults` section).

This is particularly useful with

    http-check send ... hdr request-id %[unique-id]

to ensure all requests sent by HAProxy have a unique ID header attached.

This resolves GitHub Issue #3307.

Reviewed-by: Volker Dusch <github@wallbash.com>
2026-04-13 20:02:21 +02:00
Tim Duesterhus
2c748125f5 MINOR: check: Support generating a unique_id for checks
This implementation is directly modeled after `stream_generate_unique_id()` and
the corresponding `unique_id` field on `struct stream`.

It will be used in a future commit to enable the use of the `%[unique-id]`
fetch in check rules.
2026-04-13 20:01:42 +02:00
Tim Duesterhus
7ff2627112 CLEANUP: log: Stop touching struct stream internals for %ID
Use the return value of `stream_generate_unique_id()` instead of relying on the
`unique_id` field of `struct stream` when handling the `%ID` log placeholder.
This also allowed to unify the "stream available" and "stream not available"
paths.

Reviewed-by: Volker Dusch <github@wallbash.com>
2026-04-13 20:01:42 +02:00
Tim Duesterhus
38796d4c06 MINOR: Allow inlining of stream_generate_unique_id()
With the introduction of the `generate_unique_id()` helper, the actual
complicated logic is sitting in a different file. Allow inlining of
`stream_generate_unique_id()`, so that callers can benefit from an abstraction
without hiding away the access of `strm->unique_id` behind a function call.
2026-04-13 20:01:42 +02:00
Tim Duesterhus
73040e3a8e MINOR: Add generate_unique_id() helper
This new function will handle the actual generation of the unique ID according
to a format. The caller is responsible to check that no unique ID is stored
yet.
2026-04-13 20:01:02 +02:00
Tim Duesterhus
4cf06a7d23 CLEANUP: Make lf_expr parameter of sess_build_logline_orig() const
Since this is safely possible without making any changes, we can provide this
hint to the compiler.
2026-04-13 19:59:12 +02:00
Willy Tarreau
9a5db56a36 BUG/MINOR: haterm: don't apply the default pipe size margin twice
Commit 6d16b11022 ("BUG/MINOR: haterm: preserve the pipe size margin
for splicing") solved the issue of pipe size being sufficient for the
vmsplice() call, but as Christopher pointed out, the ratio was applied
to the default size of 64k, so now it's applied twice, giving 100k
instead of 80k. Let's drop it from there.

No backport needed.
2026-04-13 19:38:48 +02:00
Egor Shestakov
79c54d28b0 BUG/MINOR: acme: don't pass NULL into format string
Printing a "(null)" when NULL passed with the %s format specifier is a
GNU extension, so it must be avoided for portability reasons.

Must be backported as far as 3.2
2026-04-13 18:56:13 +02:00
William Lallemand
53679fe5f6 BUG/MINOR: acme: read the wildcard flag from the authorization response
The wildcard field was declared and used when building the dns-persist-01
TXT record value (policy=wildcard suffix), but was never populated from
the server's authorization response. Add the missing mjson_get_bool() call
to read $.wildcard before saving auth->dns.
2026-04-13 18:49:53 +02:00
William Lallemand
a5e732ed1d DOC: configuration: document dns-persist-01 challenge type and options
Document the dns-persist-01 challenge type under the challenge keyword,
the challenge-ready dns option (existence-only TXT check for dns-persist-01),
and the default challenge-ready value when challenge is dns-persist-01.
2026-04-13 18:45:08 +02:00
William Lallemand
39476040ec MINOR: acme: extend resolver-based DNS pre-check to dns-persist-01
Add challenge_type parameter to acme_rslv_start() to select the correct
DNS lookup prefix: _validation-persist.<domain> for dns-persist-01 and
_acme-challenge.<domain> for dns-01.

Default cond_ready to ACME_RDY_DNS|ACME_RDY_DELAY for dns-persist-01.
Extend ACME_CLI_WAIT to cover dns-persist-01 alongside dns-01.

In ACME_RSLV_READY, check only TXT record existence for dns-persist-01
since the resolver cannot parse multiple strings within a single TXT entry.
2026-04-13 18:45:08 +02:00
Mia Kanashi
0d3689959d MEDIUM: acme: implement dns-persist-01 challenge
Implements draft DNS-PERSIST-01 challenge based on
https://datatracker.ietf.org/doc/html/draft-ietf-acme-dns-persist

Blog post: https://letsencrypt.org/2026/02/18/dns-persist-01

This challenge is designed to use preprovisioned DNS records,
unlike DNS-01 challenge it doesn't need per provider API integration.

In short instead of validating order by crafting a custom response
based on input recieved from ACME server, like other challenges do
in particular DNS-01, HTTP-01, TLS-ALPN-01, in this challenge you
authorize domain statically, ACME account key functions similar to
a private key and accounturi in the record functions like a public key,
ACME server verifies that account uri matches account key and authorizes
based on that. You only need to write DNS record one time,
accounturi binds to an account key, and will only change if new account
key is created, although it is possible to rotate account key without
changing account uri.

Main benefits of this challenge in contrast to DNS-01:
1. Security, no need to give reverse proxy write access to the DNS.
2. Simplicity, no complex per provider integrations like Lego needed.
3. Robustness, no worrying about DNS record cache each renewal.

It would be used like this:
1. generate an account key ahead of time
2. add required DNS record manually or automatically using IaC tools
3. start HAProxy with the same account key used

Intended way to use this challenge is with a code that will print
and maybe sets DNS records ahead of time. For example that could
be integrated into the IaC provisioning step. This challenge type
is extremely recent though, so those integrations are yet to be written.

It is possible to do this challenge without extra tools too,
with pebble / challtestsrv steps would be as following:

After starting HAProxy it will print required records in the logs.

With challtestsrv you can then set those records like this:

curl -d '{
  "host":"_validation-persist.localhost.",
  "value": "pebble.letsencrypt.org; accounturi=...; policy=wildcard"}
' http://localhost:8055/set-txt

After setting the records run renew with the name of the certificate:

echo "acme renew @cert/localhost.pem" \
  | socat stdio tcp4-connect:127.0.0.1:9999

Or just restart HAProxy.

Unlike with DNS-01 you don't have to worry about DNS records changing,
if there is any problem with DNS records you can just retry.
2026-04-13 18:45:08 +02:00
Willy Tarreau
6d16b11022 BUG/MINOR: haterm: preserve the pipe size margin for splicing
Originally in httpterm we used to allocate 5/4 of the size of a pipe to
permit to use vmsplice because there's some fragmentation or overhead
internally that requires to use a bit of margin. While this was initially
applied to haterm as well, it was accidentally lost with commit fb82dece47
("BUG/MEDIUM: haterm: Properly initialize the splicing support for haterm"),
resulting in errors about vmsplice() whenever tune.pipesize is set. Let's
enforce the ratio again.

No backport is needed.
2026-04-13 18:37:04 +02:00
Egor Shestakov
61f04d1951 MINOR: errors: remove excessive errmsg checks
I noticed some strange checks for presence of errmsg. Called functions
generate non-empty error message in case of failure, so a non-NULL address
of the error message is enough.

No backport needed.
2026-04-13 15:39:05 +02:00
Christopher Faulet
5331093195 REGTESTS: Never reuse server connection in reg-tests/jwt/jwt_decrypt.vtc
A "Connection: close" header is added to responses to avoid any connection
reuse. This should avoid errors on the client side.
2026-04-13 15:18:47 +02:00