Core concepts

Variables

Variables store values in order to make them available during various phases of load balancing.

Temporary variables Jump to heading

A variable holds a value from a fetch method so that you can use that value later in your configuration. Typically, you need them when you want to store a value from a fetch method that is only available when the load balancer receives a request, but not when returning the response. For example, the path fetch is available during the request phase, but not during the response phase. By storing the path in a variable, you can access it during the response phase too.

Set a variable Jump to heading

To set a variable, use one of the following directives:

  • http-request set-var
  • http-response set-var
  • http-response-after-response set-var

The following snippet does not work and results in an error when reloading the configuration:

haproxy
frontend www
bind :80
http-response add-header X-Path %[path]
# error: sample fetch path can't be reliably used here
haproxy
frontend www
bind :80
http-response add-header X-Path %[path]
# error: sample fetch path can't be reliably used here

To fix this, store the path in a variable. Below, we use http-request set-var to set a variable named txn.mypath in which to store the path value:

haproxy
frontend www
bind :80
http-request set-var(txn.mypath) path
http-response add-header X-Path %[var(txn.mypath)]
# success!
haproxy
frontend www
bind :80
http-request set-var(txn.mypath) path
http-response add-header X-Path %[var(txn.mypath)]
# success!

All variables are scoped, meaning they can only be accessed within the same scope. When you set a variable, you prefix its names with a scope. The scope can be any of the following:

Scope Description
proc the variable is available during all phases
sess the variable is available during a client’s entire TCP session
txn the variable is available during an entire HTTP request-response transaction
req the variable is available during the HTTP request phase only
res the variable is available during the HTTP response phase only

Read a variable Jump to heading

To retrieve the value of a variable, use the var fetch method.

In the next snippet, the req.hdr fetch does not return a value during the response phase and so the if condition always evaluates to false. Therefore, this configuration does not work properly:

haproxy
frontend www
bind :80
http-response add-header X-Message str("My message") if { req.hdr(user-agent) -i -m sub firefox }
# failure: header will not be added
haproxy
frontend www
bind :80
http-response add-header X-Message str("My message") if { req.hdr(user-agent) -i -m sub firefox }
# failure: header will not be added

However, the following works because we use the var fetch method to read the variable txn.useragent, which contains the header’s value, making it available during the response phase:

haproxy
frontend www
bind :80
http-request set-var(txn.useragent) req.hdr(user-agent)
http-response add-header X-Message str("My message") if { var(txn.useragent) -i -m sub firefox }
# success! header is added
haproxy
frontend www
bind :80
http-request set-var(txn.useragent) req.hdr(user-agent)
http-response add-header X-Message str("My message") if { var(txn.useragent) -i -m sub firefox }
# success! header is added

Unset a variable Jump to heading

Use one of the following directives to unset a variable:

  • http-request unset-var
  • http-response unset-var
  • http-response-after-response unset-var

Global variables Jump to heading

Available since

  • HAProxy 2.4
  • HAProxy Enterprise 2.4r1
  • HAProxy ALOHA 13.5

A global variable lives for the lifetime of the load balancer process. Use the set-var directive in the global section to define a global variable.

haproxy
global
# Set a variable named "my_string" to a string value
set-var proc.my_string str("some string value")
# Set a variable named "my_num_var" to an integer value
set-var proc.my_num_var int(123)
haproxy
global
# Set a variable named "my_string" to a string value
set-var proc.my_string str("some string value")
# Set a variable named "my_num_var" to an integer value
set-var proc.my_num_var int(123)

Once a variable is defined, you can use it in various parts of the configuration file such as ACLs, log formats, and HTTP header values by using the var fetch method.

haproxy
frontend www
bind :80
http-response set-header X-MyString %[var(proc.my_string)]
http-response set-header X-MyNumber %[var(proc.my_num_var)]
haproxy
frontend www
bind :80
http-response set-header X-MyString %[var(proc.my_string)]
http-response set-header X-MyNumber %[var(proc.my_num_var)]

Environment variables Jump to heading

Environment variables are defined outside of the load balancer in the operating system or container environment, and then passed to the load balancer when it starts. You can use environment variables to alter the configuration based on the context in which the load balancer is running. For example, get the IP address to bind to, the destination for logs, or a login password.

By using environment variables to define configuration values, you can reduce the amount of hard-coded values in your configuration files and make it easier to reuse configuration values across multiple load balancer servers.

Set environment variables in the service file Jump to heading

When the load balancer runs as a system service, then one way to add environment variables is to append them to the Environment line in the service file. For example, in the file /lib/systemd/system/hapee-2.7-lb.service, we set several environment variables, including the IP address to bind to:

hapee-2.7-lb.service
ini
[Service]
Environment="CONFIG=/etc/hapee-2.7/hapee-lb.cfg" "PIDFILE=/run/hapee-2.7-lb.pid" "IP=192.168.1.10"
hapee-2.7-lb.service
ini
[Service]
Environment="CONFIG=/etc/hapee-2.7/hapee-lb.cfg" "PIDFILE=/run/hapee-2.7-lb.pid" "IP=192.168.1.10"

Set an environment variable with sentenv and presetenv Jump to heading

You can also use setenv in the global section of your configuration to set environment variables. This will override an existing environment variable that has the same name.

Below, we use sentenv in the global section to override the IP variable:

haproxy
global
setenv IP 192.168.1.11
haproxy
global
setenv IP 192.168.1.11

Alternatively, use the presetenv directive to set an environment variable only if it has not already been set. If that variable is already set, it will not be overridden.

Below, we use presetenv in the global section to set the IP variable only if it has not already been set.

haproxy
global
presetenv IP 192.168.1.11
haproxy
global
presetenv IP 192.168.1.11

Read an environment variable Jump to heading

To read the value of an environment variable, precede it with a dollar sign and surround it with double quotes. Optionally, enclose it in curly braces.

In this example, we read several variables in the configuration.

haproxy
global
setenv IP 192.168.56.10
setenv PORT 8080
setenv USER foo
setenv PASS bar
setenv DEFAULT_BACKEND be_app
setenv LOG_ADDRESS 192.168.56.5
setenv LOG_LEVEL notice
defaults
# Set syslog logging
log "$LOG_ADDRESS" local0 "$LOG_LEVEL"
userlist credentials
# Set a Basic auth username and password
user "$USER" insecure-password "$PASS"
frontend fe_main
# Set the IP address and port using variables
bind "$IP":"$PORT"
# enforce Basic authentication
http-request auth unless { http_auth(credentials) }
default_backend "$DEFAULT_BACKEND"
haproxy
global
setenv IP 192.168.56.10
setenv PORT 8080
setenv USER foo
setenv PASS bar
setenv DEFAULT_BACKEND be_app
setenv LOG_ADDRESS 192.168.56.5
setenv LOG_LEVEL notice
defaults
# Set syslog logging
log "$LOG_ADDRESS" local0 "$LOG_LEVEL"
userlist credentials
# Set a Basic auth username and password
user "$USER" insecure-password "$PASS"
frontend fe_main
# Set the IP address and port using variables
bind "$IP":"$PORT"
# enforce Basic authentication
http-request auth unless { http_auth(credentials) }
default_backend "$DEFAULT_BACKEND"

In ACL expressions, which expect a fetch method, use the env method to read the variable. Below, we read the environment variable MAINTENANCE_ON when deciding whether to show a down for maintenance web page.

haproxy
global
# Use 1 for true and 0 for false
setenv MAINTENANCE_ON 1
frontend fe_main
bind :80
# Show a 'down for maintenance' page
http-request return status 503 content-type text/html file /maintenance.html if { env(MAINTENANCE_ON) -m bool }
default_backend be_app
haproxy
global
# Use 1 for true and 0 for false
setenv MAINTENANCE_ON 1
frontend fe_main
bind :80
# Show a 'down for maintenance' page
http-request return status 503 content-type text/html file /maintenance.html if { env(MAINTENANCE_ON) -m bool }
default_backend be_app

See also Jump to heading

Do you have any suggestions on how we can improve the content of this page?