Skip to content

Releases: crowdsecurity/cs-haproxy-spoa-bouncer

v0.2.0

18 Nov 16:17
10eec3b

Choose a tag to compare

Breaking Changes

As outlined in the 0.1.0 release, every minor version before 1.0.0 may contain breaking changes.
Please review the sections below carefully before upgrading to avoid service interruptions.


TL;DR (Key Changes)

  • Parent/worker model removed – the SPOA now runs as a single process.
  • workers, worker_user, worker_group options removed – replaced by listen_tcp / listen_unix.
  • admin_socket removed – the setting is now ignored and can be deleted.
  • Service now runs fully as crowdsec-spoa user – config/log file permissions must allow this.
  • Docker image now runs as crowdsec-spoa.
  • Default log directory moved to /var/log/crowdsec-spoa/ (config change required).

Inner Architecture

In short:
We removed the parent/worker architecture and now run a simpler, single-process model.

Background

Previously:

  • Multiple workers handled incoming SPOE messages from HAProxy.

  • Each worker communicated with a parent process over a Unix socket to fetch:

    • State
    • Decisions
    • Host configuration (e.g. ban / captcha)

This design existed to support multiple SPOA listeners from a single process.

In practice, we found that users almost never configured more than one SPOA listener.
The added complexity:

  • Slowed down feature development,
  • Increased code debt,
  • Made onboarding new contributors harder.

As a result, we have simplified the architecture to a single process that directly handles SPOE messages.

Configuration Changes

We have removed the following YAML options:

  • workers
  • worker_user
  • worker_group

These are replaced with:

listen_tcp: 127.0.0.1:9090
listen_unix: /path/to/unix.sock

Recommendation:
Add these keys to your configuration before upgrading to avoid startup failures.


Admin Socket

Because we no longer support multiple SPOA listeners, the admin socket no longer provides value.

  • The following option has been removed and is now ignored:
admin_socket: /path/to/admin.sock

You can safely remove this key from your configuration.

We know users still need a way to reload the SPOA without dropping in-flight messages from HAProxy.
In a future release, we plan to add a proper systemctl reload hook to handle this cleanly.


Process Owner (systemd Unit)

With the removal of the parent/worker model and the admin socket, the systemd unit now runs entirely as the crowdsec-spoa user.

This improves separation between service accounts and root, but it also means:

  • All files needed by the SPOA must be readable by the crowdsec-spoa group.

For example:

chown root:crowdsec-spoa /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml
chmod 640 /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml

If you have created .local variants of these configuration files, please run equivalent commands for those files as well.

Note:
The DEB/RPM packages are patched to adjust these permissions on upgrade.
If you encounter issues, manually validate permissions/ownership and open an issue on this repository if problems persist.


Dockerfile

The Docker image has also been updated to run as the crowdsec-spoa user.

If you are building the container locally and mounting configuration files, ensure that:

  • The mounted configuration is readable by crowdsec-spoa.

Log Files

Since the systemd unit now runs as crowdsec-spoa, it can no longer write to the root-owned default /var/log directly.

The unit is configured to create a dedicated directory:

/var/log/crowdsec-spoa

Please update your YAML configuration accordingly:

log_dir: /var/log/crowdsec-spoa/

Note:
The DEB/RPM packages may not clean up old log files in previous locations.
After the upgrade, you may want to manually remove any obsolete log files or directories.

v0.2.0-rc5

18 Nov 15:38
10eec3b

Choose a tag to compare

v0.2.0-rc5 Pre-release
Pre-release

Breaking Changes

As outlined in the 0.1.0 release, every minor version before 1.0.0 may contain breaking changes.
Please review the sections below carefully before upgrading to avoid service interruptions.


TL;DR (Key Changes)

  • Parent/worker model removed – the SPOA now runs as a single process.
  • workers, worker_user, worker_group options removed – replaced by listen_tcp / listen_unix.
  • admin_socket removed – the setting is now ignored and can be deleted.
  • Service now runs fully as crowdsec-spoa user – config/log file permissions must allow this.
  • Docker image now runs as crowdsec-spoa.
  • Default log directory moved to /var/log/crowdsec-spoa/ (config change required).

Inner Architecture

In short:
We removed the parent/worker architecture and now run a simpler, single-process model.

Background

Previously:

  • Multiple workers handled incoming SPOE messages from HAProxy.

  • Each worker communicated with a parent process over a Unix socket to fetch:

    • State
    • Decisions
    • Host configuration (e.g. ban / captcha)

This design existed to support multiple SPOA listeners from a single process.

In practice, we found that users almost never configured more than one SPOA listener.
The added complexity:

  • Slowed down feature development,
  • Increased code debt,
  • Made onboarding new contributors harder.

As a result, we have simplified the architecture to a single process that directly handles SPOE messages.

Configuration Changes

We have removed the following YAML options:

  • workers
  • worker_user
  • worker_group

These are replaced with:

listen_tcp: 127.0.0.1:9090
listen_unix: /path/to/unix.sock

Recommendation:
Add these keys to your configuration before upgrading to avoid startup failures.


Admin Socket

Because we no longer support multiple SPOA listeners, the admin socket no longer provides value.

  • The following option has been removed and is now ignored:
admin_socket: /path/to/admin.sock

You can safely remove this key from your configuration.

We know users still need a way to reload the SPOA without dropping in-flight messages from HAProxy.
In a future release, we plan to add a proper systemctl reload hook to handle this cleanly.


Process Owner (systemd Unit)

With the removal of the parent/worker model and the admin socket, the systemd unit now runs entirely as the crowdsec-spoa user.

This improves separation between service accounts and root, but it also means:

  • All files needed by the SPOA must be readable by the crowdsec-spoa group.

For example:

chown root:crowdsec-spoa /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml
chmod 640 /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml

If you have created .local variants of these configuration files, please run equivalent commands for those files as well.

Note:
The DEB/RPM packages are patched to adjust these permissions on upgrade.
If you encounter issues, manually validate permissions/ownership and open an issue on this repository if problems persist.


Dockerfile

The Docker image has also been updated to run as the crowdsec-spoa user.

If you are building the container locally and mounting configuration files, ensure that:

  • The mounted configuration is readable by crowdsec-spoa.

Log Files

Since the systemd unit now runs as crowdsec-spoa, it can no longer write to the root-owned default /var/log directly.

The unit is configured to create a dedicated directory:

/var/log/crowdsec-spoa

Please update your YAML configuration accordingly:

log_dir: /var/log/crowdsec-spoa/

Note:
The DEB/RPM packages may not clean up old log files in previous locations.
After the upgrade, you may want to manually remove any obsolete log files or directories.

v0.2.0-rc4

17 Nov 16:03
d38678c

Choose a tag to compare

v0.2.0-rc4 Pre-release
Pre-release

Breaking Changes

As outlined in the 0.1.0 release, every minor version before 1.0.0 may contain breaking changes.
Please review the sections below carefully before upgrading to avoid service interruptions.


TL;DR (Key Changes)

  • Parent/worker model removed – the SPOA now runs as a single process.
  • workers, worker_user, worker_group options removed – replaced by listen_tcp / listen_unix.
  • admin_socket removed – the setting is now ignored and can be deleted.
  • Service now runs fully as crowdsec-spoa user – config/log file permissions must allow this.
  • Docker image now runs as crowdsec-spoa.
  • Default log directory moved to /var/log/crowdsec-spoa/ (config change required).

Inner Architecture

In short:
We removed the parent/worker architecture and now run a simpler, single-process model.

Background

Previously:

  • Multiple workers handled incoming SPOE messages from HAProxy.

  • Each worker communicated with a parent process over a Unix socket to fetch:

    • State
    • Decisions
    • Host configuration (e.g. ban / captcha)

This design existed to support multiple SPOA listeners from a single process.

In practice, we found that users almost never configured more than one SPOA listener.
The added complexity:

  • Slowed down feature development,
  • Increased code debt,
  • Made onboarding new contributors harder.

As a result, we have simplified the architecture to a single process that directly handles SPOE messages.

Configuration Changes

We have removed the following YAML options:

  • workers
  • worker_user
  • worker_group

These are replaced with:

listen_tcp: 127.0.0.1:9090
listen_unix: /path/to/unix.sock

Recommendation:
Add these keys to your configuration before upgrading to avoid startup failures.


Admin Socket

Because we no longer support multiple SPOA listeners, the admin socket no longer provides value.

  • The following option has been removed and is now ignored:
admin_socket: /path/to/admin.sock

You can safely remove this key from your configuration.

We know users still need a way to reload the SPOA without dropping in-flight messages from HAProxy.
In a future release, we plan to add a proper systemctl reload hook to handle this cleanly.


Process Owner (systemd Unit)

With the removal of the parent/worker model and the admin socket, the systemd unit now runs entirely as the crowdsec-spoa user.

This improves separation between service accounts and root, but it also means:

  • All files needed by the SPOA must be readable by the crowdsec-spoa group.

For example:

chown root:crowdsec-spoa /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml
chmod 640 /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml

If you have created .local variants of these configuration files, please run equivalent commands for those files as well.

Note:
The DEB/RPM packages are patched to adjust these permissions on upgrade.
If you encounter issues, manually validate permissions/ownership and open an issue on this repository if problems persist.


Dockerfile

The Docker image has also been updated to run as the crowdsec-spoa user.

If you are building the container locally and mounting configuration files, ensure that:

  • The mounted configuration is readable by crowdsec-spoa.

Log Files

Since the systemd unit now runs as crowdsec-spoa, it can no longer write to the root-owned default /var/log directly.

The unit is configured to create a dedicated directory:

/var/log/crowdsec-spoa

Please update your YAML configuration accordingly:

log_dir: /var/log/crowdsec-spoa/

Note:
The DEB/RPM packages may not clean up old log files in previous locations.
After the upgrade, you may want to manually remove any obsolete log files or directories.

v0.2.0-rc3

17 Nov 15:03
aa4d984

Choose a tag to compare

v0.2.0-rc3 Pre-release
Pre-release

Breaking Changes

As outlined in the 0.1.0 release, every minor version before 1.0.0 may contain breaking changes.
Please review the sections below carefully before upgrading to avoid service interruptions.


TL;DR (Key Changes)

  • Parent/worker model removed – the SPOA now runs as a single process.
  • workers, worker_user, worker_group options removed – replaced by listen_tcp / listen_unix.
  • admin_socket removed – the setting is now ignored and can be deleted.
  • Service now runs fully as crowdsec-spoa user – config/log file permissions must allow this.
  • Docker image now runs as crowdsec-spoa.
  • Default log directory moved to /var/log/crowdsec-spoa/ (config change required).

Inner Architecture

In short:
We removed the parent/worker architecture and now run a simpler, single-process model.

Background

Previously:

  • Multiple workers handled incoming SPOE messages from HAProxy.

  • Each worker communicated with a parent process over a Unix socket to fetch:

    • State
    • Decisions
    • Host configuration (e.g. ban / captcha)

This design existed to support multiple SPOA listeners from a single process.

In practice, we found that users almost never configured more than one SPOA listener.
The added complexity:

  • Slowed down feature development,
  • Increased code debt,
  • Made onboarding new contributors harder.

As a result, we have simplified the architecture to a single process that directly handles SPOE messages.

Configuration Changes

We have removed the following YAML options:

  • workers
  • worker_user
  • worker_group

These are replaced with:

listen_tcp: 127.0.0.1:9090
listen_unix: /path/to/unix.sock

Recommendation:
Add these keys to your configuration before upgrading to avoid startup failures.


Admin Socket

Because we no longer support multiple SPOA listeners, the admin socket no longer provides value.

  • The following option has been removed and is now ignored:
admin_socket: /path/to/admin.sock

You can safely remove this key from your configuration.

We know users still need a way to reload the SPOA without dropping in-flight messages from HAProxy.
In a future release, we plan to add a proper systemctl reload hook to handle this cleanly.


Process Owner (systemd Unit)

With the removal of the parent/worker model and the admin socket, the systemd unit now runs entirely as the crowdsec-spoa user.

This improves separation between service accounts and root, but it also means:

  • All files needed by the SPOA must be readable by the crowdsec-spoa group.

For example:

chown root:crowdsec-spoa /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml
chmod 640 /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml

If you have created .local variants of these configuration files, please run equivalent commands for those files as well.

Note:
The DEB/RPM packages are patched to adjust these permissions on upgrade.
If you encounter issues, manually validate permissions/ownership and open an issue on this repository if problems persist.


Dockerfile

The Docker image has also been updated to run as the crowdsec-spoa user.

If you are building the container locally and mounting configuration files, ensure that:

  • The mounted configuration is readable by crowdsec-spoa.

Log Files

Since the systemd unit now runs as crowdsec-spoa, it can no longer write to the root-owned default /var/log directly.

The unit is configured to create a dedicated directory:

/var/log/crowdsec-spoa

Please update your YAML configuration accordingly:

log_dir: /var/log/crowdsec-spoa/

Note:
The DEB/RPM packages may not clean up old log files in previous locations.
After the upgrade, you may want to manually remove any obsolete log files or directories.

v0.2.0-rc2

17 Nov 13:07
05259b8

Choose a tag to compare

v0.2.0-rc2 Pre-release
Pre-release

Breaking Changes

As outlined in the 0.1.0 release, every minor version before 1.0.0 may contain breaking changes.
Please review the sections below carefully before upgrading to avoid service interruptions.


TL;DR (Key Changes)

  • Parent/worker model removed – the SPOA now runs as a single process.
  • workers, worker_user, worker_group options removed – replaced by listen_tcp / listen_unix.
  • admin_socket removed – the setting is now ignored and can be deleted.
  • Service now runs fully as crowdsec-spoa user – config/log file permissions must allow this.
  • Docker image now runs as crowdsec-spoa.
  • Default log directory moved to /var/log/crowdsec-spoa/ (config change required).

Inner Architecture

In short:
We removed the parent/worker architecture and now run a simpler, single-process model.

Background

Previously:

  • Multiple workers handled incoming SPOE messages from HAProxy.

  • Each worker communicated with a parent process over a Unix socket to fetch:

    • State
    • Decisions
    • Host configuration (e.g. ban / captcha)

This design existed to support multiple SPOA listeners from a single process.

In practice, we found that users almost never configured more than one SPOA listener.
The added complexity:

  • Slowed down feature development,
  • Increased code debt,
  • Made onboarding new contributors harder.

As a result, we have simplified the architecture to a single process that directly handles SPOE messages.

Configuration Changes

We have removed the following YAML options:

  • workers
  • worker_user
  • worker_group

These are replaced with:

listen_tcp: 127.0.0.1:9090
listen_unix: /path/to/unix.sock

Recommendation:
Add these keys to your configuration before upgrading to avoid startup failures.


Admin Socket

Because we no longer support multiple SPOA listeners, the admin socket no longer provides value.

  • The following option has been removed and is now ignored:
admin_socket: /path/to/admin.sock

You can safely remove this key from your configuration.

We know users still need a way to reload the SPOA without dropping in-flight messages from HAProxy.
In a future release, we plan to add a proper systemctl reload hook to handle this cleanly.


Process Owner (systemd Unit)

With the removal of the parent/worker model and the admin socket, the systemd unit now runs entirely as the crowdsec-spoa user.

This improves separation between service accounts and root, but it also means:

  • All files needed by the SPOA must be readable by the crowdsec-spoa group.

For example:

chown root:crowdsec-spoa /etc/crowdsec/bouncers/crowdsec-haproxy-spoa.yaml
chmod 640 /etc/crowdsec/bouncers/crowdsec-haproxy-spoa.yaml

If you have created .local variants of these configuration files, please run equivalent commands for those files as well.

Note:
The DEB/RPM packages are patched to adjust these permissions on upgrade.
If you encounter issues, manually validate permissions/ownership and open an issue on this repository if problems persist.


Dockerfile

The Docker image has also been updated to run as the crowdsec-spoa user.

If you are building the container locally and mounting configuration files, ensure that:

  • The mounted configuration is readable by crowdsec-spoa.

Log Files

Since the systemd unit now runs as crowdsec-spoa, it can no longer write to the root-owned default /var/log directly.

The unit is configured to create a dedicated directory:

/var/log/crowdsec-spoa

Please update your YAML configuration accordingly:

log_dir: /var/log/crowdsec-spoa/

Note:
The DEB/RPM packages may not clean up old log files in previous locations.
After the upgrade, you may want to manually remove any obsolete log files or directories.

v0.2.0-rc1

17 Nov 09:57
e1ccdbb

Choose a tag to compare

v0.2.0-rc1 Pre-release
Pre-release

Breaking Changes

As outlined in the 0.1.0 release, every minor version before 1.0.0 may contain breaking changes.
Please review the sections below carefully before upgrading to avoid service interruptions.


TL;DR (Key Changes)

  • Parent/worker model removed – the SPOA now runs as a single process.
  • workers, worker_user, worker_group options removed – replaced by listen_tcp / listen_unix.
  • admin_socket removed – the setting is now ignored and can be deleted.
  • Service now runs fully as crowdsec-spoa user – config/log file permissions must allow this.
  • Docker image now runs as crowdsec-spoa.
  • Default log directory moved to /var/log/crowdsec-spoa/ (config change required).

Inner Architecture

In short:
We removed the parent/worker architecture and now run a simpler, single-process model.

Background

Previously:

  • Multiple workers handled incoming SPOE messages from HAProxy.

  • Each worker communicated with a parent process over a Unix socket to fetch:

    • State
    • Decisions
    • Host configuration (e.g. ban / captcha)

This design existed to support multiple SPOA listeners from a single process.

In practice, we found that users almost never configured more than one SPOA listener.
The added complexity:

  • Slowed down feature development,
  • Increased code debt,
  • Made onboarding new contributors harder.

As a result, we have simplified the architecture to a single process that directly handles SPOE messages.

Configuration Changes

We have removed the following YAML options:

  • workers
  • worker_user
  • worker_group

These are replaced with:

listen_tcp: 127.0.0.1:9090
listen_unix: /path/to/unix.sock

Recommendation:
Add these keys to your configuration before upgrading to avoid startup failures.


Admin Socket

Because we no longer support multiple SPOA listeners, the admin socket no longer provides value.

  • The following option has been removed and is now ignored:
admin_socket: /path/to/admin.sock

You can safely remove this key from your configuration.

We know users still need a way to reload the SPOA without dropping in-flight messages from HAProxy.
In a future release, we plan to add a proper systemctl reload hook to handle this cleanly.


Process Owner (systemd Unit)

With the removal of the parent/worker model and the admin socket, the systemd unit now runs entirely as the crowdsec-spoa user.

This improves separation between service accounts and root, but it also means:

  • All files needed by the SPOA must be readable by the crowdsec-spoa group.

For example:

chown root:crowdsec-spoa /etc/crowdsec/bouncers/crowdsec-haproxy-spoa.yaml
chmod 640 /etc/crowdsec/bouncers/crowdsec-haproxy-spoa.yaml

If you have created .local variants of these configuration files, please run equivalent commands for those files as well.

Note:
The DEB/RPM packages are patched to adjust these permissions on upgrade.
If you encounter issues, manually validate permissions/ownership and open an issue on this repository if problems persist.


Dockerfile

The Docker image has also been updated to run as the crowdsec-spoa user.

If you are building the container locally and mounting configuration files, ensure that:

  • The mounted configuration is readable by crowdsec-spoa.

Log Files

Since the systemd unit now runs as crowdsec-spoa, it can no longer write to the root-owned default /var/log directly.

The unit is configured to create a dedicated directory:

/var/log/crowdsec-spoa

Please update your YAML configuration accordingly:

log_dir: /var/log/crowdsec-spoa/

Note:
The DEB/RPM packages may not clean up old log files in previous locations.
After the upgrade, you may want to manually remove any obsolete log files or directories.

v0.1.2

31 Oct 14:27
5d6f283

Choose a tag to compare

🚀 Highlights

  • Upstream proxy/CDN support (single-message SPOE) — Evaluate the true client IP (e.g., from X-Real-IP/X-Forwarded-For) when HAProxy sits behind a CDN/L7 proxy.
  • Smart fallback — If HAProxy didn’t precompute a remediation variable, the bouncer now falls back to IP-based remediation.
  • Maintenance & CI — Cleaner packaging scripts, pinned actions, refreshed CrowdSec deps, and linter rules.

Why this matters

When HAProxy is behind a CDN or another L7 proxy, the socket’s src is not the real client. This release lets the bouncer evaluate the true client IP (from a header like X-Real-IP) and still apply decisions correctly—even if HAProxy didn’t precompute a remediation variable.


Recommended SPOE config (single message)

Use only the crowdsec-http message. It extracts the real IP and includes all arguments the bouncer needs.
Adjust the header (x-real-ip) to match your proxy/CDN setup (e.g., x-forwarded-for).

# /etc/haproxy/spoe/crowdsec.cfg
# SPOE section
# - Uses a single message: crowdsec-http
# - Extracts real client IP from X-Real-IP (change if needed)
# - Falls back to IP remediation if 'remediation' var is not set

[crowdsec]

spoe-agent crowdsec-agent
    messages    crowdsec-http
    option      var-prefix      crowdsec
    option      set-on-error    error
    timeout     hello           100ms
    timeout     idle            30s
    timeout     processing      500ms
    use-backend crowdsec-spoa
    log         global

# This message extracts the real IP via X-Real-IP and includes all arguments.
# IMPORTANT: req.hdr_ip() returns an IP type (required by SPOE protocol).
# If 'remediation' isn't provided by HAProxy, the bouncer will check IP remediation.
spoe-message crowdsec-http
    args remediation=var(txn.crowdsec.remediation) \
         crowdsec_captcha_cookie=req.cook(crowdsec_captcha_cookie) \
         id=unique-id host=hdr(Host) method=method path=path query=query \
         version=req.ver headers=req.hdrs body=req.body url=url ssl=ssl_fc \
         src-ip=req.hdr_ip(x-real-ip) src-port=src_port
    event on-frontend-http-request

# Tip: If your upstream sets X-Forwarded-For, you can use:
#   src-ip=req.hdr_ip(x-forwarded-for)

Migration notes

  • If you don’t use an upstream proxy/CDN in front of HAProxy, keep using crowdsec-ip and crowdsec-http together as before.
  • If you do have an upstream proxy/CDN, see the examples in #85 and adapt the header (X-Real-IP vs X-Forwarded-For) to your environment.

What’s Changed

Full Changelog: v0.1.0...v0.1.2

v0.1.1-rc2

23 Oct 14:16
b50fc14

Choose a tag to compare

v0.1.1-rc2 Pre-release
Pre-release

✨ Highlights

  • Packaging & CI polish (RC2) — Safer post-remove script, cleaner installs (no install /dev/stdin), updated CrowdSec deps, pinned CI actions.
  • Config recap (from RC1, still valid) — Support for upstream proxy/CDN with a single crowdsec-http SPOE message using a real-IP header; automatic fallback to IP remediation if remediation isn’t set.

What’s Changed

Full Changelog: v0.1.1-rc1...v0.1.1-rc2


Config notes (from RC1)

  • Behind a proxy/CDN? Use only crowdsec-http and set the real client IP header (e.g., x-real-ip or x-forwarded-for).
  • Not behind a proxy? Keep using crowdsec-ip plus crowdsec-http together.
  • If remediation isn’t set by HAProxy, the bouncer falls back to IP-based remediation.

v0.1.1-rc1

16 Oct 14:52
e1cc737

Choose a tag to compare

v0.1.1-rc1 Pre-release
Pre-release

✨ Highlights

  • Upstream proxy/CDN support — You can now run HAProxy behind an upstream proxy (e.g., a CDN) and use a single SPOE message (crowdsec-http) that supports getting the real client IP from an HTTP header.
  • Safer defaults — If the remediation variable isn’t set by crowdsec-ip, the SPOA bouncer now falls back to IP-based remediation automatically.

What’s Changed

Full Changelog: v0.1.0...v0.1.1-rc1


Why this matters

When HAProxy is behind a CDN or another L7 proxy, the socket’s src is not the real client. This release lets the bouncer evaluate the true client IP (from a header like X-Real-IP) and still apply decisions correctly—even if HAProxy didn’t precompute a remediation variable.


Recommended SPOE config (single message)

Use only the crowdsec-http message. It extracts the real IP and includes all args the bouncer needs.
Adjust the header (x-real-ip) to match your proxy/CDN setup (e.g., x-forwarded-for).

# /etc/haproxy/spoe/crowdsec.cfg
# SPOE section
# - Uses a single message: crowdsec-http
# - Extracts real client IP from X-Real-IP (change if needed)
# - Falls back to IP remediation if 'remediation' var is not set

[crowdsec]

spoe-agent crowdsec-agent
    messages    crowdsec-http
    option      var-prefix      crowdsec
    option      set-on-error    error
    timeout     hello           100ms
    timeout     idle            30s
    timeout     processing      500ms
    use-backend crowdsec-spoa
    log         global

# This message extracts the real IP via X-Real-IP and includes all arguments.
# IMPORTANT: req.hdr_ip() returns an IP type (required by SPOE protocol).
# If 'remediation' isn't provided by HAProxy, the bouncer will check IP remediation.
spoe-message crowdsec-http
    args remediation=var(txn.crowdsec.remediation) \
         crowdsec_captcha_cookie=req.cook(crowdsec_captcha_cookie) \
         id=unique-id host=hdr(Host) method=method path=path query=query \
         version=req.ver headers=req.hdrs body=req.body url=url ssl=ssl_fc \
         src-ip=req.hdr_ip(x-real-ip) src-port=src_port
    event on-frontend-http-request

Tip: If your upstream sets X-Forwarded-For, you can use:
src-ip=req.hdr_ip(x-forwarded-for)


Migration notes

If you do not use an upstream proxy like Cloudflare for example then these do not apply and still use the crowdsec-ip and crowdsec-http in unison

  • if you are using a upstream proxy infront of HAproxy then check #85 the examples files and alter to your setup.

v0.1.0

13 Oct 15:27
da567fd

Choose a tag to compare

⚠️ Breaking Changes

Minor releases in this project can include breaking changes until 1.0.0. A migration path is provided below.

1) Reduce Lua invocations in HAProxy (applies to everyone)

Only call the Lua handler when a decision actually requires it.

Before

http-request lua.crowdsec_handle if { var(txn.crowdsec.remediation) -m found }

After

http-request lua.crowdsec_handle if { var(txn.crowdsec.remediation) -m str "captcha" }
http-request lua.crowdsec_handle if { var(txn.crowdsec.remediation) -m str "ban" }

2) Captcha flow moved from Lua to native HAProxy rules (only if you use Captcha)

  • Lua no longer sets or clears the captcha cookie.
  • Cookie management is now handled with http-after-response.
  • On successful captcha, redirects are now native HAProxy redirects (not Lua).

Add these to the frontend that uses Captcha:

Set/clear Captcha cookie

# Set captcha cookie when SPOA provides a status (pending or valid)
http-after-response set-header Set-Cookie %[var(txn.crowdsec.captcha_cookie)] \
  if { var(txn.crowdsec.captcha_status) -m found } { var(txn.crowdsec.captcha_cookie) -m found }

# Clear captcha cookie when cookie exists but no captcha_status (Allow decision)
http-after-response set-header Set-Cookie %[var(txn.crowdsec.captcha_cookie)] \
  if { var(txn.crowdsec.captcha_cookie) -m found } !{ var(txn.crowdsec.captcha_status) -m found }

Redirect after successful validation

# IMPORTANT: place this BEFORE the lua.crowdsec_handle lines
http-request redirect code 302 location %[var(txn.crowdsec.redirect)] \
  if { var(txn.crowdsec.remediation) -m str "allow" } { var(txn.crowdsec.redirect) -m found }

# Lua now only for captcha/ban
http-request lua.crowdsec_handle if { var(txn.crowdsec.remediation) -m str "captcha" }
http-request lua.crowdsec_handle if { var(txn.crowdsec.remediation) -m str "ban" }

Note: There is no “original” user config to revert from for the Lua cookie logic—this change replaces internal Lua behavior with HAProxy-native rules.


✅ Migration Checklist

  • Update http-request lua.crowdsec_handle to trigger only for captcha and ban.

  • If using Captcha:

    • Add the two http-after-response set-header Set-Cookie rules to your Captcha frontend.
    • Add the native http-request redirect rule before the Lua lines.
  • Reload HAProxy.


What’s Changed

Features & Enhancements

Fixes

CI / Release

  • update: CI workflows, tests, and released binaries/tarballs. (@mmetc, #45)

Full Changelog

Since last stable: v0.0.4...v0.1.0


TL;DR

  • Call Lua only for captcha and ban.
  • Move Captcha cookie + redirect handling to native HAProxy.
  • Add the provided http-after-response and http-request redirect rules to your Captcha frontend and place the redirect before Lua.
  • Includes many quality-of-life improvements (version flag, clearer post-install, better logs) and stability fixes (lifecycle, sockets, packaging).