Announcing HAProxy Data Plane API 2.6
Version Update

In HAProxy Data Plane API version 2.6, we continued the effort of expanding support for HAProxy configuration keywords, as this has been the priority with this release cycle, and it will be in the next one too to meet our goal of achieving complete feature parity with both the HAProxy configuration and Runtime API. This will enable you to use HAProxy Data Plane API for configuring HAProxy without any gaps in functionality.

With that in mind, we also implemented quality of life improvements, namely adding a health check endpoint that returns the status of the HAProxy process, and we upgraded to Go 1.18 and updated all dependencies that we are using so users can benefit from bug and security fixes.

Extended Keyword Support

We updated the HAProxy Data Plane API to cover more HAProxy configuration keywords, with the goal of making the API a full-fledged way to configure HAProxy. In this section, you’ll see everything we’ve added.

The ring section

Since HAProxy 2.2, you’ve had the ability to define a section called ring which creates a FIFO buffer in memory where you can store HAProxy’s logs temporarily before forwarded them to a remote syslog server. The benefit of using a ring buffer is that it allows you to forward log messages to a remote syslog server using TCP. A traditional log line in an HAProxy configuration forwards logs using the UDP protocol. Relaying logs using UDP avoids any slowdowns, since UDP is a connectionless protocol, but the downside is that there is no guarantee that every log message will arrive at the destination. UDP is fire and forget.

global
# Uses a UDP port
log 192.168.56.30:514 local0

However, by defining a ring section you can buffer log messages and then communicate with a syslog server over a TCP port without slowing down HAProxy since the log forwarding happens in the background. The TCP protocol is a connected protocol and guarantees delivery of all messages. In the snippet below, we define a ring section for buffering HAProxy logs.

ring logbuffer
description "My log buffer"
format rfc3164
maxlen 1200
size 32764
timeout connect 5s
timeout server 10s
# Uses a TCP port
server mysyslogsrv 192.168.56.30:514 log-proto octet-count

Then in the global section of your configuration, your log line would specify the ring buffer instead of an IP address and port:

global
log ring@logbuffer local0 info

You can now create a ring section through the API by using the /services/haproxy/configuration/rings endpoint, as shown below.

$ curl -X POST \
--user admin:password \
-H "Content-Type: application/json" \
-d '{
"name": "logbuffer",
"description": "My log buffer",
"format": "rfc3164",
"maxlen": 1200,
"size": 32764,
"timeout_connect": 5000,
"timeout_server": 1000
}' \
"http://127.0.0.1:5555/v2/services/haproxy/configuration/rings?version=1"

Then add a server to it by using the /services/haproxy/configuration/servers endpoint, setting the URL parameter parent_type to ring and parent_name to the name of the ring section.

$ curl -X POST \
-–user admin:password \
-H "Content-Type: application/json" \
-d '{
"name": "mysyslogsrv",
"address": "192.168.56.30",
"port": 514,
"log_proto": "octet-count"
}' \
"http://127.0.0.1:5555/v2/services/haproxy/configuration/servers?parent_type=ring&parent_name=logbuffer&version=2"
DEPRECATION WARNING

To remain backward compatible, the server endpoint will still have the backend query string parameter, but it will be removed in a future version. Going forward please use parenttype and parentname query string parameters to specify the section to which a server resource belongs.

Add the required log line to your global section by invoking the /services/haproxy/configuration/log_targets endpoint.

The log-forward section

Note

An earlier version of this post recommended using the log-forward section for load balancing, but this has been amended to indicate that the use case is primarily log forwarding, since health checking is not yet available.

While the ring section pertains to forwarding HAProxy’s own logs, another section named log-forward pertains to forwarding log messages for other applications to a list of syslog servers. This gets its own section in order to support relaying syslog messages over UDP, while in general HAProxy is a TCP-based proxy. The log-forward section was introduced in HAProxy 2.3 and looks like this:

log-forward sylog
# receive log messages on UDP port
dgram-bind 192.168.56.20:514
# receive log messages on TCP port
bind 192.168.56.20:514
# forward to this syslog server using UDP
log 192.168.56.21:514 local0

You can create a log-forward section through the API by using the new /services/haproxy/configuration/log_forwards endpoint.

$ curl -X POST \
-–user admin:password \
-H "Content-Type: application/json" \
-d '{
"name": "sylog",
"maxconn": 100
}' \
"http://127.0.0.1:5555/v2/services/haproxy/configuration/log_forwards?version=3"

Then add a bind line for receiving syslog traffic over TCP and a dgram_bind line for receiving it over UDP by calling the /services/haproxy/configuration/binds and /services/haproxy/configuration/dgram_binds endpoints:

$ curl -X POST \
-–user admin:password \
-H "Content-Type: application/json" \
-d '{
"address": "192.168.56.20",
"port": 514
}' \
"http://127.0.0.1:5555/v2/services/haproxy/configuration/binds?parent_type=log_forward&parent_name=syslog&version=4"
$ curl -X POST \
-–user admin:password \
-H "Content-Type: application/json" \
-d '{
"address": "192.168.56.20",
"port": 514
}' \
"http://127.0.0.1:5555/v2/services/haproxy/configuration/dgram_binds?log_forward=syslog&version=5"
DEPRECATION WARNING

To remain backward compatible, the bind resource will still have the frontend query string parameter, but it will be removed in a future version. Going forward please use parenttype and parentname query string parameters to specify the section to which a bind resource belongs too.

Finally, add the log servers to which you will forward traffic by invoking the /services/haproxy/configuration/log_targets endpoint.

$ curl -X POST \
-–user admin:password \
-H "Content-Type: application/json" \
-d '{
"address": "192.168.56.21:514",
"facility": "level0",
"sample_range": "1",
"sample_size": 2,
}' \
"http://127.0.0.1:5555/v2/services/haproxy/configuration/log_targets?parent_type=log_forward&parent_name=syslog&version=5"

Global section keywords

With version 2.6, we’re happy to announce that the /services/haproxy/configuration/global endpoint supports all options for the HAProxy global section.

Process management and security:

  • default-path

  • description

  • expose-experimental-directives

  • gid

  • grace

  • insecure-fork-wanted

  • insecure-setuid-wanted

  • issuers-chain-path

  • h2-workaround-bogus-websocket-clients

  • log-tag

  • lua-load-per-thread

  • mworker-max-reloads

  • node

  • numa-cpu-mapping

  • pp2-never-send-local

  • presetenv

  • resetenv

  • uid

  • ulimit-n

  • set-dumpable

  • set-var

  • setenv

  • unix-bind

  • unsetenv

  • strict-limits

SSL tuning options:

  • ssl-default-bind-ciphers

  • ssl-default-bind-ciphersuites

  • ssl-default-bind-curves

  • ssl-default-bind-options

  • ssl-default-server-ciphers

  • ssl-default-server-ciphersuites

  • ssl-default-server-options

  • ssl-dh-param-file

  • ssl-server-verify

  • ssl-skip-self-issued-ca

Performance tuning:

  • busy-polling

  • max-spread-checks

  • maxconnrate

  • maxcomprate

  • maxcompcpuusage

  • maxpipes

  • maxsessrate

  • maxsslconn

  • maxsslrate

  • maxzlibmem

  • noepoll

  • nokqueue

  • noevports

  • nopoll

  • nosplice

  • nogetaddrinfo

  • noreuseport

  • profiling.tasks

  • spread-checks

  • ssl-engine

Defaults, frontend and backend keywords

Version 2.6 of the HAProxy Data Plane API also brings support or all option keywords that can be configured in defaultsbackend, and frontend sections via the /services/haproxy/configuration/defaults, /services/haproxy/configuration/frontends, and /services/haproxy/configuration/backends API endpoints:

  • option abortonclose

  • option checkcache

  • option http-ignore-probes

  • option http-no-delay

  • option http-use-proxy-header

  • option httpslog

  • option independent-streams

  • option nolinger

  • option originalto

  • option persist

  • option prefer-last-server

  • option socket-stats

  • option splice-auto

  • option splice-request

  • option splice-response

  • option spop-check

  • option srvtcpka

  • option tcp-smart-accept

  • option tcp-smart-connect

  • option tcpka

  • option transparent

In addition, we’ve extended the stats object that you can configure in a frontend or backend section to include the following options:

  • stats auth

  • stats http-request

  • stats realm

For the backend and the defaults sections we added support for the server TCP keep-alive options:

  • srvtcpka-cnt

  • srvtcpka-idle

  • Srvtcpka-intvl

For the frontend and the defaults sections we added support for the client TCP keep-alive options:

  • clitcpka-cnt

  • clitcpka-idle

  • clitcpka-intvl

The http-after-response directive

HAProxy 2.6 introduced the http-after-response directive, which applies an action to all responses, even those generated by HAProxy and returned without involving a backend server. People use it to attach HTTP headers to a response when HAProxy returns a redirect, for example. The older http-response directive applies only when the backend server sends the response.

With HAProxy Data Plane API 2.6, you can configure http-after-response directives similarly to how you would configure http-response directives, only using the /services/haproxy/configuration/httpafterresponse_rules endpoint.

$ curl -X POST \
-–user admin:password \
-H "Content-Type: application/json" \
-d '{
"index": 0,
"action": "set-header",
"hdr_name": "Cache-Control",
"hdr_fmt": "no-store,no-cache,private",
}' \
"http://127.0.0.1:5555/v2/services/haproxy/configuration/http_after_response_rules?parent_type=frontend&parent_name=test&version=1"

This will create the following line in your frontend section in the HAProxy configuration file:

frontend test
http-after-response set-header Cache-Control "no-store,no-cache,private"

Health Endpoint

A new endpoint, /health, returns a value indicating whether HAProxy is up and running.

$ curl -X GET \
-–user admin:password \
-H "Content-Type: application/json" \
"http://127.0.0.1:5555/v2/health"
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Thu, 14 Jul 2022 13:01:17 GMT
Content-Length: 22
Connection: close
{
"haproxy": "up"
}

To enable this feature, you must configure the status_cmd field in the HAProxy Data Plane API configuration file (e.g. /etc/haproxy/dataplaneapi.hcl), as shown below.

HCL

haproxy {
config_file = "/etc/haproxy/haproxy.cfg"
haproxy_bin = "haproxy"
reload {
reload_delay = 5
reload_cmd = "systemctl reload haproxy"
restart_cmd = "systemctl restart haproxy"
status_cmd = "systemctl status haproxy"
reload_retention = 1
}
}

YAML

haproxy:
config_file: "/etc/haproxy/haproxy.cfg"
haproxy_bin: "haproxy"
reload:
reload_delay: 5
reload_cmd: "systemctl reload haproxy"
restart_cmd: "systemctl restart haproxy"
status_cmd: "systemctl status haproxy"
reload_retention: 1

Library Updates and Bug Fixes

One of the bigger updates is that the HAProxy Data Plane API project has been migrated to Go 1.18 along with the underlying libraries config-parser and client-native. This allows us to get all the new features of the Go language to improve our codebase, along with some optimizations and, of course, security fixes.

We’ve also updated the go-swagger library we use for code generation to the latest version, which received many bug fixes but introduced some breaking changes for our models package in the client-native project. So, the client-native package has been upgraded to v4. This is important news for all of our contributors, since they will need to update their dev environments for both Go 1.18 and go-swagger 0.29.0.

In addition to that, we did a thorough pass of all the external dependencies used by the HAProxy Data Plane API project and updated those dependencies where needed to benefit from all the bug and security fixes.

Contributors

We’d like to thank the code contributors who helped make this version possible!

Contributor

Area

Amel Husic

FEATURE

Andjelko Horvat

BUG  FEATURE

Andjelko Iharos

BUG  FEATURE

Dinko Korunic

BUG

Connor Edwards

BUG

Dario Tranchitella

BUG  CLEANUP  FEATURE  TEST

Goran Galinec

BUG  CLEANUP  FEATURE

Mark

CLEANUP

Marko Juraga

BUG  BUILD  CLEANUP  DOC   FEATURE

Moemen Mhedhbi

FEATURE

Norwin Schnyder

BUG  FEATURE

Robert Maticevic

BUG  BUILD  CLEANUP  FEATURE  REORG

Seena Fallah

BUG  FEATURE

Zlatko Bratkovic

BUG  BUILD  CLEANUP  FEATURE

Subscribe to our blog. Get the latest release updates, tutorials, and deep-dives from HAProxy experts.