From b46aad6df449445a9fc4aa7b32bd40005438e3f7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 14:18:05 +0200 Subject: Adding upstream version 2.9.5. Signed-off-by: Daniel Baumann --- doc/configuration.txt | 26732 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 26732 insertions(+) create mode 100644 doc/configuration.txt (limited to 'doc/configuration.txt') diff --git a/doc/configuration.txt b/doc/configuration.txt new file mode 100644 index 0000000..a1f15fc --- /dev/null +++ b/doc/configuration.txt @@ -0,0 +1,26732 @@ + ---------------------- + HAProxy + Configuration Manual + ---------------------- + version 2.9 + 2024/02/15 + + +This document covers the configuration language as implemented in the version +specified above. It does not provide any hints, examples, or advice. For such +documentation, please refer to the Reference Manual or the Architecture Manual. +The summary below is meant to help you find sections by name and navigate +through the document. + +Note to documentation contributors : + This document is formatted with 80 columns per line, with even number of + spaces for indentation and without tabs. Please follow these rules strictly + so that it remains easily printable everywhere. If a line needs to be + printed verbatim and does not fit, please end each line with a backslash + ('\') and continue on next line, indented by two characters. It is also + sometimes useful to prefix all output lines (logs, console outputs) with 3 + closing angle brackets ('>>>') in order to emphasize the difference between + inputs and outputs when they may be ambiguous. If you add sections, + please update the summary below for easier searching. + + +Summary +------- + +1. Quick reminder about HTTP +1.1. The HTTP transaction model +1.2. Terminology +1.3. HTTP request +1.3.1. The request line +1.3.2. The request headers +1.4. HTTP response +1.4.1. The response line +1.4.2. The response headers + +2. Configuring HAProxy +2.1. Configuration file format +2.2. Quoting and escaping +2.3. Environment variables +2.4. Conditional blocks +2.5. Time format +2.6. Size format +2.7. Examples + +3. Global parameters +3.1. Process management and security +3.2. Performance tuning +3.3. Debugging +3.4. Userlists +3.5. Peers +3.6. Mailers +3.7. Programs +3.8. HTTP-errors +3.9. Rings +3.10. Log forwarding +3.11. HTTPClient tuning + +4. Proxies +4.1. Proxy keywords matrix +4.2. Alphabetically sorted keywords reference +4.3. Actions keywords matrix +4.4. Alphabetically sorted actions reference + +5. Bind and server options +5.1. Bind options +5.2. Server and default-server options +5.3. Server DNS resolution +5.3.1. Global overview +5.3.2. The resolvers section + +6. Cache +6.1. Limitation +6.2. Setup +6.2.1. Cache section +6.2.2. Proxy section + +7. Using ACLs and fetching samples +7.1. ACL basics +7.1.1. Matching booleans +7.1.2. Matching integers +7.1.3. Matching strings +7.1.4. Matching regular expressions (regexes) +7.1.5. Matching arbitrary data blocks +7.1.6. Matching IPv4 and IPv6 addresses +7.2. Using ACLs to form conditions +7.3. Fetching samples +7.3.1. Converters +7.3.2. Fetching samples from internal states +7.3.3. Fetching samples at Layer 4 +7.3.4. Fetching samples at Layer 5 +7.3.5. Fetching samples from buffer contents (Layer 6) +7.3.6. Fetching HTTP samples (Layer 7) +7.3.7. Fetching samples for developers +7.4. Pre-defined ACLs + +8. Logging +8.1. Log levels +8.2. Log formats +8.2.1. Default log format +8.2.2. TCP log format +8.2.3. HTTP log format +8.2.4. HTTPS log format +8.2.5. Error log format +8.2.6. Custom log format +8.3. Advanced logging options +8.3.1. Disabling logging of external tests +8.3.2. Logging before waiting for the stream to terminate +8.3.3. Raising log level upon errors +8.3.4. Disabling logging of successful connections +8.4. Timing events +8.5. Stream state at disconnection +8.6. Non-printable characters +8.7. Capturing HTTP cookies +8.8. Capturing HTTP headers +8.9. Examples of logs + +9. Supported filters +9.1. Trace +9.2. HTTP compression +9.3. Stream Processing Offload Engine (SPOE) +9.4. Cache +9.5. fcgi-app +9.6. OpenTracing +9.7. Bandwidth limitation + +10. FastCGI applications +10.1. Setup +10.1.1. Fcgi-app section +10.1.2. Proxy section +10.1.3. Example +10.2. Default parameters +10.3. Limitations + +11. Address formats +11.1. Address family prefixes +11.2. Socket type prefixes +11.3. Protocol prefixes + + +1. Quick reminder about HTTP +---------------------------- + +When HAProxy is running in HTTP mode, both the request and the response are +fully analyzed and indexed, thus it becomes possible to build matching criteria +on almost anything found in the contents. + +However, it is important to understand how HTTP requests and responses are +formed, and how HAProxy decomposes them. It will then become easier to write +correct rules and to debug existing configurations. + +First, HTTP is standardized by a series of RFC that HAProxy follows as closely +as possible: + - RFC 9110: HTTP Semantics (explains the meaning of protocol elements) + - RFC 9111: HTTP Caching (explains the rules to follow for an HTTP cache) + - RFC 9112: HTTP/1.1 (representation, interoperability rules, security) + - RFC 9113: HTTP/2 (representation, interoperability rules, security) + - RFC 9114: HTTP/3 (representation, interoperability rules, security) + +In addition to these, RFC 8999 to 9002 specify the QUIC transport layer used by +the HTTP/3 protocol. + + +1.1. The HTTP transaction model +------------------------------- + +The HTTP protocol is transaction-driven. This means that each request will lead +to one and only one response. Originally, with version 1.0 of the protocol, +there was a single request per connection: a TCP connection is established from +the client to the server, a request is sent by the client over the connection, +the server responds, and the connection is closed. A new request then involves +a new connection : + + [CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ... + +In this mode, often called the "HTTP close" mode, there are as many connection +establishments as there are HTTP transactions. Since the connection is closed +by the server after the response, the client does not need to know the content +length, it considers that the response is complete when the connection closes. +This also means that if some responses are truncated due to network errors, the +client could mistakenly think a response was complete, and this used to cause +truncated images to be rendered on screen sometimes. + +Due to the transactional nature of the protocol, it was possible to improve it +to avoid closing a connection between two subsequent transactions. In this mode +however, it is mandatory that the server indicates the content length for each +response so that the client does not wait indefinitely. For this, a special +header is used: "Content-length". This mode is called the "keep-alive" mode, +and arrived with HTTP/1.1 (some HTTP/1.0 agents support it), and connections +that are reused between requests are called "persistent connections": + + [CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ... + +Its advantages are a reduced latency between transactions, less processing +power required on the server side, and the ability to detect a truncated +response. It is generally faster than the close mode, but not always because +some clients often limit their concurrent connections to a smaller value, and +this compensates less for poor network connectivity. Also, some servers have to +keep the connection alive for a long time waiting for a possible new request +and may experience a high memory usage due to the high number of connections, +and closing too fast may break some requests that arrived at the moment the +connection was closed. + +In this mode, the response size needs to be known upfront so that's not always +possible with dynamically generated or compressed contents. For this reason +another mode was implemented, the "chunked mode", where instead of announcing +the size of the whole size at once, the sender only advertises the size of the +next "chunk" of response it already has in a buffer, and can terminate at any +moment with a zero-sized chunk. In this mode, the Content-Length header is not +used. + +Another improvement in the communications is the pipelining mode. It still uses +keep-alive, but the client does not wait for the first response to send the +second request. This is useful for fetching large number of images composing a +page : + + [CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ... + +This can obviously have a tremendous benefit on performance because the network +latency is eliminated between subsequent requests. Many HTTP agents do not +correctly support pipelining since there is no way to associate a response with +the corresponding request in HTTP. For this reason, it is mandatory for the +server to reply in the exact same order as the requests were received. In +practice, after several attempts by various clients to deploy it, it has been +totally abandoned for its lack of reliability on certain servers. But it is +mandatory for servers to support it. + +The next improvement is the multiplexed mode, as implemented in HTTP/2 and +HTTP/3. In this mode, multiple transactions (i.e. request-response pairs) are +transmitted in parallel over a single connection, and they all progress at +their own speed, independent from each other. With multiplexed protocols, a new +notion of "stream" was introduced, to represent these parallel communications +happening over the same connection. Each stream is generally assigned a unique +identifier for a given connection, that is used by both endpoints to know where +to deliver the data. It is fairly common for clients to start many (up to 100, +sometimes more) streams in parallel over a same connection, and let the server +sort them out and respond in any order depending on what response is available. +The main benefit of the multiplexed mode is that it significantly reduces the +number of round trips, and speeds up page loading time over high latency +networks. It is sometimes visibles on sites using many images, where all images +appear to load in parallel. + +These protocols have also improved their efficiency by adopting some mechanisms +to compress header fields in order to reduce the number of bytes on the wire, +so that without the appropriate tools, they are not realistically manipulable +by hand nor readable to the naked eye like HTTP/1 was. For this reason, various +examples of HTTP messages continue to be represented in literature (including +this document) using the HTTP/1 syntax even for newer versions of the protocol. + +HTTP/2 suffers from some design limitations, such as packet losses affecting +all streams at once, and if a client takes too much time to retrieve an object +(e.g. needs to store it on disk), it may slow down its retrieval and make it +impossible during this time to access the data that is pending behind it. This +is called "head of line blocking" or "HoL blocking" or sometimes just "HoL". + +HTTP/3 is implemented over QUIC, itself implemented over UDP. QUIC solves the +head of line blocking at the transport level by means of independently handled +streams. Indeed, when experiencing loss, an impacted stream does not affect the +other streams, and all of them can be accessed in parallel. + +By default HAProxy operates in keep-alive mode with regards to persistent +connections: for each connection it processes each request and response, and +leaves the connection idle on both sides between the end of a response and the +start of a new request. When it receives HTTP/2 connections from a client, it +processes all the requests in parallel and leaves the connection idling, +waiting for new requests, just as if it was a keep-alive HTTP connection. + +HAProxy essentially supports 3 connection modes : + - keep alive : all requests and responses are processed, and the client + facing and server facing connections are kept alive for new + requests. This is the default and suits the modern web and + modern protocols (HTTP/2 and HTTP/3). + + - server close : the server-facing connection is closed after the response. + + - close : the connection is actively closed after end of response on + both sides. + +In addition to this, by default, the server-facing connection is reusable by +any request from any client, as mandated by the HTTP protocol specification, so +any information pertaining to a specific client has to be passed along with +each request if needed (e.g. client's source adress etc). When HTTP/2 is used +with a server, by default HAProxy will dedicate this connection to the same +client to avoid the risk of head of line blocking between clients. + + +1.2. Terminology +---------------- + +Inside HAProxy, the terminology has evolved a bit over the ages to follow the +evolutions of the HTTP protocol and its usages. While originally there was no +significant difference between a connection, a session, a stream or a +transaction, these ones clarified over time to match closely what exists in the +modern versions of the HTTP protocol, though some terms remain visible in the +configuration or the command line interface for the purpose of historical +compatibility. + +Here are some definitions that apply to the current version of HAProxy: + + - connection: a connection is a single, bidiractional communication channel + between a remote agent (client or server) and haproxy, at the lowest level + possible. Usually it corresponds to a TCP socket established between a pair + of IP and ports. On the client-facing side, connections are the very first + entities that are instantiated when a client connects to haproxy, and rules + applying at the connection level are the earliest ones that apply. + + - session: a session adds some context information associated with a + connection. This includes and information specific to the transport layer + (e.g. TLS keys etc), or variables. This term has long been used inside + HAProxy to denote end-to-end HTTP/1.0 communications between two ends, and + as such it remains visible in the name of certain CLI commands or + statistics, despite representing streams nowadays, but the help messages + and descriptions try to make this unambiguous. It is still valid when it + comes to network-level terminology (e.g. TCP sessions inside the operating + systems, or TCP sessions across a firewall), or for non-HTTP user-level + applications (e.g. a telnet session or an SSH session). It must not be + confused with "application sessions" that are used to store a full user + context in a cookie and require to be sent to the same server. + + - stream: a stream exactly corresponds to an end-to-end bidirectional + communication at the application level, where analysis and transformations + may be applied. In HTTP, it contains a single request and its associated + response, and is instantiated by the arrival of the request and is finished + with the end of delivery of the response. In this context there is a 1:1 + relation between such a stream and the stream of a multiplexed protocol. In + TCP communications there is a single stream per connection. + + - transaction: a transaction is only a pair of a request and the associated + response. The term was used in conjunction with sessions before the streams + but nowadays there is a 1:1 relation between a transaction and a stream. It + is essentially visible in the variables' scope "txn" which is valid during + the whole transaction, hence the stream. + + - request: it designates the traffic flowing from the client to the server. + It is mainly used for HTTP to indicate where operations are performed. This + term also exists for TCP operations to indicate where data are processed. + Requests often appear in counters as a unit of traffic or activity. They do + not always imply a response (e.g. due to errors), but since there is no + spontaneous responses without requests, requests remain a relevant metric + of the overall activity. In TCP there are as many requests as connections. + + - response: this designates the traffic flowing from the server to the + client, or sometimes from HAProxy to the client, when HAProxy produces the + response itself (e.g. an HTTP redirect). + + - service: this generally indicates some internal processing in HAProxy that + does not require a server, such as the stats page, the cache, or some Lua + code to implement a small application. A service usually reads a request, + performs some operations and produces a response. + + +1.3. HTTP request +----------------- + +First, let's consider this HTTP request : + + Line Contents + number + 1 GET /serv/login.php?lang=en&profile=2 HTTP/1.1 + 2 Host: www.mydomain.com + 3 User-agent: my small browser + 4 Accept: image/jpeg, image/gif + 5 Accept: image/png + + +1.3.1. The Request line +----------------------- + +Line 1 is the "request line". It is always composed of 3 fields : + + - a METHOD : GET + - a URI : /serv/login.php?lang=en&profile=2 + - a version tag : HTTP/1.1 + +All of them are delimited by what the standard calls LWS (linear white spaces), +which are commonly spaces, but can also be tabs or line feeds/carriage returns +followed by spaces/tabs. The method itself cannot contain any colon (':') and +is limited to alphabetic letters. All those various combinations make it +desirable that HAProxy performs the splitting itself rather than leaving it to +the user to write a complex or inaccurate regular expression. + +The URI itself can have several forms : + + - A "relative URI" : + + /serv/login.php?lang=en&profile=2 + + It is a complete URL without the host part. This is generally what is + received by servers, reverse proxies and transparent proxies. + + - An "absolute URI", also called a "URL" : + + http://192.168.0.12:8080/serv/login.php?lang=en&profile=2 + + It is composed of a "scheme" (the protocol name followed by '://'), a host + name or address, optionally a colon (':') followed by a port number, then + a relative URI beginning at the first slash ('/') after the address part. + This is generally what proxies receive, but a server supporting HTTP/1.1 + must accept this form too. + + - a star ('*') : this form is only accepted in association with the OPTIONS + method and is not relayable. It is used to inquiry a next hop's + capabilities. + + - an address:port combination : 192.168.0.12:80 + This is used with the CONNECT method, which is used to establish TCP + tunnels through HTTP proxies, generally for HTTPS, but sometimes for + other protocols too. + +In a relative URI, two sub-parts are identified. The part before the question +mark is called the "path". It is typically the relative path to static objects +on the server. The part after the question mark is called the "query string". +It is mostly used with GET requests sent to dynamic scripts and is very +specific to the language, framework or application in use. + +HTTP/3 and HTTP/3 do not convey a version information with the request, so the +version is assumed to be the same as the one of the underlying protocol (i.e. +"HTTP/2"). In addition, these protocols do not send a request line as one part, +but split it into individual fields called "pseudo-headers", whose name start +with a colon, and which are conveniently reassembled by HAProxy into an +equivalent request line. For this reason, request lines found in logs may +slightly differ between HTTP/1.x and HTTP/2 or HTTP/3. + + +1.3.2. The request headers +-------------------------- + +The headers start at the second line. They are composed of a name at the +beginning of the line, immediately followed by a colon (':'). Traditionally, +an LWS is added after the colon but that's not required. Then come the values. +Multiple identical headers may be folded into one single line, delimiting the +values with commas, provided that their order is respected. This is commonly +encountered in the "Cookie:" field. A header may span over multiple lines if +the subsequent lines begin with an LWS. In the example in 1.3, lines 4 and 5 +define a total of 3 values for the "Accept:" header. Finally, all LWS at the +beginning or at the end of a header are ignored and are not part of the value, +as per the specification. + +Contrary to a common misconception, header names are not case-sensitive, and +their values are not either if they refer to other header names (such as the +"Connection:" header). In HTTP/2 and HTTP/3, header names are always sent in +lower case, as can be seen when running in debug mode. Internally, all header +names are normalized to lower case so that HTTP/1.x and HTTP/2 or HTTP/3 use +the exact same representation, and they are sent as-is on the other side. This +explains why an HTTP/1.x request typed with camel case is delivered in lower +case. + +The end of the headers is indicated by the first empty line. People often say +that it's a double line feed, which is not exact, even if a double line feed +is one valid form of empty line. + +Fortunately, HAProxy takes care of all these complex combinations when indexing +headers, checking values and counting them, so there is no reason to worry +about the way they could be written, but it is important not to accuse an +application of being buggy if it does unusual, valid things. + +Important note: + As suggested by RFC7231, HAProxy normalizes headers by replacing line breaks + in the middle of headers by LWS in order to join multi-line headers. This + is necessary for proper analysis and helps less capable HTTP parsers to work + correctly and not to be fooled by such complex constructs. + + +1.4. HTTP response +------------------ + +An HTTP response looks very much like an HTTP request. Both are called HTTP +messages. Let's consider this HTTP response : + + Line Contents + number + 1 HTTP/1.1 200 OK + 2 Content-length: 350 + 3 Content-Type: text/html + +As a special case, HTTP supports so called "Informational responses" as status +codes 1xx. These messages are special in that they don't convey any part of the +response, they're just used as sort of a signaling message to ask a client to +continue to post its request for instance. In the case of a status 100 response +the requested information will be carried by the next non-100 response message +following the informational one. This implies that multiple responses may be +sent to a single request, and that this only works when keep-alive is enabled +(1xx messages appeared in HTTP/1.1). HAProxy handles these messages and is able +to correctly forward and skip them, and only process the next non-100 response. +As such, these messages are neither logged nor transformed, unless explicitly +state otherwise. Status 101 messages indicate that the protocol is changing +over the same connection and that HAProxy must switch to tunnel mode, just as +if a CONNECT had occurred. Then the Upgrade header would contain additional +information about the type of protocol the connection is switching to. + + +1.4.1. The response line +------------------------ + +Line 1 is the "response line". It is always composed of 3 fields : + + - a version tag : HTTP/1.1 + - a status code : 200 + - a reason : OK + +The status code is always 3-digit. The first digit indicates a general status : + - 1xx = informational message to be skipped (e.g. 100, 101) + - 2xx = OK, content is following (e.g. 200, 206) + - 3xx = OK, no content following (e.g. 302, 304) + - 4xx = error caused by the client (e.g. 401, 403, 404) + - 5xx = error caused by the server (e.g. 500, 502, 503) + +Status codes greater than 599 must not be emitted in communications, though +certain agents may produce them in logs to report their internal statuses. +Please refer to RFC9110 for the detailed meaning of all such codes. HTTP/2 and +above do not have a version tag and use the ":status" pseudo-header to report +the status code. + +The "reason" field is just a hint, but is not parsed by clients. Anything can +be found there, but it's a common practice to respect the well-established +messages. It can be composed of one or multiple words, such as "OK", "Found", +or "Authentication Required". It does not exist in HTTP/2 and above and is +not emitted there. When a response from HTTP/2 or above is transmitted to an +HTTP/1 client, HAProxy will produce such a common reason field that matches +the status code. + +HAProxy may emit the following status codes by itself : + + Code When / reason + 200 access to stats page, and when replying to monitoring requests + 301 when performing a redirection, depending on the configured code + 302 when performing a redirection, depending on the configured code + 303 when performing a redirection, depending on the configured code + 307 when performing a redirection, depending on the configured code + 308 when performing a redirection, depending on the configured code + 400 for an invalid or too large request + 401 when an authentication is required to perform the action (when + accessing the stats page) + 403 when a request is forbidden by a "http-request deny" rule + 404 when the requested resource could not be found + 408 when the request timeout strikes before the request is complete + 410 when the requested resource is no longer available and will not + be available again + 500 when HAProxy encounters an unrecoverable internal error, such as a + memory allocation failure, which should never happen + 501 when HAProxy is unable to satisfy a client request because of an + unsupported feature + 502 when the server returns an empty, invalid or incomplete response, or + when an "http-response deny" rule blocks the response. + 503 when no server was available to handle the request, or in response to + monitoring requests which match the "monitor fail" condition + 504 when the response timeout strikes before the server responds + +The error 4xx and 5xx codes above may be customized (see "errorloc" in section +4.2). Other status codes can be emitted on purpose by specific actions (see the +"deny", "return" and "redirect" actions in section 4.3 for example). + + +1.4.2. The response headers +--------------------------- + +Response headers work exactly like request headers, and as such, HAProxy uses +the same parsing function for both. Please refer to paragraph 1.3.2 for more +details. + + +2. Configuring HAProxy +---------------------- + +2.1. Configuration file format +------------------------------ + +HAProxy's configuration process involves 3 major sources of parameters : + + - the arguments from the command-line, which always take precedence + - the configuration file(s), whose format is described here + - the running process's environment, in case some environment variables are + explicitly referenced + +The configuration file follows a fairly simple hierarchical format which obey +a few basic rules: + + 1. a configuration file is an ordered sequence of statements + + 2. a statement is a single non-empty line before any unprotected "#" (hash) + + 3. a line is a series of tokens or "words" delimited by unprotected spaces or + tab characters + + 4. the first word or sequence of words of a line is one of the keywords or + keyword sequences listed in this document + + 5. all other words are all arguments of the first one, some being well-known + keywords listed in this document, others being values, references to other + parts of the configuration, or expressions + + 6. certain keywords delimit a section inside which only a subset of keywords + are supported + + 7. a section ends at the end of a file or on a special keyword starting a new + section + +This is all that is needed to know to write a simple but reliable configuration +generator, but this is not enough to reliably parse any configuration nor to +figure how to deal with certain corner cases. + +First, there are a few consequences of the rules above. Rule 6 and 7 imply that +the keywords used to define a new section are valid everywhere and cannot have +a different meaning in a specific section. These keywords are always a single +word (as opposed to a sequence of words), and traditionally the section that +follows them is designated using the same name. For example when speaking about +the "global section", it designates the section of configuration that follows +the "global" keyword. This usage is used a lot in error messages to help locate +the parts that need to be addressed. + +A number of sections create an internal object or configuration space, which +requires to be distinguished from other ones. In this case they will take an +extra word which will set the name of this particular section. For some of them +the section name is mandatory. For example "frontend foo" will create a new +section of type "frontend" named "foo". Usually a name is specific to its +section and two sections of different types may use the same name, but this is +not recommended as it tends to complexify configuration management. + +A direct consequence of rule 7 is that when multiple files are read at once, +each of them must start with a new section, and the end of each file will end +a section. A file cannot contain sub-sections nor end an existing section and +start a new one. + +Rule 1 mentioned that ordering matters. Indeed, some keywords create directives +that can be repeated multiple times to create ordered sequences of rules to be +applied in a certain order. For example "tcp-request" can be used to alternate +"accept" and "reject" rules on varying criteria. As such, a configuration file +processor must always preserve a section's ordering when editing a file. The +ordering of sections usually does not matter except for the global section +which must be placed before other sections, but it may be repeated if needed. +In addition, some automatic identifiers may automatically be assigned to some +of the created objects (e.g. proxies), and by reordering sections, their +identifiers will change. These ones appear in the statistics for example. As +such, the configuration below will assign "foo" ID number 1 and "bar" ID number +2, which will be swapped if the two sections are reversed: + + listen foo + bind :80 + + listen bar + bind :81 + +Another important point is that according to rules 2 and 3 above, empty lines, +spaces, tabs, and comments following and unprotected "#" character are not part +of the configuration as they are just used as delimiters. This implies that the +following configurations are strictly equivalent: + + global#this is the global section + daemon#daemonize + frontend foo + mode http # or tcp + +and: + + global + daemon + + # this is the public web frontend + frontend foo + mode http + +The common practice is to align to the left only the keyword that initiates a +new section, and indent (i.e. prepend a tab character or a few spaces) all +other keywords so that it's instantly visible that they belong to the same +section (as done in the second example above). Placing comments before a new +section helps the reader decide if it's the desired one. Leaving a blank line +at the end of a section also visually helps spotting the end when editing it. + +Tabs are very convenient for indent but they do not copy-paste well. If spaces +are used instead, it is recommended to avoid placing too many (2 to 4) so that +editing in field doesn't become a burden with limited editors that do not +support automatic indent. + +In the early days it used to be common to see arguments split at fixed tab +positions because most keywords would not take more than two arguments. With +modern versions featuring complex expressions this practice does not stand +anymore, and is not recommended. + + +2.2. Quoting and escaping +------------------------- + +In modern configurations, some arguments require the use of some characters +that were previously considered as pure delimiters. In order to make this +possible, HAProxy supports character escaping by prepending a backslash ('\') +in front of the character to be escaped, weak quoting within double quotes +('"') and strong quoting within single quotes ("'"). + +This is pretty similar to what is done in a number of programming languages and +very close to what is commonly encountered in Bourne shell. The principle is +the following: while the configuration parser cuts the lines into words, it +also takes care of quotes and backslashes to decide whether a character is a +delimiter or is the raw representation of this character within the current +word. The escape character is then removed, the quotes are removed, and the +remaining word is used as-is as a keyword or argument for example. + +If a backslash is needed in a word, it must either be escaped using itself +(i.e. double backslash) or be strongly quoted. + +Escaping outside quotes is achieved by preceding a special character by a +backslash ('\'): + + \ to mark a space and differentiate it from a delimiter + \# to mark a hash and differentiate it from a comment + \\ to use a backslash + \' to use a single quote and differentiate it from strong quoting + \" to use a double quote and differentiate it from weak quoting + +In addition, a few non-printable characters may be emitted using their usual +C-language representation: + + \n to insert a line feed (LF, character \x0a or ASCII 10 decimal) + \r to insert a carriage return (CR, character \x0d or ASCII 13 decimal) + \t to insert a tab (character \x09 or ASCII 9 decimal) + \xNN to insert character having ASCII code hex NN (e.g \x0a for LF). + +Weak quoting is achieved by surrounding double quotes ("") around the character +or sequence of characters to protect. Weak quoting prevents the interpretation +of: + + space or tab as a word separator + ' single quote as a strong quoting delimiter + # hash as a comment start + +Weak quoting permits the interpretation of environment variables (which are not +evaluated outside of quotes) by preceding them with a dollar sign ('$'). If a +dollar character is needed inside double quotes, it must be escaped using a +backslash. + +Strong quoting is achieved by surrounding single quotes ('') around the +character or sequence of characters to protect. Inside single quotes, nothing +is interpreted, it's the efficient way to quote regular expressions. + +As a result, here is the matrix indicating how special characters can be +entered in different contexts (unprintable characters are replaced with their +name within angle brackets). Note that some characters that may only be +represented escaped have no possible representation inside single quotes, +hence its absence there: + + Character | Unquoted | Weakly quoted | Strongly quoted + -----------+---------------+-----------------------------+----------------- + | \, \x09 | "", "\", "\x09" | '' + -----------+---------------+-----------------------------+----------------- + | \n, \x0a | "\n", "\x0a" | + -----------+---------------+-----------------------------+----------------- + | \r, \x0d | "\r", "\x0d" | + -----------+---------------+-----------------------------+----------------- + | \, \x20 | "", "\", "\x20" | '' + -----------+---------------+-----------------------------+----------------- + " | \", \x22 | "\"", "\x22" | '"' + -----------+---------------+-----------------------------+----------------- + # | \#, \x23 | "#", "\#", "\x23" | '#' + -----------+---------------+-----------------------------+----------------- + $ | $, \$, \x24 | "\$", "\x24" | '$' + -----------+---------------+-----------------------------+----------------- + ' | \', \x27 | "'", "\'", "\x27" | + -----------+---------------+-----------------------------+----------------- + \ | \\, \x5c | "\\", "\x5c" | '\' + -----------+---------------+-----------------------------+----------------- + + Example: + # those are all strictly equivalent: + log-format %{+Q}o\ %t\ %s\ %{-Q}r + log-format "%{+Q}o %t %s %{-Q}r" + log-format '%{+Q}o %t %s %{-Q}r' + log-format "%{+Q}o %t"' %s %{-Q}r' + log-format "%{+Q}o %t"' %s'\ %{-Q}r + +There is one particular case where a second level of quoting or escaping may be +necessary. Some keywords take arguments within parenthesis, sometimes delimited +by commas. These arguments are commonly integers or predefined words, but when +they are arbitrary strings, it may be required to perform a separate level of +escaping to disambiguate the characters that belong to the argument from the +characters that are used to delimit the arguments themselves. A pretty common +case is the "regsub" converter. It takes a regular expression in argument, and +if a closing parenthesis is needed inside, this one will require to have its +own quotes. + +The keyword argument parser is exactly the same as the top-level one regarding +quotes, except that the \#, \$, and \xNN escapes are not processed. But what is +not always obvious is that the delimiters used inside must first be escaped or +quoted so that they are not resolved at the top level. + +Let's take this example making use of the "regsub" converter which takes 3 +arguments, one regular expression, one replacement string and one set of flags: + + # replace all occurrences of "foo" with "blah" in the path: + http-request set-path %[path,regsub(foo,blah,g)] + +Here no special quoting was necessary. But if now we want to replace either +"foo" or "bar" with "blah", we'll need the regular expression "(foo|bar)". We +cannot write: + + http-request set-path %[path,regsub((foo|bar),blah,g)] + +because we would like the string to cut like this: + + http-request set-path %[path,regsub((foo|bar),blah,g)] + |---------|----|-| + arg1 _/ / / + arg2 __________/ / + arg3 ______________/ + +but actually what is passed is a string between the opening and closing +parenthesis then garbage: + + http-request set-path %[path,regsub((foo|bar),blah,g)] + |--------|--------| + arg1=(foo|bar _/ / + trailing garbage _________/ + +The obvious solution here seems to be that the closing parenthesis needs to be +quoted, but alone this will not work, because as mentioned above, quotes are +processed by the top-level parser which will resolve them before processing +this word: + + http-request set-path %[path,regsub("(foo|bar)",blah,g)] + ------------ -------- ---------------------------------- + word1 word2 word3=%[path,regsub((foo|bar),blah,g)] + +So we didn't change anything for the argument parser at the second level which +still sees a truncated regular expression as the only argument, and garbage at +the end of the string. By escaping the quotes they will be passed unmodified to +the second level: + + http-request set-path %[path,regsub(\"(foo|bar)\",blah,g)] + ------------ -------- ------------------------------------ + word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] + |---------||----|-| + arg1=(foo|bar) _/ / / + arg2=blah ___________/ / + arg3=g _______________/ + +Another approach consists in using single quotes outside the whole string and +double quotes inside (so that the double quotes are not stripped again): + + http-request set-path '%[path,regsub("(foo|bar)",blah,g)]' + ------------ -------- ---------------------------------- + word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] + |---------||----|-| + arg1=(foo|bar) _/ / / + arg2 ___________/ / + arg3 _______________/ + +When using regular expressions, it can happen that the dollar ('$') character +appears in the expression or that a backslash ('\') is used in the replacement +string. In this case these ones will also be processed inside the double quotes +thus single quotes are preferred (or double escaping). Example: + + http-request set-path '%[path,regsub("^/(here)(/|$)","my/\1",g)]' + ------------ -------- ----------------------------------------- + word1 word2 word3=%[path,regsub("^/(here)(/|$)","my/\1",g)] + |-------------| |-----||-| + arg1=(here)(/|$) _/ / / + arg2=my/\1 ________________/ / + arg3 ______________________/ + +Remember that backslashes are not escape characters within single quotes and +that the whole word above is already protected against them using the single +quotes. Conversely, if double quotes had been used around the whole expression, +single the dollar character and the backslashes would have been resolved at top +level, breaking the argument contents at the second level. + +Unfortunately, since single quotes can't be escaped inside of strong quoting, +if you need to include single quotes in your argument, you will need to escape +or quote them twice. There are a few ways to do this: + + http-request set-var(txn.foo) str("\\'foo\\'") + http-request set-var(txn.foo) str(\"\'foo\'\") + http-request set-var(txn.foo) str(\\\'foo\\\') + +When in doubt, simply do not use quotes anywhere, and start to place single or +double quotes around arguments that require a comma or a closing parenthesis, +and think about escaping these quotes using a backslash if the string contains +a dollar or a backslash. Again, this is pretty similar to what is used under +a Bourne shell when double-escaping a command passed to "eval". For API writers +the best is probably to place escaped quotes around each and every argument, +regardless of their contents. Users will probably find that using single quotes +around the whole expression and double quotes around each argument provides +more readable configurations. + + +2.3. Environment variables +-------------------------- + +HAProxy's configuration supports environment variables. Those variables are +interpreted only within double quotes. Variables are expanded during the +configuration parsing. Variable names must be preceded by a dollar ("$") and +optionally enclosed with braces ("{}") similarly to what is done in Bourne +shell. Variable names can contain alphanumerical characters or the character +underscore ("_") but should not start with a digit. If the variable contains a +list of several values separated by spaces, it can be expanded as individual +arguments by enclosing the variable with braces and appending the suffix '[*]' +before the closing brace. It is also possible to specify a default value to +use when the variable is not set, by appending that value after a dash '-' +next to the variable name. Note that the default value only replaces non +existing variables, not empty ones. + + Example: + + bind "fd@${FD_APP1}" + + log "${LOCAL_SYSLOG-127.0.0.1}:514" local0 notice # send to local server + + user "$HAPROXY_USER" + +Some variables are defined by HAProxy, they can be used in the configuration +file, or could be inherited by a program (See 3.7. Programs): + +* HAPROXY_LOCALPEER: defined at the startup of the process which contains the + name of the local peer. (See "-L" in the management guide.) + +* HAPROXY_CFGFILES: list of the configuration files loaded by HAProxy, + separated by semicolons. Can be useful in the case you specified a + directory. + +* HAPROXY_HTTP_LOG_FMT: contains the value of the default HTTP log format as + defined in section 8.2.3 "HTTP log format". It can be used to override the + default log format without having to copy the whole original definition. + + Example: + # Add the rule that gave the final verdict to the log + log-format "${HAPROXY_TCP_LOG_FMT} lr=last_rule_file:last_rule_line" + +* HAPROXY_HTTPS_LOG_FMT: similar to HAPROXY_HTTP_LOG_FMT but for HTTPS log + format as defined in section 8.2.4 "HTTPS log format". + +* HAPROXY_TCP_LOG_FMT: similar to HAPROXY_HTTP_LOG_FMT but for TCP log format + as defined in section 8.2.2 "TCP log format". + +* HAPROXY_MWORKER: In master-worker mode, this variable is set to 1. + +* HAPROXY_CLI: configured listeners addresses of the stats socket for every + processes, separated by semicolons. + +* HAPROXY_MASTER_CLI: In master-worker mode, listeners addresses of the master + CLI, separated by semicolons. + +* HAPROXY_STARTUP_VERSION: contains the version used to start, in master-worker + mode this is the version which was used to start the master, even after + updating the binary and reloading. + +* HAPROXY_BRANCH: contains the HAProxy branch version (such as "2.8"). It does + not contain the full version number. It can be useful in case of migration + if resources (such as maps or certificates) are in a path containing the + branch number. + +In addition, some pseudo-variables are internally resolved and may be used as +regular variables. Pseudo-variables always start with a dot ('.'), and are the +only ones where the dot is permitted. The current list of pseudo-variables is: + +* .FILE: the name of the configuration file currently being parsed. + +* .LINE: the line number of the configuration file currently being parsed, + starting at one. + +* .SECTION: the name of the section currently being parsed, or its type if the + section doesn't have a name (e.g. "global"), or an empty string before the + first section. + +These variables are resolved at the location where they are parsed. For example +if a ".LINE" variable is used in a "log-format" directive located in a defaults +section, its line number will be resolved before parsing and compiling the +"log-format" directive, so this same line number will be reused by subsequent +proxies. + +This way it is possible to emit information to help locate a rule in variables, +logs, error statuses, health checks, header values, or even to use line numbers +to name some config objects like servers for example. + +See also "external-check command" for other variables. + + +2.4. Conditional blocks +----------------------- + +It may sometimes be convenient to be able to conditionally enable or disable +some arbitrary parts of the configuration, for example to enable/disable SSL or +ciphers, enable or disable some pre-production listeners without modifying the +configuration, or adjust the configuration's syntax to support two distinct +versions of HAProxy during a migration.. HAProxy brings a set of nestable +preprocessor-like directives which allow to integrate or ignore some blocks of +text. These directives must be placed on their own line and they act on the +lines that follow them. Two of them support an expression, the other ones only +switch to an alternate block or end a current level. The 4 following directives +are defined to form conditional blocks: + + - .if + - .elif + - .else + - .endif + +The ".if" directive nests a new level, ".elif" stays at the same level, ".else" +as well, and ".endif" closes a level. Each ".if" must be terminated by a +matching ".endif". The ".elif" may only be placed after ".if" or ".elif", and +there is no limit to the number of ".elif" that may be chained. There may be +only one ".else" per ".if" and it must always be after the ".if" or the last +".elif" of a block. + +Comments may be placed on the same line if needed after a '#', they will be +ignored. The directives are tokenized like other configuration directives, and +as such it is possible to use environment variables in conditions. + +Conditions can also be evaluated on startup with the -cc parameter. +See "3. Starting HAProxy" in the management doc. + +The conditions are either an empty string (which then returns false), or an +expression made of any combination of: + + - the integer zero ('0'), always returns "false" + - a non-nul integer (e.g. '1'), always returns "true". + - a predicate optionally followed by argument(s) in parenthesis. + - a condition placed between a pair of parenthesis '(' and ')' + - an exclamation mark ('!') preceding any of the non-empty elements above, + and which will negate its status. + - expressions combined with a logical AND ('&&'), which will be evaluated + from left to right until one returns false + - expressions combined with a logical OR ('||'), which will be evaluated + from right to left until one returns true + +Note that like in other languages, the AND operator has precedence over the OR +operator, so that "A && B || C && D" evalues as "(A && B) || (C && D)". + +The list of currently supported predicates is the following: + + - defined() : returns true if an environment variable + exists, regardless of its contents + + - feature() : returns true if feature is listed as present + in the features list reported by "haproxy -vv" + (which means a appears after a '+') + + - streq(,) : returns true only if the two strings are equal + - strneq(,) : returns true only if the two strings differ + - strstr(,) : returns true only if the second string is found in the first one + + - version_atleast(): returns true if the current haproxy version is + at least as recent as otherwise false. The + version syntax is the same as shown by "haproxy -v" + and missing components are assumed as being zero. + + - version_before() : returns true if the current haproxy version is + strictly older than otherwise false. The + version syntax is the same as shown by "haproxy -v" + and missing components are assumed as being zero. + + - enabled() : returns true if the option is enabled at + run-time. Only a subset of options are supported: + POLL, EPOLL, KQUEUE, EVPORTS, SPLICE, + GETADDRINFO, REUSEPORT, FAST-FORWARD, + SERVER-SSL-VERIFY-NONE + +Example: + + .if defined(HAPROXY_MWORKER) + listen mwcli_px + bind :1111 + ... + .endif + + .if strneq("$SSL_ONLY",yes) + bind :80 + .endif + + .if streq("$WITH_SSL",yes) + .if feature(OPENSSL) + bind :443 ssl crt ... + .endif + .endif + + .if feature(OPENSSL) && (streq("$WITH_SSL",yes) || streq("$SSL_ONLY",yes)) + bind :443 ssl crt ... + .endif + + .if version_atleast(2.4-dev19) + profiling.memory on + .endif + + .if !feature(OPENSSL) + .alert "SSL support is mandatory" + .endif + +Four other directives are provided to report some status: + + - .diag "message" : emit this message only when in diagnostic mode (-dD) + - .notice "message" : emit this message at level NOTICE + - .warning "message" : emit this message at level WARNING + - .alert "message" : emit this message at level ALERT + +Messages emitted at level WARNING may cause the process to fail to start if the +"strict-mode" is enabled. Messages emitted at level ALERT will always cause a +fatal error. These can be used to detect some inappropriate conditions and +provide advice to the user. + +Example: + + .if "${A}" + .if "${B}" + .notice "A=1, B=1" + .elif "${C}" + .notice "A=1, B=0, C=1" + .elif "${D}" + .warning "A=1, B=0, C=0, D=1" + .else + .alert "A=1, B=0, C=0, D=0" + .endif + .else + .notice "A=0" + .endif + + .diag "WTA/2021-05-07: replace 'redirect' with 'return' after switch to 2.4" + http-request redirect location /goaway if ABUSE + + +2.5. Time format +---------------- + +Some parameters involve values representing time, such as timeouts. These +values are generally expressed in milliseconds (unless explicitly stated +otherwise) but may be expressed in any other unit by suffixing the unit to the +numeric value. It is important to consider this because it will not be repeated +for every keyword. Supported units are : + + - us : microseconds. 1 microsecond = 1/1000000 second + - ms : milliseconds. 1 millisecond = 1/1000 second. This is the default. + - s : seconds. 1s = 1000ms + - m : minutes. 1m = 60s = 60000ms + - h : hours. 1h = 60m = 3600s = 3600000ms + - d : days. 1d = 24h = 1440m = 86400s = 86400000ms + + +2.6. Size format +---------------- + +Some parameters involve values representing size, such as bandwidth limits. +These values are generally expressed in bytes (unless explicitly stated +otherwise) but may be expressed in any other unit by suffixing the unit to the +numeric value. It is important to consider this because it will not be repeated +for every keyword. Supported units are case insensitive : + + - k : kilobytes. 1 kilobyte = 1024 bytes + - m : megabytes. 1 megabyte = 1048576 bytes + - g : gigabytes. 1 gigabyte = 1073741824 bytes + +Both time and size formats require integers, decimal notation is not allowed. + + +2.7. Examples +------------- + + # Simple configuration for an HTTP proxy listening on port 80 on all + # interfaces and forwarding requests to a single backend "servers" with a + # single server "server1" listening on 127.0.0.1:8000 + global + daemon + maxconn 256 + + defaults + mode http + timeout connect 5000ms + timeout client 50000ms + timeout server 50000ms + + frontend http-in + bind *:80 + default_backend servers + + backend servers + server server1 127.0.0.1:8000 maxconn 32 + + + # The same configuration defined with a single listen block. Shorter but + # less expressive, especially in HTTP mode. + global + daemon + maxconn 256 + + defaults + mode http + timeout connect 5000ms + timeout client 50000ms + timeout server 50000ms + + listen http-in + bind *:80 + server server1 127.0.0.1:8000 maxconn 32 + + +Assuming haproxy is in $PATH, test these configurations in a shell with: + + $ sudo haproxy -f configuration.conf -c + + +3. Global parameters +-------------------- + +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-map + - crt-base + - daemon + - default-path + - description + - deviceatlas-json-file + - deviceatlas-log-level + - deviceatlas-properties-cookie + - deviceatlas-separator + - expose-experimental-directives + - external-check + - fd-hard-limit + - gid + - grace + - group + - h1-accept-payload-with-any-method + - h1-case-adjust + - h1-case-adjust-file + - h2-workaround-bogus-websocket-clients + - hard-stop-after + - insecure-fork-wanted + - insecure-setuid-wanted + - issuers-chain-path + - localpeer + - log + - log-send-hostname + - log-tag + - lua-load + - lua-load-per-thread + - lua-prepend-path + - mworker-max-reloads + - nbthread + - node + - numa-cpu-mapping + - 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-server-verify + - ssl-skip-self-issued-ca + - stats + - 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 + - nopoll + - noreuseport + - nosplice + - profiling.tasks + - server-state-base + - server-state-file + - spread-checks + - ssl-engine + - ssl-mode-async + - tune.buffers.limit + - tune.buffers.reserve + - tune.bufsize + - tune.comp.maxlevel + - tune.disable-fast-forward + - tune.disable-zero-copy-forwarding + - tune.events.max-events-at-once + - tune.fail-alloc + - tune.fd.edge-triggered + - tune.h1.zero-copy-fwd-recv + - tune.h1.zero-copy-fwd-send + - tune.h2.be.initial-window-size + - tune.h2.be.max-concurrent-streams + - tune.h2.fe.initial-window-size + - tune.h2.fe.max-concurrent-streams + - tune.h2.fe.max-total-streams + - 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.forced-yield + - tune.lua.maxmem + - tune.lua.service-timeout + - tune.lua.session-timeout + - tune.lua.task-timeout + - tune.lua.log.loggers + - tune.lua.log.stderr + - tune.max-checks-per-thread + - tune.maxaccept + - tune.maxpollevents + - tune.maxrewrite + - 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.frontend.conn-tx-buffers.limit + - tune.quic.frontend.max-idle-timeout + - tune.quic.frontend.max-streams-bidi + - tune.quic.max-frame-loss + - tune.quic.retry-threshold + - tune.quic.socket-owner + - tune.quic.zero-copy-fwd-send + - tune.rcvbuf.backend + - tune.rcvbuf.client + - tune.rcvbuf.frontend + - tune.rcvbuf.server + - tune.recv_enough + - tune.runqueue-depth + - tune.sched.low-latency + - tune.sndbuf.backend + - tune.sndbuf.client + - tune.sndbuf.frontend + - tune.sndbuf.server + - tune.stick-counters + - tune.ssl.cachesize + - tune.ssl.capture-buffer-size + - tune.ssl.capture-cipherlist-size (deprecated) + - tune.ssl.default-dh-param + - tune.ssl.force-private-cache + - tune.ssl.hard-maxrecord + - tune.ssl.keylog + - tune.ssl.lifetime + - tune.ssl.maxrecord + - tune.ssl.ssl-ctx-cache-size + - tune.ssl.ocsp-update.maxdelay + - tune.ssl.ocsp-update.mindelay + - 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 + - quiet + - 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 +------------------------------------ + +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 [ ...] + A list of 51Degrees property names to be load from the dataset. A full list + of names is available on the 51Degrees website: + https://51degrees.com/resources/property-dictionary + + Please note that this option is only available when HAProxy has been + compiled with USE_51DEGREES. + +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 + 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 } + 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 } + 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 + 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 + 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 } + 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. + +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 + 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. This only works when the process is started + with superuser privileges. It is important to ensure that is both + empty and non-writable to anyone. + +close-spread-time