# HAProxy Discovery

# Introduction

This HAProxy discovery plugin for Pandora FMS is designed to automate the monitoring of your HAProxy load balancers by leveraging the detailed information exposed by the CSV stats endpoint (`/stats;csv`). By interacting with that endpoint, the plugin collects real-time metrics that are crucial to understanding the performance and health of your HAProxy environment, including sessions, transferred bytes, errors, queues, health checks, and much more. For every HAProxy URL configured, the plugin will create one agent in Pandora FMS with one module per available metric.

# Prerrequisites

- The plugin is distributed as a compiled binary that already includes all the dependencies required for its use, so it does not require Python or any additional libraries to be installed.
- The HAProxy stats endpoint must be enabled and reachable (port and URI configured in `haproxy.cfg`). See the [HAProxy Configuration section](https://pandorafms.com/guides/public/books/haproxy-discovery-lL4/page/haproxy-configuration) for the required steps.

# HAProxy Configuration

In order for the plugin to gather statistics, HAProxy must expose the `/stats;csv` endpoint. This is done by editing the `haproxy.cfg` file (default location: `/etc/haproxy/haproxy.cfg`).

## Minimum configuration (no authentication, no SSL)

Add a dedicated `frontend` for statistics:

```
frontend stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s

```

With this configuration the plugin will consume the URL:

```
http://<SERVER_IP>:8404/stats

```

> The plugin automatically normalizes the URL by appending the `;csv` suffix and the `norefresh` parameter when missing, so it is enough to provide the base stats URL.

## Configuration with basic authentication

To protect the endpoint with a username and password, define a `userlist` and apply `http-request auth` on the stats frontend:

```
frontend stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s

    acl auth_ok http_auth(stats_users)
    http-request auth realm stats if !auth_ok

userlist stats_users
    user admin password $6$rounds=5000$<SHA512_HASH>

```

Generate the password hash with `mkpasswd` or `openssl`:

```bash
mkpasswd -m sha-256 mypassword
# or
openssl passwd -6 mypassword

```

In the plugin, the same `username` and `password` must be provided through `--user` / `--password` (or the `username` / `password` fields in the configuration file).

## Configuration with SSL/TLS

To serve the stats over HTTPS, add `ssl crt` to the `bind` directive:

```
frontend stats
    bind *:8404 ssl crt /etc/haproxy/certs/stats.pem
    stats enable
    stats uri /stats
    stats refresh 10s

```

Generate a self-signed certificate for testing with:

```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/haproxy/certs/stats.key \
  -out /etc/haproxy/certs/stats.crt \
  -subj "/CN=localhost"
cat /etc/haproxy/certs/stats.crt /etc/haproxy/certs/stats.key > /etc/haproxy/certs/stats.pem

```

In the plugin, point to the URL with the `https://` scheme and set the `--ssl` (or `verify_ssl`) parameter depending on whether the certificate should be validated:

- `verify_ssl = true` → for valid certificates in production.
- `verify_ssl = false` → for self-signed certificates or testing environments.

## Complete configuration (SSL + authentication)

```
global
    maxconn 4096

defaults
    mode http
    timeout connect 5s
    timeout client 30s
    timeout server 30s

frontend stats
    bind *:8404 ssl crt /etc/haproxy/certs/stats.pem
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if TRUE

    acl auth_ok http_auth(stats_users)
    http-request auth realm stats if !auth_ok

userlist stats_users
    user admin password $6$rounds=5000$<SHA512_HASH>

frontend myapp
    bind *:80
    default_backend servers

backend servers
    server s1 127.0.0.1:8080 check

```

After modifying `haproxy.cfg`, reload the service to apply the changes:

```bash
sudo systemctl reload haproxy

```

## Verification

To confirm that the endpoint is responding correctly, you can make a manual request to the stats CSV:

```bash
curl -u admin:mypassword http://192.168.0.10:8404/stats;csv

```

The output must be a CSV whose first record is the header with the column names (`# pxname,svname,qcur,qmax,...`) and the following rows contain the data of each `frontend`, `backend` and `server`.

# Parameters

**Simple mode**

<table border="1" id="bkmrk-haproxy-simple-params" style="width: 66.2963%;"><tbody><tr><td style="width: 21.7907%;">--urls</td><td style="width: 77.9359%;">HAProxy stats endpoint URLs, comma-separated. Each URL will create one agent.</td></tr><tr><td style="width: 21.7907%;">--user</td><td style="width: 77.9359%;">username if the HAProxy endpoint requires basic authentication, optional</td></tr><tr><td style="width: 21.7907%;">--password</td><td style="width: 77.9359%;">password if the HAProxy endpoint requires basic authentication, optional</td></tr><tr><td style="width: 21.7907%;">--ssl</td><td style="width: 77.9359%;">whether the URL has an HTTPS certificate to be verified, optional</td></tr><tr><td style="width: 21.7907%;">--prefix</td><td style="width: 77.9359%;">prefix for the module names, optional</td></tr><tr><td style="width: 21.7907%;">--transfer\_mode</td><td style="width: 77.9359%;">data transfer mode (native or tentacle), optional</td></tr><tr><td style="width: 21.7907%;">--tentacle\_ip</td><td style="width: 77.9359%;">tentacle IP, optional</td></tr><tr><td style="width: 21.7907%;">--tentacle\_port</td><td style="width: 77.9359%;">tentacle port, optional</td></tr><tr><td style="width: 21.7907%;">--interval</td><td style="width: 77.9359%;">monitoring interval in seconds, optional</td></tr><tr><td style="width: 21.7907%;">--allow\_list</td><td style="width: 77.9359%;">regular expression to include only modules whose name matches, optional</td></tr><tr><td style="width: 21.7907%;">--deny\_list</td><td style="width: 77.9359%;">regular expression to exclude modules whose name matches, optional</td></tr><tr><td style="width: 21.7907%;">--monitor\_frontends</td><td style="width: 77.9359%;">monitor frontend rows (type=0), optional</td></tr><tr><td style="width: 21.7907%;">--monitor\_backends</td><td style="width: 77.9359%;">monitor backend rows (type=1), optional</td></tr><tr><td style="width: 21.7907%;">--monitor\_servers</td><td style="width: 77.9359%;">monitor server rows (type=2), optional</td></tr></tbody></table>

**Advanced mode**

<table border="1" id="bkmrk-haproxy-advanced-params"><tbody><tr><td>--conf</td><td>path to the configuration file</td></tr><tr><td>--conf\_targets</td><td>path to the file with the HAProxy URLs (mandatory when using --conf)</td></tr></tbody></table>

**Configuration file (--conf)**

```
username= username if the HAProxy endpoint requires basic authentication, optional
password= password if the HAProxy endpoint requires basic authentication, optional
verify_ssl= whether the URL has an HTTPS certificate to be verified, optional
prefix= prefix for the module names, optional
transfer_mode= data transfer mode (native or tentacle), optional
tentacle_ip= tentacle IP, optional
tentacle_port= tentacle port, optional
agents_group= name of the agent group the created agents will be assigned to, optional
agents_group_id= ID of the agent group the created agents will be assigned to, optional
interval= monitoring interval in seconds, optional
allow_list= regular expression to include only modules whose name matches, optional
deny_list= regular expression to exclude modules whose name matches, optional
monitor_frontends= monitor frontend rows (type=0), optional
monitor_backends= monitor backend rows (type=1), optional
monitor_servers= monitor server rows (type=2), optional

```

**Example**

```ini
[CONF]
username=admin
password=12345
verify_ssl=true
prefix=haproxy_
transfer_mode=native
tentacle_ip=127.0.0.1
tentacle_port=41121
interval=300
allow_list=
deny_list=.*_wredis|.*_wretr
monitor_frontends=true
monitor_backends=true
monitor_servers=true

```

Targets file (`--conf_targets`):

```
http://192.168.0.10:8404/stats
http://192.168.0.11:8404/stats

```

# Manual execution

The plugin execution format is as follows:

```bash
./pandora_haproxy --urls <HAProxy endpoint URLs comma-separated> --user <username> --password <password> --ssl <true|false> --prefix <prefix> --transfer_mode <native|tentacle> --tentacle_ip <tentacle IP> --tentacle_port <tentacle port> --interval <interval> --allow_list <regex> --deny_list <regex> --monitor_frontends <true|false> --monitor_backends <true|false> --monitor_servers <true|false> --conf <path to configuration file> --conf_targets <path to URLs file>

```

Examples:

to run the simple mode

```bash
./pandora_haproxy --urls http://192.168.0.10:8404/stats,http://192.168.0.11:8404/stats --user admin --password 12345 --ssl false --transfer_mode native --tentacle_ip 127.0.0.1 --tentacle_port 41121

```

to run the advanced mode

```bash
./pandora_haproxy --conf /etc/pandora/haproxy.conf --conf_targets /etc/pandora/haproxy_targets.conf

```

The execution will return a JSON output with information about the run, and will generate an XML file for every monitored agent (in tentacle mode) that will be sent to the Pandora FMS server using the transfer method configured. In `native` mode the data is exposed in the `monitoring_data` field of the JSON output to be consumed by the Discovery server.

# Discovery

This plugin can be integrated with Pandora FMS *Discovery*.

To do so, the ".disco" package must be loaded. It can be downloaded from the Pandora FMS library:

[https://pandorafms.com/library/](https://pandorafms.com/library/)

Once loaded, HAProxy instances can be monitored by creating *Discovery* tasks from the *Management &gt; Discovery &gt; Application &gt; HAProxy* section.

Each task will require the following minimum data in the **HAProxy Basic** step:

- **HAProxy Stats URLs:** HAProxy stats endpoint URLs, comma-separated or one per line. Each URL will create one agent.
- **Username:** HAProxy endpoint user if basic authentication is required, optional
- **Password:** HAProxy endpoint password if basic authentication is required, optional
- **Verify SSL:** enabled if the URL has an SSL certificate to be verified, disabled by default
- **Transfer mode:** transfer mode (native or tentacle), optional
- **Tentacle IP:** tentacle IP, optional
- **Tentacle port:** Tentacle port, optional

[![](https://pandorafms.com/guides/public/uploads/images/gallery/2026-06/scaled-1680-/image-1780415354936.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2026-06/image-1780415354936.png)

In the **HAProxy Advanced** step the following additional options can be configured:

- **Module prefix:** prefix to be added to every created module name, optional
- **Monitor frontends:** enables monitoring of frontend rows (type=0), optional
- **Monitor backends:** enables monitoring of backend rows (type=1), optional
- **Monitor servers:** enables monitoring of server rows (type=2), optional
- **Allow list:** regular expression to include only modules whose name matches, optional
- **Deny list:** regular expression to exclude modules whose name matches, optional

[![](https://pandorafms.com/guides/public/uploads/images/gallery/2026-06/scaled-1680-/image-1780415365555.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2026-06/image-1780415365555.png)

Successfully completed tasks will have an execution summary with the following information:

- **Total agents**: Total number of agents generated by the task.
- **Total modules:** Total number of modules generated by the task.

# Agent and modules generated by the plugin

The plugin will create one agent for every HAProxy URL configured. The agent name is computed as an MD5 hash of the URL `netloc`, and the alias is set to that same `netloc` (for example, `192.168.0.10:8404`). Each agent includes the modules obtained by parsing the HAProxy CSV stats endpoint.

The `status` module is created **always** for every row, regardless of the monitor tokens, in order to alert on `DOWN`/`MAINT`/`STOP` states. The remaining numeric fields are included as `generic_data` (integer/decimal) or `generic_data_string` (string) modules, following the format `<pxname>_<svname>_<field>`.

The main fields available in the HAProxy CSV that generate modules are:

```bash
pxname: Proxy name (frontend/backend/listener).
svname: Service name (FRONTEND/BACKEND/server name).
qcur: Current queued requests.
qmax: Max queued requests.
scur: Current sessions.
smax: Max sessions.
slim: Configured session limit.
stot: Cumulative sessions.
bin: Bytes in.
bout: Bytes out.
dreq: Requests denied (security).
dresp: Responses denied (security).
ereq: Request errors.
econ: Connection errors to backend.
eresp: Response errors.
wretr: Connection retries.
wredis: Redispatches to another server.
status: Status (UP/DOWN/MAINT/STOP/...) — always monitored.
weight: Total weight / server weight.
act: Active servers (backend) / server active.
bck: Backup servers (backend) / server backup.
chkfail: Failed health checks.
chkdown: UP->DOWN transitions.
lastchg: Seconds since last UP<->DOWN transition.
downtime: Total downtime (seconds).
qlimit: Configured maxqueue for the server.
pid: Process ID.
iid: Unique proxy ID.
sid: Server ID (unique inside the proxy).
throttle: Current throttle percentage.
lbtot: Times the server was selected.
tracked: ID of proxy/server if tracking is enabled.
type: Type (0=frontend, 1=backend, 2=server, 3=socket).
rate: Sessions per second (last second).
rate_lim: Configured limit on new sessions/s.
rate_max: Max sessions per second.
check_status: Status of the last health check.
check_code: Layer 5-7 check code.
check_duration: Time in ms of the last health check.
hrsp_1xx: HTTP responses with 1xx code.
hrsp_2xx: HTTP responses with 2xx code.
hrsp_3xx: HTTP responses with 3xx code.
hrsp_4xx: HTTP responses with 4xx code.
hrsp_5xx: HTTP responses with 5xx code.
hrsp_other: HTTP responses with other codes.
hanafail: Failed health checks details.
req_rate: HTTP requests per second.
req_rate_max: Max HTTP requests per second.
req_tot: Total HTTP requests received.
cli_abrt: Data transfers aborted by the client.
srv_abrt: Data transfers aborted by the server.
comp_in: HTTP response bytes fed to the compressor.
comp_out: HTTP response bytes emitted by the compressor.
comp_byp: Bytes that bypassed the HTTP compressor.
comp_rsp: HTTP responses that were compressed.
lastsess: Seconds since the last session was assigned.
last_chk: Last health check contents/error.
last_agt: Last agent check contents/error.
qtime: Average queue time (ms) over the last 1024 requests.
ctime: Average connect time (ms) over the last 1024 requests.
rtime: Average response time (ms) over the last 1024 requests.
ttime: Average total session time (ms) over the last 1024 requests.
agent_status: Status of the last agent check.
agent_code: Numeric code reported by the agent.
agent_duration: Time in ms of the last agent check.
check_desc: Human-readable description of check_status.
agent_desc: Human-readable description of agent_status.
check_rise: Server's rise parameter used by checks.
check_fall: Server's fall parameter used by checks.
check_health: Server's health check value.
agent_rise: Agent's rise parameter.
agent_fall: Agent's fall parameter.
agent_health: Agent's health parameter.
addr: Address:port or unix socket.
cookie: Server's cookie value or backend's cookie name.
mode: Proxy mode (tcp, http, health, unknown).
algo: Load balancing algorithm.
conn_rate: Connections over the last elapsed second.
conn_rate_max: Highest known conn_rate.
conn_tot: Cumulative number of connections.
intercepted: Cumulative intercepted requests.
dcon: Requests denied by tcp-request connection rules.
dses: Requests denied by tcp-request session rules.

```

The `status` module is translated to a numeric value according to the following mapping: 5=UP, 4=OPEN, 3=NOLB, 2=MAINT, 1=STOP/STOPPING, 0=DOWN, which allows configuring alerts based on warning (2-4) and critical (0-2) thresholds.