Quickstart HAProxy Community Edition dataplaneAPI

This guide was written after starting up a brand new Ubuntu Server on 22.04 and details the steps taken to quickly get the dataplaneapi up and running.

sudo apt-get update
sudo apt-get install haproxy

Run this to see what version is installed

haproxy -v 

For the sake of this discussion I have HAProxy 2.4.22

Running uname -a or uname -m told me I have x86_64 - That is amd64 architecture

Pick the package that you need from this page:

Note: API just needs to be a newer version than your haproxy version long as you are on HAProxy 1.9 and above.

Iā€™m using this one: dataplaneapi_2.8.3_linux_amd64.deb

Right click on the name and click copy link
https://github.com/haproxytech/dataplaneapi/releases/download/v2.8.3/dataplaneapi_2.8.3_linux_amd64.deb

Curl and download the file into your home directory:

cd ~
curl -JLO https://github.com/haproxytech/dataplaneapi/releases/download/v2.8.3/dataplaneapi_2.8.3_linux_amd64.deb

Install it:

sudo dpkg -i dataplaneapi_2.8.3_linux_amd64.deb

I can see that the dataplane api is now installed:

which dataplaneapi

Returns:

/usr/sbin/dataplaneapi

Make sure that the global configuration has the socket configured:

grep "global\|defaults\|stats socket" /etc/haproxy/haproxy.cfg

It should return this or something similar. If ā€œdefaultsā€ shows before the stats line then you need to
make sure you move the stats line under the global section

grep "global\|defaults\|stats socket" /etc/haproxy/haproxy.cfg

Returns:

global
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
defaults
        log     global

Create the /etc/haproxy/dataplaneapi.yml file

sudo vi /etc/haproxy/dataplaneapi.yml

Paste the configuration from this page on step 5 - change the password as desired:

If you run this command to start it up it merely runs the API and starts the socket.
It will appear to hang but thatā€™s just because itā€™s listening. You can open another ssh session to test it.

sudo dataplaneapi -f /etc/haproxy/dataplaneapi.yml

Testing the api:
With the above command running run this:

curl -X GET --user admin:adminpwd http://localhost:5555/v2/info

Result should be similar to this:

{"api":{"build_date":"2023-06-15T09:07:18.000Z","version":"v2.8.0 b77adc7"},"system":{}}

If itā€™s not then see the green ā€œTipā€ sections for help on this page:

Letā€™s make it load on startup

sudo vi /etc/haproxy/haproxy.cfg

Add these items in (note: the word ā€˜globalā€™ should already be present, donā€™t duplicate it):

global
  master-worker
program api
  command dataplaneapi -f /etc/haproxy/dataplaneapi.yml
  no option start-on-reload

Restart haproxy:

sudo systemctl restart haproxy

This is my current frontend and backend configuration:

frontend frontend1
        bind *:80
        mode http
        option httplog
        log global

        default_backend    be_app

backend be_app
        mode http
        option httpchk HEAD /
        log global
        server app1        172.16.1.32:80 cookie a1 check

If I query for the frontend this way:

curl -X GET   --user admin:adminpwd   "http://127.0.0.1:5555/v2/services/haproxy/configuration/frontends"

The response looks like this:

{"_version":2,"data":[{"default_backend":"be_app","from":"unnamed_defaults_1","httplog":true,"mode":"http","name":"frontend1"}]}

Personally thatā€™s hard to read so I want to install jq and pipe the command to that so it reads like this:

sudo apt-get install jq

Now send it:

curl -X GET   --user admin:adminpwd http://127.0.0.1:5555/v2/services/haproxy/configuration/frontends" | jq

Response is this:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   129  100   129    0     0   262k      0 --:--:-- --:--:-- --:--:--  125k
{
  "_version": 2,
  "data": [
    {
      "default_backend": "be_app",
      "from": "unnamed_defaults_1",
      "httplog": true,
      "mode": "http",
      "name": "frontend1"
    }
  ]
}	
2 Likes

Amazing guide @randomguy
No wonder I was previously unable to make it work on my own, itā€™s quite involved!

{
   "_version": 4,
   "data": [
      {
         "default_backend": "be_app",
         "from": "RandomGuyRocks",
         "httplog": true,
         "mode": "http",
         "name": "Glorious"
      }
   ]
}

For any future readers thereā€™s some good examples on using it here:

Something to watch for is notice that a frontend configuration and a bind configuration are two different things so make sure you create both as needed.

Hi @randomguy Nate, any chance you could add to the guide these topics?:

  • Creating a server
  • Adding a server to a backend
  • How to get the ā€œversionā€

Thank you.

Just to be clear are you looking for the dataplane api version or the HAProxy version?

Hi @Yosu_Cadilla the way I commonly work through API stuff is to configure the object by hand and then run a call to the API to get the data and see what it looks like. Once I have a base structure understanding then the manuals and reference become helpful. I am NOT a programmer or the best person for this but this is how I do it.

For example

admin@HAProxy:~$ curl -k -X GET   --user admin:adminpwd "https://172.16.1.2:5555/v2/services/haproxy/configuration" | jq -M . | grep -i server
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8257    0  8257    0     0   719k      0 --:--:-- --:--:-- --:--:--  733k
    "description": "Returns an array of all servers that are configured in specified backend.",
    "title": "Return an array of servers",
    "url": "/services/haproxy/configuration/servers"
    "description": "Returns an array of all configured nameservers.",
    "title": "Return an array of nameservers",
    "url": "/services/haproxy/configuration/nameservers"
    "description": "Returns an array of all server templates that are configured in specified backend.",
    "title": "Return an array of server templates",
    "url": "/services/haproxy/configuration/server_templates"
    "title": "Return an array of all Server Switching Rules",
    "url": "/services/haproxy/configuration/server_switching_rules"

From this I can see that I want servers

admin@HAProxy:~$ curl -k -X GET   --user admin:adminpwd "https://172.16.1.2:5555/v2/services/haproxy/configuration/servers?parent_type=backend&parent_name=be_http" | jq -M .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    79  100    79    0     0  11570      0 --:--:-- --:--:-- --:--:-- 13166
{
  "_version": 16,
  "data": [
    {
      "address": "172.16.1.32",
      "name": "server_1",
      "port": 80
    }
  ]
}

To reverse the process I just pull up the docs - HAProxy Data Plane API

Thereā€™s an ā€œexampleā€ tab so I can just take that and send it (or use my data from above).

admin@HAProxy:~$ curl -k -X POST \
  --user admin:adminpwd \
  -H "Content-Type: application/json" \
  -d '{
      "address": "172.16.1.33",
      "name": "server_2",
      "port": 80
    }' \
  "https://172.16.1.2:5555/v2/services/haproxy/configuration/servers?backend=be_http"
{"code":400,"message":"13: version or transaction not specified, specify only one"}

Notice that I changed from using ?parent_type=backend&parent_name=be_http to just ?backend=be_http. Thatā€™s just to illustrate the differences. That post should do the trick of creating a server and assigning it.

Oh but look I got an error! So check the reference doc and youā€™ll see ā€œQUERY-STRING PARAMETERSā€ at the top. Notice that version is an option:

admin@HAProxy:~$ curl -k -X POST   --user admin:adminpwd   -H "Content-Type: application/json"   -d '{
      "address": "172.16.1.33",
      "name": "server_2",
      "port": 80
    }'   "https://172.16.1.2:5555/v2/services/haproxy/configuration/servers?backend=be_http&version=1"
{"code":409,"message":"15: version in configuration file is 16, given version is 1"}

I just tagged that variable ā€œversionā€ on the end and dang another error but fairly clear. A quick adjustment to the version string and Iā€™m all set.

admin@HAProxy:~$ curl -k -X POST   --user admin:adminpwd   -H "Content-Type: application/json"   -d '{
      "address": "172.16.1.33",
      "name": "server_2",
      "port": 80
    }'   "https://172.16.1.2:5555/v2/services/haproxy/configuration/servers?backend=be_http&version=16"
{"address":"172.16.1.33","name":"server_2","port":80}

My config file now has this (I cut a few lines just to make it easier to read). So it created the server and assigned it.

backend be_http from unnamed_defaults_1
  server server_1 172.16.1.32:80
  server server_2 172.16.1.33:80

Thatā€™s how you can walk through the API and also use the reference to find what you need. I did a search for ā€œversionā€ and nothing showed up in the docs so I just jump on down to the root and start working through it:

admin@HAProxy:~$ curl -k -X GET   --user admin:adminpwd "https://172.16.1.2:5555/v2/"  | jq -M .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1259  100  1259    0     0   110k      0 --:--:-- --:--:-- --:--:--  111k
[
  {
    "description": "Return API, hardware and OS information",
    "title": "Return API, hardware and OS information",
    "url": "/info"
  },
  ...snip...

Ah that looks promising

admin@HAProxy:~$ curl -k -X GET   --user admin:adminpwd "https://172.16.1.2:5555/v2/info"  | jq -M
.
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    94  100    94    0     0  13599      0 --:--:-- --:--:-- --:--:-- 15666
{
  "api": {
    "build_date": "2024-01-02T12:00:36.000Z",
    "version": "v2.8.4-ee3 8182e868"
  },
  "system": {}
}

Thereā€™s a ton more to explore and play with but hopefully this gives you some insight into how you can leverage the docs and the API.

1 Like

Reverse engineering the HAPDPAPI!
Itā€™s a good way to ā€œbuildā€ the json indeed.
Thanks !

@Yosu_Cadilla Why not use one of the available Terraform providers to configure HAProxy, works like a charm fairly well-documented and simple to use Terraform Registry