---
title: "3. Global Section"
linkTitle: "3. Global Section"
weight: 140
description: "Process security, performance tuning, debugging, and HTTP client settings"
icon: fa-solid fa-earth-americas
module: [HAPROXY]
categories: [Reference]
aliases:
- /haproxy/configuration/global/
- /docs/haproxy/configuration/global/
- /haproxy/global/
upstream_link: "https://docs.haproxy.org/3.4/configuration.html"
upstream_name: "HAProxy 3.4 Configuration Manual"
upstream_ref: "v3.4.4, chapter 3"
---
Parameters in the "global" section are process-wide and often OS-specific. They are generally set
once for all and do not need being changed once correct. Some of them have command-line equivalents.
The following keywords are supported in the "global" section:
- Process management and security
- 51degrees-allow-unmatched
- 51degrees-cache-size
- 51degrees-data-file
- 51degrees-difference
- 51degrees-drift
- 51degrees-property-name-list
- 51degrees-property-separator
- 51degrees-use-performance-graph
- 51degrees-use-predictive-graph
- ca-base
- chroot
- cluster-secret
- cpu-affinity
- cpu-map
- cpu-policy
- cpu-set
- crt-base
- daemon
- default-path
- description
- deviceatlas-json-file
- deviceatlas-log-level
- deviceatlas-properties-cookie
- deviceatlas-separator
- dns-accept-family
- expose-deprecated-directives
- expose-experimental-directives
- external-check
- fd-hard-limit
- gid
- grace
- group
- h1-accept-payload-with-any-method
- h1-case-adjust
- h1-case-adjust-file
- h1-do-not-close-on-insecure-transfer-encoding
- h2-workaround-bogus-websocket-clients
- hard-stop-after
- harden.reject-privileged-ports.tcp
- harden.reject-privileged-ports.quic
- insecure-fork-wanted
- insecure-setuid-wanted
- issuers-chain-path
- jwt.decrypt_alg_list
- jwt.decrypt_enc_list
- key-base
- limited-quic
- localpeer
- log
- log-send-hostname
- log-tag
- lua-load
- lua-load-per-thread
- lua-prepend-path
- max-threads-per-group
- mworker-max-reloads
- nbthread
- node
- numa-cpu-mapping
- ocsp-update.disable
- ocsp-update.maxdelay
- ocsp-update.mindelay
- ocsp-update.httpproxy
- ocsp-update.mode
- pidfile
- pp2-never-send-local
- presetenv
- prealloc-fd
- resetenv
- set-dumpable
- set-var
- setenv
- ssl-default-bind-ciphers
- ssl-default-bind-ciphersuites
- ssl-default-bind-client-sigalgs
- ssl-default-bind-curves
- ssl-default-bind-options
- ssl-default-bind-sigalgs
- ssl-default-server-ciphers
- ssl-default-server-ciphersuites
- ssl-default-server-client-sigalgs
- ssl-default-server-curves
- ssl-default-server-options
- ssl-default-server-sigalgs
- ssl-dh-param-file
- ssl-propquery
- ssl-provider
- ssl-provider-path
- ssl-security-level
- ssl-server-verify
- ssl-skip-self-issued-ca
- stats
- stats-file
- strict-limits
- uid
- ulimit-n
- unix-bind
- unsetenv
- user
- wurfl-cache-size
- wurfl-data-file
- wurfl-information-list
- wurfl-information-list-separator
- Performance tuning
- busy-polling
- max-spread-checks
- maxcompcpuusage
- maxcomprate
- maxconn
- maxconnrate
- maxpipes
- maxsessrate
- maxsslconn
- maxsslrate
- maxzlibmem
- no-memory-trimming
- noepoll
- noevports
- nogetaddrinfo
- nokqueue
- noktls
- nopoll
- noreuseport
- nosplice
- profiling.memory
- profiling.tasks
- server-state-base
- server-state-file
- spread-checks
- ssl-engine
- ssl-mode-async
- tune.applet.zero-copy-forwarding
- tune.buffers.limit
- tune.buffers.reserve
- tune.bufsize
- tune.bufsize.large
- tune.bufsize.small
- tune.cli.max-payload-size
- tune.comp.maxlevel
- tune.defaults.purge
- tune.disable-fast-forward
- tune.disable-zero-copy-forwarding
- tune.epoll.mask-events
- tune.events.max-events-at-once
- tune.fail-alloc
- tune.fd.edge-triggered
- tune.h1.be.glitches-threshold
- tune.h1.fe.glitches-threshold
- tune.h1.zero-copy-fwd-recv
- tune.h1.zero-copy-fwd-send
- tune.h2.be.glitches-threshold
- tune.h2.be.initial-window-size
- tune.h2.be.max-concurrent-streams
- tune.h2.be.max-frames-at-once
- tune.h2.be.rxbuf
- tune.h2.fe.glitches-threshold
- tune.h2.fe.initial-window-size
- tune.h2.fe.max-concurrent-streams
- tune.h2.fe.max-frames-at-once
- tune.h2.fe.max-rst-at-once
- tune.h2.fe.max-total-streams
- tune.h2.fe.rxbuf
- tune.h2.header-table-size
- tune.h2.initial-window-size
- tune.h2.max-concurrent-streams
- tune.h2.max-frame-size
- tune.h2.zero-copy-fwd-send
- tune.http.cookielen
- tune.http.logurilen
- tune.http.maxhdr
- tune.idle-pool.shared
- tune.idletimer
- tune.lua.bool-sample-conversion
- tune.lua.burst-timeout
- tune.lua.forced-yield
- tune.lua.log.loggers
- tune.lua.log.stderr
- tune.lua.maxmem
- tune.lua.openlibs
- tune.lua.service-timeout
- tune.lua.session-timeout
- tune.lua.task-timeout
- tune.max-checks-per-thread
- tune.maxaccept
- tune.maxpollevents
- tune.maxrewrite
- tune.max-rules-at-once
- tune.memory.hot-size
- tune.pattern.cache-size
- tune.peers.max-updates-at-once
- tune.pipesize
- tune.pool-high-fd-ratio
- tune.pool-low-fd-ratio
- tune.pt.zero-copy-forwarding
- tune.quic.be.cc.cubic-min-losses
- tune.quic.be.cc.hystart
- tune.quic.be.cc.max-frame-loss
- tune.quic.be.cc.max-win-size
- tune.quic.be.cc.reorder-ratio
- tune.quic.be.max-idle-timeout
- tune.quic.be.sec.glitches-threshold
- tune.quic.be.stream.data-ratio
- tune.quic.be.stream.max-concurrent
- tune.quic.be.stream.rxbuf
- tune.quic.be.tx.pacing
- tune.quic.be.tx.udp-gso
- tune.quic.cc.cubic.min-losses (deprecated)
- tune.quic.cc-hystart (deprecated)
- tune.quic.disable-tx-pacing (deprecated)
- tune.quic.disable-udp-gso (deprecated)
- tune.quic.fe.cc.cubic-min-losses
- tune.quic.fe.cc.hystart
- tune.quic.fe.cc.max-frame-loss
- tune.quic.fe.cc.max-win-size
- tune.quic.fe.cc.reorder-ratio
- tune.quic.fe.max-idle-timeout
- tune.quic.fe.sec.glitches-threshold
- tune.quic.fe.sec.retry-threshold
- tune.quic.fe.sock-per-conn
- tune.quic.fe.stream.data-ratio
- tune.quic.fe.stream.max-concurrent
- tune.quic.fe.stream.max-total
- tune.quic.fe.stream.rxbuf
- tune.quic.fe.tx.pacing
- tune.quic.fe.tx.udp-gso
- tune.quic.frontend.max-data-size (deprecated)
- tune.quic.frontend.max-idle-timeout (deprecated)
- tune.quic.frontend.max-streams-bidi (deprecated)
- tune.quic.frontend.max-tx-mem (deprecated)
- tune.quic.frontend.stream-data-ratio (deprecated)
- tune.quic.frontend.default-max-window-size (deprecated)
- tune.quic.listen
- tune.quic.max-frame-loss (deprecated)
- tune.quic.mem.tx-max
- tune.quic.reorder-ratio (deprecated)
- tune.quic.retry-threshold (deprecated)
- tune.quic.socket-owner (deprecated)
- tune.quic.zero-copy-fwd-send
- tune.renice.runtime
- tune.renice.startup
- tune.rcvbuf.backend
- tune.rcvbuf.client
- tune.rcvbuf.frontend
- tune.rcvbuf.server
- tune.recv_enough
- tune.ring.queues
- tune.runqueue-depth
- tune.sched.low-latency
- tune.sndbuf.backend
- tune.sndbuf.client
- tune.sndbuf.frontend
- tune.sndbuf.server
- tune.streams-elasticity
- tune.stick-counters
- tune.ssl.cachesize
- tune.ssl.capture-buffer-size
- tune.ssl.capture-cipherlist-size (deprecated)
- tune.ssl.certificate-compression
- tune.ssl.default-dh-param
- tune.ssl.force-private-cache
- tune.ssl.hard-maxrecord
- tune.ssl.keylog
- tune.ssl.keyupdate-rate-limit
- tune.ssl.lifetime
- tune.ssl.maxrecord
- tune.ssl.ssl-ctx-cache-size
- tune.ssl.ocsp-update.maxdelay (deprecated)
- tune.ssl.ocsp-update.mindelay (deprecated)
- tune.takeover-other-tg-connections
- tune.vars.global-max-size
- tune.vars.proc-max-size
- tune.vars.reqres-max-size
- tune.vars.sess-max-size
- tune.vars.txn-max-size
- tune.zlib.memlevel
- tune.zlib.windowsize
- Debugging
- anonkey
- debug.counters
- force-cfg-parser-pause
- quiet
- warn-blocked-traffic-after
- zero-warning
- HTTPClient
- httpclient.resolvers.disabled
- httpclient.resolvers.id
- httpclient.resolvers.prefer
- httpclient.retries
- httpclient.ssl.ca-file
- httpclient.ssl.verify
- httpclient.timeout.connect
## 3.1. Process management and security {#section-3-1}
**`51degrees-data-file `**
```haproxy
51degrees-data-file
```
The path of the 51Degrees data file to provide device detection services. The file should be
unzipped and accessible by HAProxy with relevant permissions.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES.
**`51degrees-property-name-list [ ...]`**
```haproxy
51degrees-property-name-list [ ...]
```
A list of 51Degrees property names to be load from the dataset. A full list of names is available on
the 51Degrees website:
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES.
**`51degrees-property-separator `**
```haproxy
51degrees-property-separator
```
A char that will be appended to every property value in a response header containing 51Degrees
results. If not set that will be set as ','.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES.
**`51degrees-cache-size `**
```haproxy
51degrees-cache-size
```
Sets the size of the 51Degrees converter cache to `` entries. This is an LRU cache which
reminds previous device detections and their results. By default, this cache is disabled.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES.
**`51degrees-use-performance-graph { on | off }`**
```haproxy
51degrees-use-performance-graph { on | off }
```
Enables ('on') or disables ('off') the use of the performance graph in the detection process. The
default value depends on 51Degrees library.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES and
51DEGREES_VER=4.
**`51degrees-use-predictive-graph { on | off }`**
```haproxy
51degrees-use-predictive-graph { on | off }
```
Enables ('on') or disables ('off') the use of the predictive graph in the detection process. The
default value depends on 51Degrees library.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES and
51DEGREES_VER=4.
**`51degrees-drift `**
```haproxy
51degrees-drift
```
Sets the drift value that a detection can allow.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES and
51DEGREES_VER=4.
**`51degrees-difference `**
```haproxy
51degrees-difference
```
Sets the difference value that a detection can allow.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES and
51DEGREES_VER=4.
**`51degrees-allow-unmatched { on | off }`**
```haproxy
51degrees-allow-unmatched { on | off }
```
Enables ('on') or disables ('off') the use of unmatched nodes in the detection process. The default
value depends on 51Degrees library.
Please note that this option is only available when HAProxy has been compiled with USE_51DEGREES and
51DEGREES_VER=4.
**`acme.scheduler { auto | off }`**
```haproxy
acme.scheduler { auto | off }
```
Enable or disable the ACME scheduler.
The ACME scheduler starts at HAProxy startup, it will loop over the certificates and start an ACME
renewal task when the notAfter value is past curtime + (notAfter - notBefore) / 12, or 7 days if
notBefore is not defined. The scheduler will then sleep and wakeup after 12 hours.
The default value is "auto".
See also: acme
**`ca-base `**
```haproxy
ca-base
```
Assigns a default directory to fetch SSL CA certificates and CRLs from when a relative path is used
with "ca-file", "ca-verify-file" or "crl-file" directives. Absolute locations specified in
"ca-file", "ca-verify-file" and "crl-file" prevail and ignore "ca-base".
**`chroot { | auto }`**
```haproxy
chroot { | auto }
```
Changes current directory to `` and performs a chroot() there before dropping privileges.
This increases the security level in case an unknown vulnerability would be exploited, since it
would make it very hard for the attacker to exploit the system. It is important to ensure that
`` is both empty and non-writable to anyone. When the process is started with superuser
privileges, the chroot() is performed directly. On Linux, when started unprivileged, haproxy
attempts to perform it from inside a new user namespace created with unshare(CLONE_NEWUSER); if that
mechanism is unavailable the chroot() will fail with the usual error.
As a special case, `` may be set to "auto", in which case haproxy creates an anonymous
temporary directory, unlinks it, and chroots into it. The resulting jail has no name in the
filesystem and is empty and read-only, removing the need to prepare a dedicated jail directory.
When starting with superuser privileges, a warning will be displayed if no chroot is used, in order
to encourage users to always use the mechanism. If for any reason there is a compelling reason not
to use chroot (e.g. access to a server via a UNIX socket with an unconvenient path), it remains
possible to silence the warning by adding an explicit "chroot /", which has the benefit of being
visible in a configuration.
**`close-spread-time `**
```haproxy
close-spread-time
```
Define a time window during which idle connections and active connections closing is spread in case
of soft-stop. After a SIGUSR1 is received and the grace period is over (if any), the idle
connections will all be closed at once if this option is not set, and active HTTP or HTTP2
connections will be ended after the next request is received, either by appending a "Connection:
close" line to the HTTP response, or by sending a GOAWAY frame in case of HTTP2. When this option is
set, connection closing will be spread over this set ``. If the close-spread-time is set to
"infinite", active connection closing during a soft-stop will be disabled. The "Connection: close"
header will not be added to HTTP responses (or GOAWAY for HTTP2) anymore and idle connections will
only be closed once their timeout is reached (based on the various timeouts set in the
configuration).
Arguments:
```text
is a time window (by default in milliseconds) during which
connection closing will be spread during a soft-stop operation, or
"infinite" if active connection closing should be disabled.
```
It is recommended to set this setting to a value lower than the one used in the "hard-stop-after"
option if this one is used, so that all connections have a chance to gracefully close before the
process stops.
See also: grace, hard-stop-after, idle-close-on-response
**`cluster-secret `**
```haproxy
cluster-secret
```
Define an ASCII string secret shared between several nodes belonging to the same cluster. It could
be used for different usages. It is at least used to derive stateless reset tokens for all the QUIC
connections instantiated by this process. This is also the case to derive secrets used to encrypt
Retry tokens.
If this parameter is not set, a random value will be selected on process startup. This allows to use
features which rely on it, albeit with some limitations.
**`cpu-map [auto:][/] [,...] [...]`**
```haproxy
cpu-map [auto:][/] [,...] [...]
```
On some operating systems, it is possible to bind a thread group or a thread to a specific CPU set.
This means that the designated threads will never run on other CPUs. The "cpu-map" directive
specifies CPU sets for individual threads or thread groups. The first argument is a thread group
range, optionally followed by a thread set. These ranges have the following format:
```text
all | odd | even | number[-[number]]
```
`` must be a number between 1 and 32 or 64, depending on the machine's word size. Any group
IDs above 'thread-groups' and any thread IDs above the machine's word size are ignored. All thread
numbers are relative to the group they belong to. It is possible to specify a range with two such
number delimited by a dash ('-'). It also is possible to specify all threads at once using "all",
only odd numbers using "odd" or even numbers using "even", just like with the "thread" bind
directive. The second and forthcoming arguments are CPU sets. Each CPU set is either a unique number
starting at 0 for the first CPU or a range with two such numbers delimited by a dash ('-'). These
CPU numbers and ranges may be repeated by delimiting them with commas or by passing more ranges as
new arguments on the same line. Outside of Linux and BSD operating systems, there may be a
limitation on the maximum CPU index to either 31 or 63. Multiple "cpu-map" directives may be
specified, but each "cpu-map" directive will replace the previous ones when they overlap.
Ranges can be partially defined. The higher bound can be omitted. In such case, it is replaced by
the corresponding maximum value, 32 or 64 depending on the machine's word size.
The prefix "auto:" can be added before the thread set to let HAProxy automatically bind a set of
threads to a CPU by incrementing threads and CPU sets. To be valid, both sets must have the same
size. No matter the declaration order of the CPU sets, it will be bound from the lowest to the
highest bound. Having both a group and a thread range with the "auto:" prefix is not supported. Only
one range is supported, the other one must be a fixed number.
Note that group ranges are supported for historical reasons. Nowadays, a lone number designates a
thread group and must be 1 if thread-groups are not used, and specifying a thread range or number
requires to prepend "1/" in front of it if thread groups are not used. Finally, "1" is strictly
equivalent to "1/all" and designates all threads in the group.
Examples:
```shell
cpu-map 1/all 0-3 # bind all threads of the first group on the
# first 4 CPUs
cpu-map 1/1- 0- # will be replaced by "cpu-map 1/1-64 0-63"
# or "cpu-map 1/1-32 0-31" depending on the machine's
# word size.
# all these lines bind thread 1 to the cpu 0, the thread 2 to cpu 1
# and so on.
cpu-map auto:1/1-4 0-3
cpu-map auto:1/1-4 0-1 2-3
cpu-map auto:1/1-4 3 2 1 0
cpu-map auto:1/1-4 3,2,1,0
# bind each thread to exactly one CPU using all/odd/even keyword
cpu-map auto:1/all 0-63
cpu-map auto:1/even 0-31
cpu-map auto:1/odd 32-63
# invalid cpu-map because thread and CPU sets have different sizes.
cpu-map auto:1/1-4 0 # invalid
cpu-map auto:1/1 0-3 # invalid
# map 40 threads of those 4 groups to individual CPUs
cpu-map auto:1/1-10 0-9
cpu-map auto:2/1-10 10-19
cpu-map auto:3/1-10 20-29
cpu-map auto:4/1-10 30-39
# Map 80 threads to one physical socket and 80 others to another socket
# without forcing assignment. These are split into 4 groups since no
# group may have more than 64 threads.
cpu-map 1/1-40 0-39,80-119 # node0, siblings 0 & 1
cpu-map 2/1-40 0-39,80-119
cpu-map 3/1-40 40-79,120-159 # node1, siblings 0 & 1
cpu-map 4/1-40 40-79,120-159
```
**`cpu-affinity `**
```haproxy
cpu-affinity
```
Defines how you want threads to be bound to cpus. It currently accepts the following values:
- per-core: each thread will be bound to all the hardware threads of one core.
- per-group: each thread will be bound to all the hardware threads of the group. This is the default
unless "threads-per-core 1" is used in "cpu-policy". "per-group" accepts an optional argument, to
specify how CPUs should be allocated. When a list of CPUs is larger than the maximum allowed
number of CPUs per group and has to be split between multiple groups, an extra option allows to
choose how the groups will be bound to those CPUs:
- auto: each thread group will only be assigned a fair share of contiguous CPU cores that are
dedicated to it and not shared with other groups. This is the default as it generally is more
optimal.
- loose: each group will still be allowed to use any CPU in the list. This generally causes more
contention, but may sometimes help deal better with parasitic loads running on the same CPUs.
- auto: "per-group" will be used, unless "threads-per-core 1" is used in "cpu-policy", in which case
"per-core" will be used. This is the default.
- per-thread: that will bind one thread to one hardware thread only. If "threads-per-core 1" is used
in "cpu-policy", then each thread will be bound to one hardware thread of a different core.
- per-ccx: each thread will be bound to all the hardware threads of a CCX.
**`cpu-policy [threads-per-core 1 | auto]`**
```haproxy
cpu-policy [threads-per-core 1 | auto]
```
Selects the CPU allocation policy to be used.
On multi-CPU systems, there can be plenty of reasons for not using all available CPU cores, and/or
for grouping them into different thread groups, for performance, latency, cost, or system-wide
resource management. The "cpu-set" directive already allows to evict a number of them, but once
done, it is necessary to decide how to assign the remaining ones to threads and thread groups.
This mapping is normally performed using the "cpu-map" directive, though it can be particularly
difficult to maintain on heterogeneous systems.
The "cpu-policy" directive chooses between a small number of allocation policies which one to use
instead, when "cpu-map" is not used. The following policies are currently supported, with
"performance" being the default one:
- none no particular post-selection is performed. All enabled CPUs will be usable, and if the number
of threads is not set, it will be set to the number of available CPUs but no more than 32 for
32-bit systems or 64 for 64-bit systems, per thread-group. The number of thread-groups, if not
set, will be set to 1.
- efficiency exactly like "group-by-ccx" below, except that CPU clusters composed of cores whose
performance is more than 25% above that of the next less performant one are evicted. These are
typically "big" or "performance" cores. This means that if more than one type of CPU cores are
detected, only the efficient one will be used. This can make sense for use with moderate loads
when the most powerful cores need to be available to the application or a security component. Some
modern CPUs have a large number of such efficient CPU cores which can collectively deliver a
decent level of performance while using less power.
- first-usable-node if the CPUs were not previously restricted at boot (for example using the
"taskset" utility), and if the "nbthread" directive was not set, then the first NUMA node with
enabled CPUs will be used, and this number of CPUs will be used as the number of threads. A single
thread group will be enabled with all of them, within the limit of 32 or 64 depending on the
system.
- group-by-2-ccx same as "group-by-ccx" below but create a group every two CCX. This can make sense
on CPUs having many CCX of few cores each, to avoid creating many groups, or to smooth the
distribution a little bit when not all cores are in use. Please note that it can have very bad
performance effects when the communication between CCX is slow. This is generally recommended
against.
- group-by-2-clusters same as "group-by-cluster" but create a group every two clusters. This can
make sense on CPUs having many clusters of few cores each, to avoid creating many groups, or to
smooth the distribution a little bit when not all cores are in use. Please note that it can have
very bad performance effects when the communication between clusters is slow. This is generally
recommended against.
- group-by-3-ccx same as "group-by-ccx" below but create a group every three CCX. This can make
sense on CPUs having many CCX of few cores each, to avoid creating many groups, or to smooth the
distribution a little bit when not all cores are in use. Please note that it can have very bad
performance effects when the communication between CCX is slow. This is generally recommended
against.
- group-by-3-clusters same as "group-by-cluster" but create a group every three clusters. This can
make sense on CPUs having many clusters of few cores each, to avoid creating many groups, or to
smooth the distribution a little bit when not all cores are in use. Please note that it can have
very bad performance effects when the communication between clusters is slow. This is generally
recommended against.
- group-by-4-ccx same as "group-by-ccx" below but create a group every four CCX. This can make sense
on CPUs having many CCX of few cores each, to avoid creating many groups, or to smooth the
distribution a little bit when not all cores are in use. Please note that it can have very bad
performance effects when the communication between CCX is slow. This is generally recommended
against.
- group-by-4-clusters same as "group-by-cluster" but create a group every four clusters. This can
make sense on CPUs having many clusters of few cores each, to avoid creating many groups, or to
smooth the distribution a little bit when not all cores are in use. Please note that it can have
very bad performance effects when the communication between clusters is slow. This is generally
recommended against.
- group-by-ccx if neither "nbthread" not "nbtgroups" were set, then one thread group is created for
each CPU core complex ("CCX") with available CPUs, each with as many threads as CPUs. A CCX groups
CPUs having a similarly fast access to the last level cache ("LLC"), typically the L3 cache. On
most modern machines, it is critical for performance not to mix CPUs from distant CCX in the same
thread group. All threads of a group are then bound to all CPUs of the CCX so that intra-group
communications remain local to the CCX without enforcing too strong a binding. The per-group
thread limits and thread-group limits are respected. This is recommended on multi-socket and NUMA
systems, as well as CPUs with bad inter-CCX latencies.
- group-by-cluster if neither "nbthread" not "nbtgroups" were set, then one thread group is created
for each CPU cluster with available CPUs, each with as many threads as CPUs. All threads of a
group are bound to all CPUs of the cluster so that intra-group communications remain local to the
cluster without enforcing too strong a binding. The per-group thread limits and thread-group
limits are respected. This is recommended on multi-socket and NUMA systems, as well as CPUs with
bad inter-CCX latencies. On most server machines, clusters and CCX are the same, but on
heterogeneous machines ("performance" vs "efficiency" or "big" vs "little"), a cluster will
generally be made of only a part of a CCX composed only of very similar CPUs (same type, +/-5%
frequency difference max). The difference is visible on modern laptops and desktop machines used
by developers and admins to validate setups.
- performance exactly like "group-by-ccx" above, except that CPU clusters composed of cores whose
performance is less than 80% of those of the next more performant one are evicted. These are
typically "little" or "efficient" cores, whose addition generally doesn't bring significant gains
and can easily be counter-productive (e.g. TLS handshakes). Often, keeping such cores for other
tasks such as network handling is much more effective. On development systems, these can also be
used to run auxiliary tools such as load generators and monitoring tools. This is the default
policy.
- resource this is like "group-by-cluster" above, except that only the smallest and most efficient
CPU cluster will be used, while all other ones will be ignored. This can be used to limit the
resource usage to the strict minimum that still delivers decent performance, for example to try to
further reduce power consumption or minimize the number of cores needed on some rented systems for
a sidecar setup, in order to scale the system down more easily. Note that if a single cluster is
present, it will still be fully used.
An optional keyword can be added, "threads-per-core". It can accept two values, "1" and "auto". If
set to 1, then only one thread per core will be created, unrespective of how many hardware threads
the core has. If set to auto, then one thread per hardware thread will be created. If no affinity is
specified, and threads-per-core 1 is used, then by default the affinity will be per-core.
See also: "cpu-map", "cpu-set", "nbthread"
**`cpu-set ...`**
```haproxy
cpu-set ...
```
Allows to symbolically describe what sets of CPUs to run on. The directive supports the following
keyword: - reset this undoes any previous limitation that could have been inherited by a service
manager or a "taskset" command for example. - drop-cpu `` do not bind to CPUs in this set -
only-cpu `` do not bind to CPUs not in this set - drop-node `` do not bind to CPUs
belonging to this NUMA node - only-node `` do not bind to CPUs not belonging to this NUMA
node - drop-cluster `` do not bind to CPUs on this hardware cluster number - only-cluster
`` do not bind to CPUs on other hardware cluster number - drop-core `` do not bind to CPUs
on this hardware core number - only-core `` do not bind to CPUs on other hardware core number -
drop-thread `` do not bind to CPUs on this hardware thread number - only-thread `` do not
bind to CPUs on other hardware thread number See also: "cpu-policy"
**`crt-base `**
```haproxy
crt-base
```
Assigns a default directory to fetch SSL certificates from when a relative path is used with
"crtfile" or "crt" directives. Absolute locations specified prevail and ignore "crt-base".
**`daemon`**
```haproxy
daemon
```
Makes the process fork into background. This is the recommended mode of operation. It is equivalent
to the command line "-D" argument. It can be disabled by the command line "-db" argument. This
option is ignored in systemd mode.
**`default-path { current | config | parent | origin }`**
```haproxy
default-path { current | config | parent | origin }
```
By default HAProxy loads all files designated by a relative path from the location the process is
started in. In some circumstances it might be desirable to force all relative paths to start from a
different location just as if the process was started from such locations. This is what this
directive is made for. Technically it will perform a temporary chdir() to the designated location
while processing each configuration file, and will return to the original directory after processing
each file. It takes an argument indicating the policy to use when loading files whose path does not
start with a slash ('/'): - "current" indicates that all relative files are to be loaded from the
directory the process is started in; this is the default.
- "config" indicates that all relative files should be loaded from the
directory containing the configuration file. More specifically, if the
configuration file contains a slash ('/'), the longest part up to the
last slash is used as the directory to change to, otherwise the current
directory is used. This mode is convenient to bundle maps, errorfiles,
certificates and Lua scripts together as relocatable packages. When
multiple configuration files are loaded, the directory is updated for
each of them.
- "parent" indicates that all relative files should be loaded from the
parent of the directory containing the configuration file. More
specifically, if the configuration file contains a slash ('/'), ".."
is appended to the longest part up to the last slash is used as the
directory to change to, otherwise the directory is "..". This mode is
convenient to bundle maps, errorfiles, certificates and Lua scripts
together as relocatable packages, but where each part is located in a
different subdirectory (e.g. "config/", "certs/", "maps/", ...).
- "origin" indicates that all relative files should be loaded from the
designated (mandatory) path. This may be used to ease management of
different HAProxy instances running in parallel on a system, where each
instance uses a different prefix but where the rest of the sections are
made easily relocatable.
Each "default-path" directive instantly replaces any previous one and will possibly result in
switching to a different directory. While this should always result in the desired behavior, it is
really not a good practice to use multiple default-path directives, and if used, the policy ought to
remain consistent across all configuration files.
Warning: some configuration elements such as maps or certificates are uniquely identified by their
configured path. By using a relocatable layout, it becomes possible for several of them to end up
with the same unique name, making it difficult to update them at run time, especially when multiple
configuration files are loaded from different directories. It is essential to observe a strict
collision-free file naming scheme before adopting relative paths. A robust approach could consist in
prefixing all files names with their respective site name, or in doing so at the directory level.
**`description `**
```haproxy
description
```
Add a text that describes the instance.
Please note that it is required to escape certain characters (# for example) and this text is
inserted into a html page so you should avoid using "\<" and "\>" characters.
**`deviceatlas-json-file `**
```haproxy
deviceatlas-json-file
```
Sets the path of the DeviceAtlas JSON data file to be loaded by the API. The path must be a valid
JSON data file and accessible by HAProxy process.
**`deviceatlas-log-level `**
```haproxy
deviceatlas-log-level
```
Sets the level of information returned by the API. This directive is optional and set to 0 by
default if not set.
**`deviceatlas-properties-cookie `**
```haproxy
deviceatlas-properties-cookie
```
Sets the client cookie's name used for the detection if the DeviceAtlas Client-side component was
used during the request. This directive is optional and set to DAPROPS by default if not set.
**`deviceatlas-separator `**
```haproxy
deviceatlas-separator
```
Sets the character separator for the API properties results. This directive is optional and set to
\| by default if not set.
**`dns-accept-family [,...]`**
```haproxy
dns-accept-family [,...]
```
By default, DNS resolvers accept both IPv4 and IPv6 addresses. This can be influenced by the
"resolve-prefer" keywords on server lines as well as the family argument to the "do-resolve" action,
but that is only a preference, which does not block the other family from being used when it's
alone. In some environments where dual-stack is not usable, stumbling on an unreachable IPv6-only
DNS record can cause significant trouble as it will replace a previous IPv4 one which would possibly
have continued to work till next request. The "dns-accept-family" global option permits to enforce
usage of only one (or both) address families. The argument is a comma-delimited list of the
following words: - "ipv4": query and accept IPv4 addresses ("A" records) - "ipv6": query and accept
IPv6 addresses ("AAAA" records) - "auto": use IPv4, and IPv6 if the system has a default gateway for
it. The result of the last check is cached for 30 seconds.
When a single family is used, no request will be sent to resolvers for the other family, and any
response for the other family will be ignored. The default value since 3.3 is "auto", which
effectively enables both families only once IPv6 has been proven to be routable, otherwise sticks to
IPv4. See also: "resolve-prefer", "do-resolve"
**`expose-deprecated-directives`**
```haproxy
expose-deprecated-directives
```
This statement must appear before using some directives tagged as deprecated to silent warnings and
make sure the config file will not be rejected. Not all deprecated directives are concerned, only
those without any alternative solution.
**`expose-experimental-directives`**
```haproxy
expose-experimental-directives
```
This statement must appear before using directives tagged as experimental or the config file will be
rejected. Please note that features covered by this option are not guaranteed to work well and may
break during the maintenance cycle. Developers will maintain them in best effort mode while the next
version is being worked on, and will deploy any reasonable effort to avoid breaking them but with no
guarantee. For these reasons, these features are not expected to be supported beyond the release of
the next LTS release. Users who want to try experimental features are expected to upgrade quickly to
benefit from the improvements made to that feature. In order to know if this directive is still
needed, it's easy: if it is enabled without being used by any such feature, a warning will be
emitted suggesting to turn it off. So without any warning, it means it's still needed.
**`external-check [preserve-env]`**
```haproxy
external-check [preserve-env]
```
Allows the use of an external agent to perform health checks. This is disabled by default as a
security precaution, and even when enabled, checks may still fail unless "insecure-fork-wanted" is
enabled as well. If the program launched makes use of a setuid executable (it should really not),
you may also need to set "insecure-setuid-wanted" in the global section. By default, the checks
start with a clean environment which only contains variables defined in the "external-check" command
in the backend section. It may sometimes be desirable to preserve the environment though, for
example when complex scripts retrieve their extra paths or information there. This can be done by
appending the "preserve-env" keyword. In this case however it is strongly advised not to run a
setuid nor as a privileged user, as this exposes the check program to potential attacks. See "option
external-check", and "insecure-fork-wanted", and "insecure-setuid-wanted" for extra details.
**`fd-hard-limit `**
```haproxy
fd-hard-limit
```
Sets an upper bound to the maximum number of file descriptors that the process will use, regardless
of system limits. While "ulimit-n" and "maxconn" may be used to enforce a value, when they are not
set, the process will be limited to the hard limit of the RLIMIT_NOFILE setting as reported by
"ulimit -n -H". But some modern operating systems are now allowing extremely large values here (in
the order of 1 billion), which will consume way too much RAM for regular usage. The fd-hard-limit
setting is provided to enforce a possibly lower bound to this limit. This means that it will always
respect the system-imposed limits when they are below `` but the specified value will be
used if system-imposed limits are higher. By default fd-hard-limit is set to 1048576. This default
could be changed via DEFAULT_MAXFD compile-time variable, that could serve as the maximum (kernel)
system limit, if RLIMIT_NOFILE hard limit is extremely large. fd-hard-limit set in global section
allows to temporarily override the value provided via DEFAULT_MAXFD at the build-time. In the
example below, no other setting is specified and the maxconn value will automatically adapt to the
lower of "fd-hard-limit" and the RLIMIT_NOFILE limit:
```text
global
# use as many FDs as possible but no more than 50000
fd-hard-limit 50000
```
See also: ulimit-n, maxconn
**`gid `**
```haproxy
gid
```
Changes the process's group ID to ``. It is recommended that the group ID is dedicated to
HAProxy or to a small set of similar daemons. HAProxy must be started with a user belonging to this
group, or with superuser privileges. Note that if HAProxy is started from a user having
supplementary groups, it will only be able to drop these groups if started with superuser
privileges. See also "group" and "uid".
**`grace `**
```haproxy
grace
```
Defines a delay between SIGUSR1 and real soft-stop.
Arguments:
```text
is an extra delay (by default in milliseconds) after receipt of the
SIGUSR1 signal that will be waited for before proceeding with the
soft-stop operation.
```
This is used for compatibility with legacy environments where the haproxy process needs to be
stopped but some external components need to detect the status before listeners are unbound. The
principle is that the internal "stopping" variable (which is reported by the "stopping" sample fetch
function) will be turned to true, but listeners will continue to accept connections undisturbed,
until the delay expires, after what the regular soft-stop will proceed. This must not be used with
processes that are reloaded, or this will prevent the old process from unbinding, and may prevent
the new one from starting, or simply cause trouble.
Example:
```shell
global
grace 10s
# Returns 200 OK until stopping is set via SIGUSR1
frontend ext-check
bind:9999
monitor-uri /ext-check
monitor fail if { stopping }
```
Please note that a more flexible and durable approach would instead consist for an orchestration
system in setting a global variable from the CLI, use that variable to respond to external checks,
then after a delay send the SIGUSR1 signal.
Example:
```shell
# Returns 200 OK until proc.stopping is set to non-zero. May be done
# from HTTP using set-var(proc.stopping) or from the CLI using:
# > set var proc.stopping int(1)
frontend ext-check
bind:9999
monitor-uri /ext-check
monitor fail if { var(proc.stopping) -m int gt 0 }
```
See also: hard-stop-after, monitor
**`group `**
```haproxy
group
```
Similar to "gid" but uses the GID of group name `` from /etc/group. See also "gid" and
"user".
**`h1-accept-payload-with-any-method`**
```haproxy
h1-accept-payload-with-any-method
```
Does not reject HTTP/1.0 GET/HEAD/DELETE requests with a payload with a 413 Payload Too Large HTTP
response.
While It is explicitly allowed in HTTP/1.1, HTTP/1.0 is not clear on this point and some old servers
don't expect any payload and never look for body length (via Content-Length or Transfer-Encoding
headers). It means that some intermediaries may properly handle the payload for HTTP/1.0
GET/HEAD/DELETE requests, while some others may totally ignore it. That may lead to security issues
because a request smuggling attack is possible. Thus, by default, HAProxy rejects HTTP/1.0
GET/HEAD/DELETE requests with a payload.
However, it may be an issue with some old clients. In this case, this global option may be set.
**`h1-do-not-close-on-insecure-transfer-encoding`**
```haproxy
h1-do-not-close-on-insecure-transfer-encoding
```
As mandated by the HTTP/1.1 specification (RFC9112#6.1), the presence of both a Transfer-Encoding
header field and a Content-Length header field in the same message represents a serious risk of
conveying a content smuggling attack if there are any HTTP/1.0 agent anywhere in the upstream of
downstream chain, and when facing this, an agent must absolutely close the connection after the
response so as to prevent any exploitation. But this may have a performance impact on some very old
clients, especially if they need to renegotiate a TLS connection for every request. This option is
present to ask HAProxy not to enforce this rule, and to just sanitize the message but leave the
connection alive after the response. This may only be done when absolutely certain that no HTTP/1.0
agents are present in the chain and that all implementations before HAProxy are fully HTTP/1.1
compliant regarding the rules that apply to these header fields. In any case, HAProxy will continue
to ignore and drop the extraneous Content-Length header so as not to confuse the next hop.
When enabling this option to work around an old broken client or server, it is important to
understand that regardless of the need or not for this option, such an agent violating this rule
faces a risk to see its messages truncated by old agents that would consider Content-Length and
ignore Transfer-Encoding, since the cumulated size of the encoded chunk sizes are not being
accounted for. As such, the rule above is not just a matter of security but also of taking care of
getting rid of agents that may face communication trouble due to incompatibilities with older ones.
**`h1-case-adjust `**
```haproxy
h1-case-adjust
```
Defines the case adjustment to apply, when enabled, to the header name ``, to change it to
`` before sending it to HTTP/1 clients or servers. `` must be in lower case, and ``
and `` must not differ except for their case. It may be repeated if several header names need to
be adjusted. Duplicate entries are not allowed. If a lot of header names have to be adjusted, it
might be more convenient to use "h1-case-adjust-file". Please note that no transformation will be
applied unless "option h1-case-adjust-bogus-client" or "option h1-case-adjust-bogus-server" is
specified in a proxy.
There is no standard case for header names because, as stated in RFC7230, they are case-insensitive.
So applications must handle them in a case-insensitive manner. But some bogus applications violate
the standards and erroneously rely on the cases most commonly used by browsers. This problem becomes
critical with HTTP/2 because all header names must be exchanged in lower case, and HAProxy follows
the same convention. All header names are sent in lower case to clients and servers, regardless of
the HTTP version.
Applications which fail to properly process requests or responses may require to temporarily use
such workarounds to adjust header names sent to them for the time it takes the application to be
fixed. Please note that an application which requires such workarounds might be vulnerable to
content smuggling attacks and must absolutely be fixed.
Example:
```text
global
h1-case-adjust content-length Content-Length
```
See "h1-case-adjust-file", "option h1-case-adjust-bogus-client" and "option
h1-case-adjust-bogus-server".
**`h1-case-adjust-file `**
```haproxy
h1-case-adjust-file
```
Defines a file containing a list of key/value pairs used to adjust the case of some header names
before sending them to HTTP/1 clients or servers. The file `` must contain 2 header names
per line. The first one must be in lower case and both must not differ except for their case. Lines
which start with '#' are ignored, just like empty lines. Leading and trailing tabs and spaces are
stripped. Duplicate entries are not allowed. Please note that no transformation will be applied
unless "option h1-case-adjust-bogus-client" or "option h1-case-adjust-bogus-server" is specified in
a proxy.
If this directive is repeated, only the last one will be processed. It is an alternative to the
directive "h1-case-adjust" if a lot of header names need to be adjusted. Please read the risks
associated with using this.
See "h1-case-adjust", "option h1-case-adjust-bogus-client" and "option h1-case-adjust-bogus-server".
**`h2-workaround-bogus-websocket-clients`**
```haproxy
h2-workaround-bogus-websocket-clients
```
This disables the announcement of the support for h2 websockets to clients. This can be use to
overcome clients which have issues when implementing the relatively fresh RFC8441, such as Firefox
88. To allow clients to automatically downgrade to http/1.1 for the websocket tunnel, specify h2
support on the bind line using "alpn" without an explicit "proto" keyword. If this statement was
previously activated, this can be disabled by prefixing the keyword with "no".
**`hard-stop-after `**
```haproxy
hard-stop-after
```
Defines the maximum time allowed to perform a clean soft-stop.
Arguments:
```text
is the maximum time (by default in milliseconds) for which the
instance will remain alive when a soft-stop is received via the
SIGUSR1 signal.
```
This may be used to ensure that the instance will quit even if connections remain opened during a
soft-stop (for example with long timeouts for a proxy in tcp mode). It applies both in TCP and HTTP
mode.
Example:
```text
global
hard-stop-after 30s
```
See also: grace
**`harden.reject-privileged-ports.tcp { on | off }`**
```haproxy
harden.reject-privileged-ports.tcp { on | off }
harden.reject-privileged-ports.quic { on | off }
```
Toggle per protocol protection which forbid communication with clients which use privileged ports as
their source port. This range of ports is defined according to RFC 6335. By default, protection is
active for QUIC protocol as this behavior is suspicious and may be used as a spoofing or DNS/NTP
amplification attack.
**`http-err-codes [+-][,...] [...]`**
```haproxy
http-err-codes [+-][,...] [...]
```
Replace, reduce or extend the list of status codes that define an error as considered by the
termination codes and the "http_err_cnt" counter in stick tables. The default range for errors is
400 to 499, but in certain contexts some users prefer to exclude specific codes, especially when
tracking client errors (e.g. 404 on systems with dynamically generated contents). See also
"http-fail-codes" and "http_err_cnt".
A range specified without '+' nor '-' redefines the existing range to the new one. A range starting
with '+' extends the existing range to also include the specified one, which may or may not overlap
with the existing one. A range starting with '-' removes the specified range from the existing one.
A range consists in a number from 100 to 599, optionally followed by "-" followed by another number
greater than or equal to the first one to indicate the high boundary of the range. Multiple ranges
may be delimited by commas for a same add/del/ replace operation.
Example:
```text
http-err-codes 400,402-444,446-480,490 # sets exactly these codes
http-err-codes 400-499 -450 +500 # sets 400 to 500 except 450
http-err-codes -450-459 # removes 450 to 459 from range
http-err-codes +501,505 # adds 501 and 505 to range
```
**`http-fail-codes [+-][,...] [...]`**
```haproxy
http-fail-codes [+-][,...] [...]
```
Replace, reduce or extend the list of status codes that define a failure as considered by the
termination codes and the "http_fail_cnt" counter in stick tables. The default range for failures is
500 to 599 except 501 and 505 which can be triggered by clients, and normally indicate a failure
from the server to process the request. Some users prefer to exclude certain codes in certain
contexts where it is known they're not relevant, such as 500 in certain SOAP environments as it
doesn't translate a server fault there. The syntax is exactly the same as for http-err-codes above.
See also "http-err-codes" and "http_fail_cnt".
**`insecure-fork-wanted`**
```haproxy
insecure-fork-wanted
```
By default HAProxy tries hard to prevent any thread and process creation after it starts. Doing so
is particularly important when using Lua files of uncertain origin, and when experimenting with
development versions which may still contain bugs whose exploitability is uncertain. And generally
speaking it's good hygiene to make sure that no unexpected background activity can be triggered by
traffic. But this prevents external checks from working, and may break some very specific Lua
scripts which actively rely on the ability to fork. This option is there to disable this protection.
Note that it is a bad idea to disable it, as a vulnerability in a library or within HAProxy itself
will be easier to exploit once disabled. In addition, forking from Lua or anywhere else is not
reliable as the forked process may randomly embed a lock set by another thread and never manage to
finish an operation. As such it is highly recommended that this option is never used and that any
workload requiring such a fork be reconsidered and moved to a safer solution (such as agents instead
of external checks). This option supports the "no" prefix to disable it. This can also be activated
with "-dI" on the haproxy command line.
**`insecure-setuid-wanted`**
```haproxy
insecure-setuid-wanted
```
HAProxy doesn't need to call executables at run time (except when using external checks which are
strongly recommended against), and is even expected to isolate itself into an empty chroot. As such,
there basically is no valid reason to allow a setuid executable to be called without the user being
fully aware of the risks. In a situation where HAProxy would need to call external checks and/or
disable chroot, exploiting a vulnerability in a library or in HAProxy itself could lead to the
execution of an external program. On Linux it is possible to lock the process so that any setuid bit
present on such an executable is ignored. This significantly reduces the risk of privilege
escalation in such a situation. This is what HAProxy does by default. In case this causes a problem
to an external check (for example one which would need the "ping" command), then it is possible to
disable this protection by explicitly adding this directive in the global section. If enabled, it is
possible to turn it back off by prefixing it with the "no" keyword.
**`issuers-chain-path `**
```haproxy
issuers-chain-path
```
Assigns a directory to load certificate chain for issuer completion. All files must be in PEM
format. For certificates loaded with "crt" or "crt-list", if certificate chain is not included in
PEM (also commonly known as intermediate certificate), HAProxy will complete chain if the issuer of
the certificate corresponds to the first certificate of the chain loaded with "issuers-chain-path".
A "crt" file with PrivateKey+Certificate+IntermediateCA2+IntermediateCA1 could be replaced with
PrivateKey+Certificate. HAProxy will complete the chain if a file with
IntermediateCA2+IntermediateCA1 is present in "issuers-chain-path" directory. All other certificates
with the same issuer will share the chain in memory.
The OCSP features are able to use the completed chain when no .issuer was used, or no chain was
provided in the PEM.
**`jwt.decrypt_alg_list `**
```haproxy
jwt.decrypt_alg_list
```
Set the list of algorithms allowed in the jwt_decrypt_XXX converters. JWT tokens using an
unsupported or disabled algorithms will never be decrypted. The specified algorithms must have the
same format as in [section 4.1](/docs/haproxy/proxies/#section-4-1) of RFC7518 and must be colon-separated. The special "ALL" name can be
used to enable all the supported algorithms (see "jwt_decrypt_jwk" converter for a complete list)
and a '!' can be appended to an algorithm name to explicitly disable it. Please note that unless
"ALL" is specified, using this option will disable any algorithm that is not explicitly mentioned in
the provided list.
Examples:
```shell
# Enable all algorithms but the "ECDH-ES" one
jwt.decrypt_alg_list ALL:!ECDH-ES
# Only enable ECDH-ES algorithms
jwt.decrypt_alg_list ECDH-ES:ECDH-ES+A128KW:ECDH-ES+A192KW:ECDH-ES+A256KW
```
**`jwt.decrypt_enc_list `**
```haproxy
jwt.decrypt_enc_list
```
Set the list of encryption algorithms allowed in the jwt_decrypt_XXX converters. JWT tokens using an
unsupported or disabled encryption algorithms will never be decrypted. The specified algorithms must
have the same format as in [section 5.1](/docs/haproxy/bind-and-server-options/#section-5-1) of RFC7518 and must be colon-separated. The special "ALL"
name can be used to enable all the supported algorithms (see "jwt_decrypt_jwk" converter for a
complete list) and a '!' can be appended to an algorithm name to explicitly disable it. Please note
that unless "ALL" is specified, using this option will disable any algorithm that is not explicitly
mentioned in the provided list.
Examples:
```shell
# Enable only AES GCM encrypting algorithms
jwt.decrypt_enc_list A128GCM:A192GCM:A256GCM
```
**`key-base `**
```haproxy
key-base
```
Assigns a default directory to fetch SSL private keys from when a relative path is used with "key"
directives. Absolute locations specified prevail and ignore "key-base". This option only works with
a crt-store load line.
**`limited-quic`**
```haproxy
limited-quic
```
This setting must be used to explicitly enable the QUIC listener bindings when haproxy is compiled
with a version of OpenSSL without QUIC support. It activates an haproxy internal compatibility layer
which must have been selected at build time with USE_QUIC_OPENSSL_COMPAT=1. This compatibility layer
supports most of the necessary TLS operations, albeit without QUIC 0-RTT capability.
This feature is primarily targeted for OpenSSL prior to version 3.5.2, where QUIC API was not
implemented or only partially. The compatibility layer can still be activated for version 3.5.2 and
above, but this is probably unnecessary.
If limited-quic is set but the compatibility layer was not selected at build time, the option is
silently ignored and QUIC TLS operations rely on the TLS library.
**`localpeer `**
```haproxy
localpeer
```
Sets the local instance's peer name. It will be ignored if the "-L" command line argument is
specified or if used after "peers" section definitions. In such cases, a warning message will be
emitted during the configuration parsing.
This option will also set the HAPROXY_LOCALPEER environment variable. See also "-L" in the
management guide and "peers" section below.
**`log [len ] [format ] [sample :]`**
```haproxy
log [len ] [format ] [sample :]
[profile ] [max level [min level]]
```
Adds a global syslog server. Several global servers can be defined. They will receive logs for
starts and exits, as well as all logs from proxies configured with "log global". See "log" option
for proxies for more details.
**`log-send-hostname []`**
```haproxy
log-send-hostname []
```
Sets the hostname field in the syslog header. If optional "string" parameter is set the header is
set to the string contents, otherwise uses the hostname of the system. Generally used if one is not
relaying logs through an intermediate syslog server or for simply customizing the hostname printed
in the logs.
**`log-tag `**
```haproxy
log-tag
```
Sets the tag field in the syslog header to this string. It defaults to the program name as launched
from the command line, which usually is "haproxy". Sometimes it can be useful to differentiate
between multiple processes running on the same host. See also the per-proxy "log-tag" directive.
**`lua-load [ [ [ ... ] ] ]`**
```haproxy
lua-load [ [ [ ... ] ] ]
```
This global directive loads and executes a Lua file in the shared context that is visible to all
threads. Any variable set in such a context is visible from any thread. This is the easiest and
recommended way to load Lua programs but it will not scale well if a lot of Lua calls are performed,
as only one thread may be running on the global state at a time. A program loaded this way will
always see 0 in the "core.thread" variable. This directive can be used multiple times.
args are available in the lua file using the code below in the body of the file. Do not forget that
Lua arrays start at index 1. A "local" variable declared in a file is available in the entire file
and not available on other files.
local args = table.pack(...)
**`lua-load-per-thread [ [ [ ... ] ] ]`**
```haproxy
lua-load-per-thread [ [ [ ... ] ] ]
```
This global directive loads and executes a Lua file into each started thread. Any global variable
has a thread-local visibility so that each thread could see a different value. As such it is
strongly recommended not to use global variables in programs loaded this way. An independent copy is
loaded and initialized for each thread, everything is done sequentially and in the thread's numeric
order from 1 to nbthread. If some operations need to be performed only once, the program should
check the "core.thread" variable to figure what thread is being initialized. Programs loaded this
way will run concurrently on all threads and will be highly scalable. This is the recommended way to
load simple functions that register sample-fetches, converters, actions or services once it is
certain the program doesn't depend on global variables. For the sake of simplicity, the directive is
available even if only one thread is used and even if threads are disabled (in which case it will be
equivalent to lua-load). This directive can be used multiple times.
See lua-load for usage of args.
**`lua-prepend-path []`**
```haproxy
lua-prepend-path []
```
Prepends the given string followed by a semicolon to Lua's package.`` variable. `` must
either be "path" or "cpath". If `` is not given it defaults to "path".
Lua's paths are semicolon delimited lists of patterns that specify how the `require` function
attempts to find the source file of a library. Question marks (?) within a pattern will be replaced
by module name. The path is evaluated left to right. This implies that paths that are prepended
later will be checked earlier.
As an example by specifying the following path:
```text
lua-prepend-path /usr/share/haproxy-lua/?/init.lua
lua-prepend-path /usr/share/haproxy-lua/?.lua
```
When `require "example"` is being called Lua will first attempt to load the
/usr/share/haproxy-lua/example.lua script, if that does not exist the
/usr/share/haproxy-lua/example/init.lua will be attempted and the default paths if that does not
exist either.
See for the details within the Lua documentation.
**`master-worker (deprecated)`**
```haproxy
master-worker (deprecated)
```
Master-worker mode. It is equivalent to the command line "-W" argument.
This keyword is deprecated, please start in master-worker mode using "-W" or "-Ws".
This mode will launch a "master" which will fork a "worker" after reading the configuration to
process the traffic. The master is used as a process manager which will monitor the "workers".
Using this mode, you can reload HAProxy directly by sending a SIGUSR2 signal to the master.
Reloading will ask the master to read the configuration again and fork a new worker. The previous
worker will be kept until the end of its jobs.
The master-worker mode is compatible either with the foreground or daemon mode.
By default, if a worker exits with a bad return code, in the case of a segfault for example, all
workers will be killed, and the master will leave. It is convenient to combine this behavior with
Restart=on-failure in a systemd unit file in order to relaunch the whole process. If you don't want
this behavior, you must use the keyword "no-exit-on-failure".
See also "-W" in the management guide.
**`master-worker no-exit-on-failure`**
```haproxy
master-worker no-exit-on-failure
```
In master-worker mode, by default, if a worker exits with a bad return code, in the case of a
segfault for example, all workers will be killed, and the master will leave. It is convenient to
combine this behavior with Restart=on-failure in a systemd unit file in order to relaunch the whole
process.
This keyword allows to keep the remaining processes alive when a worker crashed instead of killing
everything. This need to be used with caution as it is only meant for debugging and could put the
master process in an abnormal state.
**`max-threads-per-group `**
```haproxy
max-threads-per-group
```
Defines the maximum number of threads in a thread group. Unless the number of thread groups is fixed
with the "thread-groups" directive, haproxy will create as many thread groups as needed to satisfy
the requested number of threads. The minimum value is 1, and the maximum value is 64 (on 64-bit
systems, or 32 on 32-bit systems). Lower values reduce contention caused by atomic operations on
shared states, but can increase the number of sockets needed to create all listeners and to hold
idle backend connections. Higher values will reduce these costs, at the expense of higher CPU usage
under contented situations, and lower connection rates. The default value is 16, which provides the
best tradeoff that was experimentally found on various tested systems, including x86_64 processors
from multiple vendors, and large Arm64 systems, both on bare metal and hypervisors.
**`mworker-max-reloads `**
```haproxy
mworker-max-reloads
```
In master-worker mode, this option limits the number of time a worker can survive to a reload. If
the worker did not leave after a reload, once its number of reloads is greater than this number, the
worker will receive a SIGTERM. This option helps to keep under control the number of workers. See
also "show proc" in the Management Guide.
By default this value is set to 50.
**`nbthread `**
```haproxy
nbthread
```
This setting is only available when support for threads was built in. It makes HAProxy run on
`` threads. "nbthread" also works when HAProxy is started in foreground. On some platforms
supporting CPU affinity, the default "nbthread" value is automatically set to the number of CPUs the
process is bound to upon startup. This means that the thread count can easily be adjusted from the
calling process using commands like "taskset" or "cpuset". Otherwise, this value defaults to 1. The
default value is reported in the output of "haproxy -vv". Note that values set here or automatically
detected are subject to the limit set by "thread-hard-limit" (if set).
**`numa-cpu-mapping`**
```haproxy
numa-cpu-mapping
```
When running on a NUMA-aware platform, this enables the "cpu-policy" directive to inspect the
topology and figure the best set of CPUs to use and the corresponding number of threads. However, if
the applied binding is non optimal on a particular architecture, it can be disabled with the
statement 'no numa-cpu-mapping'. This automatic binding is also not applied if a 'nbthread'
statement is present in the configuration, if the affinity of the process is already specified, for
example via the 'cpu-map' directive or the taskset utility, or if the cpu-policy is set to any other
value. See also "cpu-map", "cpu-policy", "cpu-set".
**`ocsp-update.disable [ on | off ]`**
```haproxy
ocsp-update.disable [ on | off ]
```
Disable completely the ocsp-update in HAProxy. Any ocsp-update configuration will be ignored.
Default is "off". See option "ocsp-update" for more information about the auto update mechanism.
**`ocsp-update.httpproxy [:port]`**
```haproxy
ocsp-update.httpproxy [:port]
```
Allow to use an HTTP proxy for the OCSP updates. This only works with HTTP, HTTPS is not supported.
This option will allow the OCSP updater to send absolute URI in the request to the proxy.
**`ocsp-update.maxdelay `**
```haproxy
ocsp-update.maxdelay
tune.ssl.ocsp-update.maxdelay (deprecated)
```
Sets the maximum interval between two automatic updates of the same OCSP response. This time is
expressed in seconds and defaults to 3600 (1 hour). It must be set to a higher value than
"ocsp-update.mindelay". See option "ocsp-update" for more information about the auto update
mechanism.
**`ocsp-update.mindelay `**
```haproxy
ocsp-update.mindelay
tune.ssl.ocsp-update.mindelay (deprecated)
```
Sets the minimum interval between two automatic updates of the same OCSP response. This time is
expressed in seconds and defaults to 300 (5 minutes). It is particularly useful for OCSP response
that do not have explicit expiration times. It must be set to a lower value than
"ocsp-update.maxdelay". See option "ocsp-update" for more information about the auto update
mechanism.
**`ocsp-update.mode [ on | off ]`**
```haproxy
ocsp-update.mode [ on | off ]
```
Sets the default ocsp-update mode for all certificates used in the configuration. This global option
can be superseded by the crt-list "ocsp-update" option. This option is set to "off" by default. See
option "ocsp-update" for more information about the auto update mechanism.
**`pidfile `**
```haproxy
pidfile
```
Writes PIDs of all daemons into file `` when daemon mode or writes PID of master process
into file `` when master-worker mode. This option is equivalent to the "-p" command line
argument. The file must be accessible to the user starting the process. See also "daemon" and
"master-worker".
**`pp2-never-send-local`**
```haproxy
pp2-never-send-local
```
A bug in the PROXY protocol v2 implementation was present in HAProxy up to version 2.1, causing it
to emit a PROXY command instead of a LOCAL command for health checks. This is particularly minor but
confuses some servers' logs. Sadly, the bug was discovered very late and revealed that some servers
which possibly only tested their PROXY protocol implementation against HAProxy fail to properly
handle the LOCAL command, and permanently remain in the "down" state when HAProxy checks them. When
this happens, it is possible to enable this global option to revert to the older (bogus) behavior
for the time it takes to contact the affected components' vendors and get them fixed. This option is
disabled by default and acts on all servers having the "send-proxy-v2" statement.
**`presetenv `**
```haproxy
presetenv
```
Sets environment variable `` to value ``. If the variable exists, it is NOT
overwritten. The changes immediately take effect so that the next line in the configuration file
sees the new value. See also "setenv", "resetenv", and "unsetenv".
**`prealloc-fd`**
```haproxy
prealloc-fd
```
Performs a one-time open of the maximum file descriptor which results in a pre-allocation of the
kernel's data structures. This prevents short pauses when nbthread\>1 and HAProxy opens a file
descriptor which requires the kernel to expand its data structures.
**`resetenv [ ...]`**
```haproxy
resetenv [ ...]
```
Removes all environment variables except the ones specified in argument. It allows to use a clean
controlled environment before setting new values with setenv or unsetenv. Please note that some
internal functions may make use of some environment variables, such as time manipulation functions,
but also OpenSSL or even external checks. This must be used with extreme care and only after
complete validation. The changes immediately take effect so that the next line in the configuration
file sees the new environment. See also "setenv", "presetenv", and "unsetenv".
**`server-state-base `**
```haproxy
server-state-base
```
Specifies the directory prefix to be prepended in front of all servers state file names which do not
start with a '/'. See also "server-state-file", "load-server-state-from-file" and
"server-state-file-name".
**`server-state-file `**
```haproxy
server-state-file
```
Specifies the path to the file containing state of servers. If the path starts with a slash ('/'),
it is considered absolute, otherwise it is considered relative to the directory specified using
"server-state-base" (if set) or to the current directory. Before reloading HAProxy, it is possible
to save the servers' current state using the stats command "show servers state". The output of this
command must be written in the file pointed by ``. When starting up, before handling traffic,
HAProxy will read, load and apply state for each server found in the file and available in its
current running configuration. See also "server-state-base" and "show servers state",
"load-server-state-from-file" and "server-state-file-name"
**`set-dumpable [ on | off | libs ]`**
```haproxy
set-dumpable [ on | off | libs ]
```
This option helps choose the core dump behavior in case of process crash. Available options are:
- on this enables core dumping at the process level if it was previously disabled.
- off this disables a previously enabled core dumping.
- libs this enables core dumping with an embedded copy of the binaries and libraries that are
required for debugging. This may be requested by developers. In this case haproxy will try to load
the libraries it depends on into memory and keep them preciously. If the process crashes, they
will be dumped into the core so there is no need for retrieving them from the file system anymore
and no risk that they do not match the core. This takes a few megabytes to a few tens of megabytes
of additional RAM, so it is better not to use it on small systems.
This option is better left disabled by default and enabled only upon a developer's request. By
default it is disabled. Without argument, it defaults to "on". If it has been enabled, it may still
be forcibly disabled by prefixing it with the "no" keyword or by setting it to "off". It has no
impact on performance nor stability but will try hard to re-enable core dumps that were possibly
disabled by file size limitations (ulimit -f), core size limitations (ulimit -c), or "dumpability"
of a process after changing its UID/GID (such as /proc/sys/fs/suid_dumpable on Linux). Core dumps
might still be limited by the current directory's permissions (check what directory the file is
started from), the chroot directory's permission (it may be needed to temporarily disable the chroot
directive or to move it to a dedicated writable location), or any other system-specific constraint.
For example, some Linux flavours are notorious for replacing the default core file with a path to an
executable not even installed on the system (check /proc/sys/kernel/core_pattern). Often, simply
writing "core", "core.%p" or "/var/log/core/core.%p" addresses the issue. When trying to enable this
option waiting for a rare issue to re-appear, it's often a good idea to first try to obtain such a
dump by issuing, for example, "kill -11" to the "haproxy" process and verify that it leaves a core
where expected when dying.
**`set-var `**
```haproxy
set-var
```
Sets the process-wide variable '``' to the result of the evaluation of the sample
expression ``. The variable '``' may only be a process-wide variable (using the
'proc.' prefix). It works exactly like the 'set-var' action in TCP or HTTP rules except that the
expression is evaluated at configuration parsing time and that the variable is instantly set. The
sample fetch functions and converters permitted in the expression are only those using internal
data, typically 'int(value)' or 'str(value)'. It is possible to reference previously allocated
variables as well. These variables will then be readable (and modifiable) from the regular rule
sets.
Example:
```text
global
set-var proc.current_state str(primary)
set-var proc.prio int(100)
set-var proc.threshold int(200),sub(proc.prio)
```
**`set-var-fmt `**
```haproxy
set-var-fmt
```
Sets the process-wide variable '``' to the string resulting from the evaluation of the
log-format ``. The variable '``' may only be a process-wide variable (using the
'proc.' prefix). It works exactly like the 'set-var-fmt' action in TCP or HTTP rules except that the
expression is evaluated at configuration parsing time and that the variable is instantly set. The
sample fetch functions and converters permitted in the expression are only those using internal
data, typically 'int(value)' or 'str(value)'. It is possible to reference previously allocated
variables as well. These variables will then be readable (and modifiable) from the regular rule
sets. Please see [section 8.2.6](/docs/haproxy/configuration-logging/#section-8-2-6) for details on the Custom log format syntax.
Example:
```text
global
set-var-fmt proc.current_state "primary"
set-var-fmt proc.bootid "%pid|%t"
```
**`setcap [,...]`**
```haproxy
setcap [,...]
```
Sets a list of capabilities that must be preserved when starting and running either as a non-root
user (uid \> 0), or when starting with uid 0 (root) and switching then to a non-root. By default all
permissions are lost by the uid switch, but some are often needed when trying to connect to a server
from a foreign address during transparent proxying, or when binding to a port below 1024, e.g. when
using "tune.quic.fe.sock-per-conn default-on", resulting in setups running entirely under uid 0.
Setting capabilities generally is a safer alternative, as only the required capabilities will be
preserved. The feature is OS-specific and only enabled on Linux when USE_LINUX_CAP=1 is set at build
time. The list of supported capabilities also depends on the OS and is enumerated by the error
message displayed when an invalid capability name or an empty one is passed. Multiple capabilities
may be passed, delimited by commas. Among those commonly used, "cap_net_raw" allows to transparently
bind to a foreign address, and "cap_net_bind_service" allows to bind to a privileged port and may be
used by QUIC. If the process is started and run under the same non-root user, needed capabilities
should be set on haproxy binary file with setcap along with this keyword. For more details about
setting capabilities on haproxy binary, please see chapter 13.1 Linux capabilities support in the
Management guide.
Example:
```text
global
setcap cap_net_bind_service,cap_net_admin
```
**`setenv `**
```haproxy
setenv
```
Sets environment variable `` to value ``. If the variable exists, it is overwritten.
The changes immediately take effect so that the next line in the configuration file sees the new
value. See also "presetenv", "resetenv", and "unsetenv".
**`shm-stats-file `**
```haproxy
shm-stats-file
```
When this directive is set, it enables the use of shared memory for storing stats counters. ``
is used as argument to shm_open() to open the shared memory at a unique location. It also means that
the directive is only available on systems which support shm_open(). When SHM is used for stats, all
shareable counters for frontends, backends, listeners and servers will be stored in the SHM,
provided that they have a GUID set. When reloading haproxy, new process will try to scan the SHM for
objects that could be associated to objects defined in the configuration based on GUID and type, the
goal is to be able to preserve some counters' values upon reload. On the other hand, when haproxy is
properly stopped, the SHM objects are released, which means counters are effectively reset. It is
also possible to manually remove the file before starting a fresh process to force a reset.
See also "guid", "guid-prefix" and "shm-stats-file-max-objects"
**`shm-stats-file-max-objects `**
```haproxy
shm-stats-file-max-objects
```
This setting defines the maximum number of objects the shared memory used for shared counters will
be able to store per thread group. It is directly related to the maximum memory size of the shm and
is used to "premap" the shm to a given size in order to avoid runtime re-mapping. It defaults to 2k,
which should suit for most setups without risking unsuitable memory usage, but can be easily changed
if needed. haproxy will complain during startup if this value is to low to register objects that are
expected to be stored in the shared memory. It is only relevant when "shm-stats-file" was defined.
See also "thread-groups"
**`ssl-default-bind-ciphers `**
```haproxy
ssl-default-bind-ciphers
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of cipher algorithms ("cipher suite") that are negotiated during the SSL/TLS
handshake up to TLSv1.2 for all "bind" lines which do not explicitly define theirs. The format of
the string is defined in "man 1 ciphers" from OpenSSL man pages. For background information and
recommendations see e.g. () and
( ). For TLSv1.3 cipher
configuration, please check the "ssl-default-bind-ciphersuites" keyword. Please check the "bind"
keyword for more information.
**`ssl-default-bind-ciphersuites `**
```haproxy
ssl-default-bind-ciphersuites
```
This setting is only available when support for OpenSSL was built in and OpenSSL 1.1.1 or later was
used to build HAProxy. It sets the default string describing the list of cipher algorithms ("cipher
suite") that are negotiated during the TLSv1.3 handshake for all "bind" lines which do not
explicitly define theirs. The format of the string is defined in "man 1 ciphers" from OpenSSL man
pages under the section "ciphersuites". For cipher configuration for TLSv1.2 and earlier, please
check the "ssl-default-bind-ciphers" keyword. This setting might accept TLSv1.2 ciphersuites however
this is an undocumented behavior and not recommended as it could be inconsistent or buggy. The
default TLSv1.3 ciphersuites of OpenSSL are:
"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
TLSv1.3 only supports 5 ciphersuites:
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_CCM_SHA256
- TLS_AES_128_CCM_8_SHA256
Please check the "bind" keyword for more information.
Example:
```text
global
ssl-default-bind-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
```
**`ssl-default-bind-client-sigalgs `**
```haproxy
ssl-default-bind-client-sigalgs
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of signature algorithms related to client authentication for all "bind" lines
which do not explicitly define theirs. The format of the string is a colon-delimited list of
signature algorithms. Each signature algorithm can use one of two forms: TLS1.3 signature scheme
names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form ("ECDSA+SHA256"). A list can
contain both forms. For more information on the format, see SSL_CTX_set1_client_sigalgs(3). A list
of signature algorithms is also available in RFC8446 section 4.2.3 and in OpenSSL in the
ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier versions of the protocol as
the signature algorithms aren't separately negotiated in these versions. It is not recommended to
change this setting unless compatibility with a middlebox is required.
**`ssl-default-bind-curves `**
```haproxy
ssl-default-bind-curves
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of elliptic curves algorithms ("curve suite") that are negotiated during the
SSL/TLS handshake with ECDHE. The format of the string is a colon-delimited list of curve name.
Please check the "bind" keyword for more information.
**`ssl-default-bind-options []...`**
```haproxy
ssl-default-bind-options [ ]...
```
This setting is only available when support for OpenSSL was built in. It sets default ssl-options to
force on all "bind" lines. Please check the "bind" keyword to see available options.
Example:
```text
global
ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets
```
**`ssl-default-bind-sigalgs `**
```haproxy
ssl-default-bind-sigalgs
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of signature algorithms that are negotiated during the TLSv1.2 and TLSv1.3
handshake for all "bind" lines which do not explicitly define theirs. The format of the string is a
colon-delimited list of signature algorithms. Each signature algorithm can use one of two forms:
TLS1.3 signature scheme names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form
("ECDSA+SHA256"). A list can contain both forms. For more information on the format, see
SSL_CTX_set1_sigalgs(3). A list of signature algorithms is also available in RFC8446 section 4.2.3
and in OpenSSL in the ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier
versions of the protocol as the signature algorithms aren't separately negotiated in these versions.
It is not recommended to change this setting unless compatibility with a middlebox is required.
**`ssl-default-server-ciphers `**
```haproxy
ssl-default-server-ciphers
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of cipher algorithms that are negotiated during the SSL/TLS handshake up to
TLSv1.2 with the server, for all "server" lines which do not explicitly define theirs. The format of
the string is defined in "man 1 ciphers" from OpenSSL man pages. For background information and
recommendations see e.g. () and
( ). For TLSv1.3 cipher
configuration, please check the "ssl-default-server-ciphersuites" keyword. Please check the "server"
keyword for more information.
**`ssl-default-server-ciphersuites `**
```haproxy
ssl-default-server-ciphersuites
```
This setting is only available when support for OpenSSL was built in and OpenSSL 1.1.1 or later was
used to build HAProxy. It sets the default string describing the list of cipher algorithms that are
negotiated during the TLSv1.3 handshake with the server, for all "server" lines which do not
explicitly define theirs. The format of the string is defined in "man 1 ciphers" from OpenSSL man
pages under the section "ciphersuites". For cipher configuration for TLSv1.2 and earlier, please
check the "ssl-default-server-ciphers" keyword. Please check the "server" keyword for more
information.
**`ssl-default-server-client-sigalgs `**
```haproxy
ssl-default-server-client-sigalgs
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of signature algorithms related to client authentication for all "server" lines
which do not explicitly define theirs. The format of the string is a colon-delimited list of
signature algorithms. Each signature algorithm can use one of two forms: TLS1.3 signature scheme
names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form ("ECDSA+SHA256"). A list can
contain both forms. For more information on the format, see SSL_CTX_set1_client_sigalgs(3). A list
of signature algorithms is also available in RFC8446 section 4.2.3 and in OpenSSL in the
ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier versions of the protocol as
the signature algorithms aren't separately negotiated in these versions. It is not recommended to
change this setting unless compatibility with a middlebox is required.
**`ssl-default-server-curves `**
```haproxy
ssl-default-server-curves
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of elliptic curves algorithms ("curve suite") that are negotiated during the
SSL/TLS handshake with ECDHE. The format of the string is a colon-delimited list of curve name.
Please check the "server" keyword for more information.
**`ssl-default-server-options []...`**
```haproxy
ssl-default-server-options [ ]...
```
This setting is only available when support for OpenSSL was built in. It sets default ssl-options to
force on all "server" lines. Please check the "server" keyword to see available options.
**`ssl-default-server-sigalgs `**
```haproxy
ssl-default-server-sigalgs
```
This setting is only available when support for OpenSSL was built in. It sets the default string
describing the list of signature algorithms that are negotiated during the TLSv1.2 and TLSv1.3
handshake for all "server" lines which do not explicitly define theirs. The format of the string is
a colon-delimited list of signature algorithms. Each signature algorithm can use one of two forms:
TLS1.3 signature scheme names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form
("ECDSA+SHA256"). A list can contain both forms. For more information on the format, see
SSL_CTX_set1_sigalgs(3). A list of signature algorithms is also available in RFC8446 section 4.2.3
and in OpenSSL in the ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier
versions of the protocol as the signature algorithms aren't separately negotiated in these versions.
It is not recommended to change this setting unless compatibility with a middlebox is required.
**`ssl-dh-param-file `**
```haproxy
ssl-dh-param-file
```
This setting is only available when support for OpenSSL was built in. It sets the default DH
parameters that are used during the SSL/TLS handshake when ephemeral Diffie-Hellman (DHE) key
exchange is used, for all "bind" lines which do not explicitly define theirs. It will be overridden
by custom DH parameters found in a bind certificate file if any. If custom DH parameters are not
specified either by using ssl-dh-param-file or by setting them directly in the certificate file, DHE
ciphers will not be used, unless tune.ssl.default-dh-param is set. In this latter case, pre-defined
DH parameters of the specified size will be used. Custom parameters are known to be more secure and
therefore their use is recommended. Custom DH parameters may be generated by using the OpenSSL
command "openssl dhparam ``", where size should be at least 2048, as 1024-bit DH parameters
should not be considered secure anymore.
**`ssl-passphrase-cmd ...`**
```haproxy
ssl-passphrase-cmd ...
```
This settings is only available when support for OpenSSL was built in. It allows to define a full
command line that will be called when an encrypted certificate is loaded during init. The command
could be a script or any other program. It will be provided with the encrypted private key path as
first parameter and the user-defined "args" parameters then and should dump the passphrase that
allows to decode the encrypted private key on the standard output. For every new encrypted private
key loaded during init, HAProxy will first try every other already known passphrase to decode the
private key and will ultimately call the passphrase command again if none works.
**`ssl-propquery `**
```haproxy
ssl-propquery
```
This setting is only available when support for OpenSSL was built in and when OpenSSL's version is
at least 3.0. It allows to define a default property string used when fetching algorithms in
providers. It behave the same way as the openssl propquery option and it follows the same syntax
(described in ). For instance, if you have
two providers loaded, the foo one and the default one, the propquery "?provider=foo" allows to pick
the algorithm implementations provided by the foo provider by default, and to fallback on the
default provider's one if it was not found.
**`ssl-provider `**
```haproxy
ssl-provider
```
This setting is only available when support for OpenSSL was built in and when OpenSSL's version is
at least 3.0. It allows to load a provider during init. If loading is successful, any capabilities
provided by the loaded provider might be used by HAProxy. Multiple 'ssl-provider' options can be
specified in a configuration file. The providers will be loaded in their order of appearance.
Please note that loading a provider explicitly prevents OpenSSL from loading the 'default' provider
automatically. OpenSSL also allows to define the providers that should be loaded directly in its
configuration file (openssl.cnf for instance) so it is not necessary to use this 'ssl-provider'
option to load providers. The "show ssl providers" CLI command can be used to show all the providers
that were successfully loaded.
The default search path of OpenSSL provider can be found in the output of the "openssl version -a"
command. If the provider is in another directory, you can set the OPENSSL_MODULES environment
variable, which takes the directory where your provider can be found.
See also "ssl-propquery" and "ssl-provider-path".
**`ssl-provider-path `**
```haproxy
ssl-provider-path
```
This setting is only available when support for OpenSSL was built in and when OpenSSL's version is
at least 3.0. It allows to specify the search path that is to be used by OpenSSL for looking for
providers. It behaves the same way as the OPENSSL_MODULES environment variable. It will be used for
any following 'ssl-provider' option or until a new 'ssl-provider-path' is defined. See also
"ssl-provider".
**`ssl-load-extra-del-ext`**
```haproxy
ssl-load-extra-del-ext
```
This setting allows to configure the way HAProxy does the lookup for the extra SSL files. By default
HAProxy adds a new extension to the filename. (ex: with "foobar.crt" load "foobar.crt.key"). With
this option enabled, HAProxy removes the extension before adding the new one (ex: with "foobar.crt"
load "foobar.key").
Your crt file must have a ".crt" extension for this option to work.
This option is not compatible with bundle extensions (.ecdsa, .rsa. .dsa) and won't try to remove
them.
This option is disabled by default. See also "ssl-load-extra-files".
**`ssl-load-extra-files *`**
```haproxy
ssl-load-extra-files *
```
This setting alters the way HAProxy will look for unspecified files during the loading of the SSL
certificates. This option applies to certificates associated to "bind" lines as well as "server"
lines but some of the extra files will not have any functional impact for "server" line
certificates.
By default, HAProxy discovers automatically a lot of files not specified in the configuration, and
you may want to disable this behavior if you want to optimize the startup time.
"none": Only load the files specified in the configuration. Don't try to load a certificate bundle
if the file does not exist. In the case of a directory, it won't try to bundle the certificates if
they have the same basename.
"all": This is the default behavior, it will try to load everything, bundles, sctl, ocsp, issuer,
key.
"bundle": When a file specified in the configuration does not exist, HAProxy will try to load a
"cert bundle". Certificate bundles are only managed on the frontend side and will not work for
backend certificates.
Starting from HAProxy 2.3, the bundles are not loaded in the same OpenSSL certificate store, instead
it will loads each certificate in a separate store which is equivalent to declaring multiple "crt".
OpenSSL 1.1.1 is required to achieve this. Which means that bundles are now used only for backward
compatibility and are not mandatory anymore to do an hybrid RSA/ECC bind configuration.
To associate these PEM files into a "cert bundle" that is recognized by HAProxy, they must be named
in the following way: All PEM files that are to be bundled must have the same base name, with a
suffix indicating the key type. Currently, three suffixes are supported: rsa, dsa and ecdsa. For
example, if [www.example.com](http://www.example.com) has two PEM files, an RSA file and an ECDSA
file, they must be named: "example.pem.rsa" and "example.pem.ecdsa". The first part of the filename
is arbitrary; only the suffix matters. To load this bundle into HAProxy, specify the base name only:
Example: bind:8443 ssl crt example.pem
Note that the suffix is not given to HAProxy; this tells HAProxy to look for a cert bundle.
HAProxy will load all PEM files in the bundle as if they were configured separately in several
"crt".
The bundle loading does not have an impact anymore on the directory loading since files are loading
separately.
On the CLI, bundles are seen as separate files, and the bundle extension is required to commit them.
OCSP files (.ocsp), issuer files (.issuer), Certificate Transparency (.sctl) as well as private keys
(.key) are supported with multi-cert bundling.
"sctl": Try to load "``.sctl" for each crt keyword. If provided for a backend certificate,
it will be loaded but will not have any functional impact.
"ocsp": Try to load "``.ocsp" for each crt keyword. If provided for a backend certificate,
it will be loaded but will not have any functional impact.
"issuer": Try to load "``.issuer" if the issuer of the OCSP file is not provided in the
PEM file. If provided for a backend certificate, it will be loaded but will not have any functional
impact.
"key": If the private key was not provided by the PEM file, try to load a file "``.key"
containing a private key.
The default behavior is "all".
Example:
```text
ssl-load-extra-files bundle sctl
ssl-load-extra-files sctl ocsp issuer
ssl-load-extra-files none
```
See also: "crt", [section 5.1](/docs/haproxy/bind-and-server-options/#section-5-1) about bind options and [section 5.2](/docs/haproxy/bind-and-server-options/#section-5-2) about server options.
**`ssl-security-level `**
```haproxy
ssl-security-level
```
This directive allows to chose the OpenSSL security level as described in
The security level will
be applied to every SSL contextes in HAProxy. Only a value between 0 and 5 is supported.
The default value depends on your OpenSSL version, distribution and how was compiled the library.
This directive requires at least OpenSSL 1.1.1.
**`ssl-server-verify [none|required]`**
```haproxy
ssl-server-verify [none|required]
```
The default behavior for SSL verify on servers side. If specified to 'none', servers certificates
are not verified. The default is 'required' except if forced using cmdline option '-dV'.
**`ssl-skip-self-issued-ca`**
```haproxy
ssl-skip-self-issued-ca
```
Self issued CA, aka x509 root CA, is the anchor for chain validation: as a server is useless to send
it, client must have it. Standard configuration need to not include such CA in PEM file. This option
allows you to keep such CA in PEM file without sending it to the client. Use case is to provide
issuer for ocsp without the need for '.issuer' file and be able to share it with
'issuers-chain-path'. This concerns all certificates without intermediate certificates. It's useless
for BoringSSL, .issuer is ignored because ocsp bits does not need it. Requires at least OpenSSL
1.0.2.
**`stats calculate-max-counters [on|off]`**
```haproxy
stats calculate-max-counters [on|off]
```
Activates or deactivates the calculation of stats max counters. If you don't need them, deactivating
them may increase performances a bit. The default is on.
**`stats maxconn `**
```haproxy
stats maxconn
```
By default, the stats socket is limited to 10 concurrent connections. It is possible to change this
value with "stats maxconn".
**`stats socket [|