# CrowdSec WAF QuickStart for HAProxy (SPOA)

Protect web applications running behind [HAProxy](https://www.haproxy.org/) with CrowdSec's [AppSec (WAF) Component](https://docs.crowdsec.net/docs/next/appsec/intro.md#introduction), using the HAProxy SPOA remediation component to forward HTTP requests.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

Make sure the following are already done on the machine running HAProxy (each is a single-page install guide):

1. **CrowdSec Security Engine** installed and running — see the [Linux quickstart](https://docs.crowdsec.net/u/getting_started/installation/linux.md).
2. **HAProxy** already running and proxying your application(s).
3. **HAProxy SPOA bouncer** (`crowdsec-haproxy-spoa-bouncer`) installed and registered against the CrowdSec LAPI. See the [SPOA bouncer guide](https://docs.crowdsec.net/u/bouncers/haproxy_spoa.md).

## 1. Install the AppSec rule collections[​](#1-install-the-appsec-rule-collections "Direct link to 1. Install the AppSec rule collections")

SHCOPY

```
sudo cscli collections install \
    crowdsecurity/appsec-virtual-patching \
    crowdsecurity/appsec-generic-rules
```

This pulls the [`appsec-virtual-patching`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-virtual-patching) collection (rules for known CVEs, auto-updated daily) and the [`appsec-generic-rules`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-generic-rules) collection (common attack patterns), plus the default AppSec configuration.

## 2. Turn on the AppSec Component[​](#2-turn-on-the-appsec-component "Direct link to 2. Turn on the AppSec Component")

Create the acquisition file, then restart CrowdSec:

SHCOPY

```
sudo mkdir -p /etc/crowdsec/acquis.d
sudo tee /etc/crowdsec/acquis.d/appsec.yaml > /dev/null <<'EOF'
appsec_configs:
  - crowdsecurity/appsec-default
labels:
  type: appsec
listen_addr: 127.0.0.1:7422
source: appsec
EOF
sudo systemctl restart crowdsec
```

warning

Keep `listen_addr` on `127.0.0.1` — the AppSec Component must only be reachable from your reverse proxy.

## 3. Enable AppSec forwarding in the SPOA bouncer[​](#3-enable-appsec-forwarding-in-the-spoa-bouncer "Direct link to 3. Enable AppSec forwarding in the SPOA bouncer")

Edit `/etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml` and add the `appsec_url` plus the `appsec` block under your host(s):

/etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml

YAML/etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yamlCOPY

```
# AppSec (WAF forwarding)
appsec_url: "http://127.0.0.1:7422"
appsec_timeout: "200ms"

hosts:
  - host: "*"
    appsec:
      always_send: false
```

Restart the bouncer:

SHCOPY

```
sudo systemctl restart crowdsec-spoa-bouncer
```

note

If AppSec runs on a different host (or in containers), update `appsec_url` to the correct reachable address.

## 4. Verify[​](#4-verify "Direct link to 4. Verify")

Hit an endpoint that should trip an AppSec rule (adjust the URL to match your HAProxy frontend):

SHCOPY

```
curl -I http://<your-haproxy-url>/.env
```

You should get an `HTTP/1.1 403 Forbidden` response.

Check that CrowdSec recorded the block:

SHCOPY

```
sudo cscli metrics show appsec
```

What just happened?

1. `curl` hit HAProxy at `/.env`.
2. HAProxy forwarded the request to the SPOA remediation component.
3. The bouncer queried the AppSec Component at `appsec_url`.
4. The request matched the [`vpatch-env-access`](https://app.crowdsec.net/hub/author/crowdsecurity/appsec-rules/vpatch-env-access) rule.
5. AppSec answered `403`; HAProxy blocked the request.

## AppSec limitations with HAProxy SPOA[​](#appsec-limitations-with-haproxy-spoa "Direct link to AppSec limitations with HAProxy SPOA")

HAProxy SPOA forwarding is constrained by HAProxy/SPOE/SPOA mechanics:

* Request bodies are only available if you enable buffering (`option http-buffer-request`) and must fit within tight size limits (commonly capped at \~50 KB).
* When the body is too large (uploads, large JSON, etc.), you typically fall back to a "no-body" SPOE group, which means **body-dependent WAF rules cannot match**.
* This is not full streaming inspection: SPOA works with what HAProxy can capture within buffer/frame limits.

CrowdSec AppSec is a single source of truth for rules — you can point multiple WAF-capable integrations at the same AppSec endpoint so rule updates stay in sync.

Recommended layered approach:

* Use HAProxy SPOA for **edge enforcement** (IP/range/country decisions, ban/captcha) and lightweight WAF evaluation when the request fits within the configured limits.

* Put a full-featured L7 proxy/WAF-capable integration **downstream** (or protect the app directly) when you need deeper inspection of large bodies, file uploads, or application-specific request parsing. Examples:

  <!-- -->

  * [Nginx/OpenResty](https://docs.crowdsec.net/docs/next/appsec/quickstart/nginxopenresty.md)
  * [Traefik](https://docs.crowdsec.net/docs/next/appsec/quickstart/traefik.md)
  * [WordPress](https://docs.crowdsec.net/docs/next/appsec/quickstart/wordpress.md)

## Next steps[​](#next-steps "Direct link to Next steps")

* Monitor WAF alerts with `sudo cscli alerts list` or in the [CrowdSec Console](https://app.crowdsec.net).
* Review the [AppSec troubleshooting guide](https://docs.crowdsec.net/docs/next/appsec/troubleshooting.md) and the [HAProxy SPOA bouncer docs](https://docs.crowdsec.net/u/bouncers/haproxy_spoa.md) if you need to investigate or refine the deployment.
* Explore [WAF deployment strategies](https://docs.crowdsec.net/docs/next/appsec/advanced_deployments.md) if you want to expand beyond this initial setup.
