diff --git a/crowdsec-docs/docusaurus.config.ts b/crowdsec-docs/docusaurus.config.ts
index 0543214c5..fb3c0a9a8 100644
--- a/crowdsec-docs/docusaurus.config.ts
+++ b/crowdsec-docs/docusaurus.config.ts
@@ -238,6 +238,8 @@ const redirects = [
},
// redirecting old hidden invoice page to new faq billing
{ from: "/u/console/premium_upgrade/premium_invoices/", to: "/u/troubleshooting/billing_faq" },
+ // unified Cloudflare bouncer page, cloudflare-workers content moved to cloudflare page (and that one became deprecated)
+ { from: "/u/bouncers/cloudflare-workers", to: "/u/bouncers/cloudflare" },
];
function redirectsGlobalDataPlugin() {
diff --git a/crowdsec-docs/sidebarsUnversioned.ts b/crowdsec-docs/sidebarsUnversioned.ts
index ce6abed26..cd7bd4838 100644
--- a/crowdsec-docs/sidebarsUnversioned.ts
+++ b/crowdsec-docs/sidebarsUnversioned.ts
@@ -655,11 +655,6 @@ const sidebarsUnversionedConfig: SidebarConfig = {
label: "Cloudflare",
id: "bouncers/cloudflare",
},
- {
- type: "doc",
- label: "Cloudflare Workers",
- id: "bouncers/cloudflare-workers",
- },
{
type: "doc",
label: "Custom",
diff --git a/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-decisions-endpoint-edit.png b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-decisions-endpoint-edit.png
new file mode 100644
index 000000000..62f3c508d
Binary files /dev/null and b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-decisions-endpoint-edit.png differ
diff --git a/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-decisions-endpoint-info.png b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-decisions-endpoint-info.png
new file mode 100644
index 000000000..52359ede8
Binary files /dev/null and b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-decisions-endpoint-info.png differ
diff --git a/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-init-valid-token.png b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-init-valid-token.png
new file mode 100644
index 000000000..9aea27295
Binary files /dev/null and b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-init-valid-token.png differ
diff --git a/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-init.png b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-init.png
new file mode 100644
index 000000000..596277d86
Binary files /dev/null and b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-init.png differ
diff --git a/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-set-captcha.png b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-set-captcha.png
new file mode 100644
index 000000000..91c12807e
Binary files /dev/null and b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-set-captcha.png differ
diff --git a/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-worker-preview.png b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-worker-preview.png
new file mode 100644
index 000000000..d5bf42901
Binary files /dev/null and b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-worker-preview.png differ
diff --git a/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-zone-bind.png b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-zone-bind.png
new file mode 100644
index 000000000..a676ca841
Binary files /dev/null and b/crowdsec-docs/static/img/bouncer/cloudflare-worker/cf-installer-zone-bind.png differ
diff --git a/crowdsec-docs/unversioned/bouncers/cloudflare-deprecated.mdx b/crowdsec-docs/unversioned/bouncers/cloudflare-deprecated.mdx
new file mode 100644
index 000000000..01ceb7129
--- /dev/null
+++ b/crowdsec-docs/unversioned/bouncers/cloudflare-deprecated.mdx
@@ -0,0 +1,523 @@
+---
+id: cloudflare-deprecated
+title: Cloudflare DEPRECATED BOUNCER
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import RemediationSupportBadges from '@site/src/components/remediation-support-badge';
+
+
+
+
+
+
+
+
+
+
+
+
+📚 Documentation
+💠 Hub
+💬 Discourse
+
+
+
+
+:::danger
+
+This bouncer isn't actively supported anymore, due to changes to Cloudflare's API rate limitations.
+
+You should instead look at the [Cloudflare Workers Bouncer](/u/bouncers/cloudflare).
+
+:::
+
+A Remediation Component that syncs the decisions made by CrowdSec with CloudFlare's firewall. Manages multi user, multi account, multi zone setup. Supports IP, Country and AS scoped decisions.
+
+
+
+## Installation
+
+### Repository
+
+Packages for crowdsec-cloudflare-bouncer [are available on our repositories](/u/getting_started/installation/linux#repository-installation). You need to pick the package accord to your firewall system :
+
+
+
+
+```bash
+sudo apt install crowdsec-cloudflare-bouncer
+```
+
+
+
+
+```bash
+sudo yum install crowdsec-cloudflare-bouncer
+```
+
+
+
+
+
+Then run the following commands to setup your bouncer:
+
+
+```bash
+sudo crowdsec-cloudflare-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
+sudo crowdsec-cloudflare-bouncer -s # this sets up IP lists and firewall rules at cloudflare for the provided config.
+sudo systemctl start crowdsec-cloudflare-bouncer # the bouncer now syncs the crowdsec decisions with cloudflare components.
+```
+
+:::warning
+
+Please configure your server to emit real IPs rather than cloudflare IPs in logs, so crowdsec can function properly. See how to [here](https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs)
+
+:::
+
+:::info
+
+If your component is not installed on the same machine than LAPI, don't forget to set the `crowdsec_lapi_url` and `crowdsec_lapi_key` in the configuration file `/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml`
+
+:::
+
+:::note
+
+You need to run `sudo crowdsec-cloudflare-bouncer -d` to cleanup exisiting cloudflare components created by component before editing the config files.
+
+:::
+
+:::note
+
+You can run `sudo crowdsec-cloudflare-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml` to generate the configuration by discovering all the accounts and the zones associated with the provided tokens.
+
+:::
+
+
+### Manual
+
+#### Assisted
+
+Download the [latest release](https://github.com/crowdsecurity/cs-cloudflare-bouncer/releases).
+
+```bash
+tar xzvf crowdsec-cloudflare-bouncer.tgz
+cd crowdsec-cloudflare-bouncer/
+sudo ./install.sh
+sudo crowdsec-cloudflare-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml # auto-generate cloudflare config for provided tokens
+sudo crowdsec-cloudflare-bouncer -s # this sets up IP lists and firewall rules at cloudflare for the provided config.
+sudo systemctl start crowdsec-cloudflare-bouncer # the bouncer now syncs the crowdsec decisions with cloudflare components.
+```
+
+#### From source
+
+```bash
+make release
+cd crowdsec-cloudflare-bouncer-vX.X.X
+sudo ./install.sh
+```
+Rest of the steps are same as of the above method.
+
+
+## Container
+
+Make sure you have docker or podman installed. In this guide we will use docker, but podman would work as a drop in replacement too.
+
+### Setup
+
+```bash
+docker run crowdsecurity/cloudflare-bouncer \
+ -g , > cfg.yaml # auto-generate cloudflare config for provided space separated tokens
+```
+
+You can then review the contents of the file `cfg.yaml` and make any necessary changes.
+
+```
+vim cfg.yaml # review config and set `crowdsec_lapi_key`
+```
+
+The `crowdsec_lapi_key` can be obtained by running the following:
+
+```bash
+sudo cscli -oraw bouncers add cloudflarebouncer # -oraw flag can discarded for human friendly output.
+```
+
+The `crowdsec_lapi_url` must be accessible from the container.
+
+### Runtime
+
+```bash
+ docker run \
+ -v $PWD/cfg.yaml:/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml \
+ -p 2112:2112 \
+ crowdsecurity/cloudflare-bouncer
+```
+
+
+## Configuration
+
+Configuration file can be found at `/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml`
+
+```yaml
+# CrowdSec Config
+crowdsec_lapi_url: http://localhost:8080/
+crowdsec_lapi_key: ${API_KEY}
+crowdsec_update_frequency: 10s
+include_scenarios_containing: [] # ignore IPs banned for triggering scenarios not containing either of provided word, eg ["ssh", "http"]
+exclude_scenarios_containing: [] # ignore IPs banned for triggering scenarios containing either of provided word
+only_include_decisions_from: [] # only include IPs banned due to decisions orginating from provided sources. eg value ["cscli", "crowdsec"]
+
+#Cloudflare Config.
+cloudflare_config:
+ accounts:
+ - id:
+ token:
+ ip_list_prefix: crowdsec
+ default_action: managed_challenge
+ total_ip_list_capacity: # only this many latest ip scoped decisions would be kept
+
+ zones:
+ - actions:
+ - managed_challenge # valid choices are either of managed_challenge, js_challenge, block
+ zone_id:
+
+ update_frequency: 30s # the frequency to update the cloudflare IP list
+
+# Component Config
+daemon: true
+log_mode: file
+log_dir: /var/log/
+log_level: info # valid choices are either debug, info, error
+log_max_size: 40
+log_max_age: 30
+log_max_backups: 3
+compress_logs: true
+
+prometheus:
+ enabled: true
+ listen_addr: 127.0.0.1
+ listen_port: 2112
+```
+
+## Making changes to configuration
+
+The component creates Cloudflare infra (IP lists, rules etc) according to your config file.
+
+Before changing the config, always run the following command to clear old infra:
+
+```
+sudo crowdsec-cloudflare-bouncer -d
+```
+
+### Upgrading from v0.0.X to v0.1.Y
+
+During v0.0.X there was no `managed_challenge` action, instead `challenge` action was used by bouncer. This is deprecated since v0.1.0 .
+
+This section assumes you used the default config (generated via `crowdsec-cloudflare-bouncer -g ,` )
+
+After upgrading the component from v0.0.X to v0.1.Y , run the following commands to migrate to `managed_challenge`.
+
+```bash
+sudo crowdsec-cloudflare-bouncer -d
+sudo crowdsec-cloudflare-bouncer -g , -o
+sudo systemctl restart crowdsec-cloudflare-bouncer
+```
+
+
+## Cloudflare Configuration
+
+**Background:** In Cloudflare, each user can have access to multiple accounts. Each account can own/access multiple zones. In this context a zone can be considered as a domain. Each domain registered with cloudflare gets a distinct `zone_id`.
+
+
+For obtaining the `token`:
+1. Sign in as a user who has access to the desired account.
+2. Go to [Tokens](https://dash.cloudflare.com/profile/api-tokens) and create the token. The component requires the following permissions to function.
+
+
+To automatically generate config for cloudflare check the helper section below.
+
+
+:::note
+If the zone is subscribed to a paid Cloudflare plan then it can be configured to support multiple types of actions. For free plan zones only one action is supported. The first action is applied as default action.
+:::
+
+## Helpers
+
+The component binary has built in helper scripts to do various operations.
+
+### Auto config generator
+
+Generates component config by discovering all the accounts and the zones associated with provided list of tokens.
+
+Example Usage:
+
+```bash
+sudo crowdsec-cloudflare-bouncer -g ,... -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml
+```
+
+:::note
+This script only generates cloudflare related config. By default it refers to the config at `/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml` for crowdsec configuration.
+:::
+
+Using custom config:
+
+```bash
+sudo crowdsec-cloudflare-bouncer -c /path/to/config/file -g ,...
+```
+
+### Cloudflare Setup
+
+This only creates the required IP lists and firewall rules at cloudflare and exits.
+
+Example Usage:
+```bash
+sudo crowdsec-cloudflare-bouncer -s
+```
+
+### Cloudflare Cleanup
+
+This deletes all IP lists and firewall rules at cloudflare which were created by the component.
+
+Example Usage:
+```bash
+sudo crowdsec-cloudflare-bouncer -d
+```
+
+## How it works
+
+The service polls the CrowdSec Local API for new / deleted decisions. It then makes API calls to Cloudflare to update IP lists and firewall rules depending upon the decision.
+
+## Configuration Reference
+
+### `crowdsec_lapi_url`
+> string
+
+The URL of CrowdSec LAPI. It should be accessible from the component.
+
+### `crowdsec_lapi_key`
+> string
+
+API key to authenticate with the LAPI.
+
+### `cert_path`
+> string
+
+Path to the certificate file used to authenticate with the LAPI.
+
+### `key_path`
+> string
+
+Path to the key file used to authenticate with the LAPI.
+
+### `ca_path_file`
+> string
+
+Path to the CA file used to trust the LAPI certificate.
+
+### `crowdsec_update_frequency`
+> string (That is parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
+
+The component will poll the CrowdSec every `update_frequency` interval.
+
+### `include_scenarios_containing`
+> [ ]string
+
+Ignore IPs banned for triggering scenarios not containing either of provided word.
+
+```yaml title="Example"
+include_scenarios_containing: ["ssh", "http"]
+```
+
+### `exclude_scenarios_containing`
+> [ ]string
+
+Ignore IPs banned for triggering scenarios containing either of provided word.
+
+```yaml title="Example"
+exclude_scenarios_containing: ["ssh", "http"]
+```
+
+### `only_include_decisions_from`
+> [ ]string
+
+Only include IPs banned due to decisions orginating from provided sources.
+
+```yaml title="Example"
+only_include_decisions_from: ["cscli", "crowdsec"]
+```
+
+### `cloudflare_config`
+> [CloudflareConfig](https://github.com/crowdsecurity/cs-cloudflare-bouncer/blob/20c902ee1e95fe13135dd493d7e96840bafc931b/pkg/cfg/config.go#L34-L37)
+
+This block contains cloudflare specific config.
+
+#### `update_frequency`
+> string (That is parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
+
+The frequency at which to update the cloudflare resources.
+
+```yaml title="Example"
+update_frequency: "10s"
+```
+
+#### `accounts`
+> [ ][AccountConfig](https://github.com/crowdsecurity/cs-cloudflare-bouncer/blob/20c902ee1e95fe13135dd493d7e96840bafc931b/pkg/cfg/config.go#L26-L33)
+
+List of account of configs
+
+##### `id`
+> string
+
+id of cloudflare account
+
+##### `token`
+> string
+
+cloudflare token to use to access the account.
+
+##### `ip_list_prefix`
+> string
+
+The prefix to use for naming the IP lists created by the bouncer. The name of IP list will be of the form `ip_list_prefix`+`action`.
+
+##### `total_ip_list_capacity`
+> int
+
+Limit the number of items in IP lists. This is required for avoiding limit of 10k items for lists.
+
+##### `default_action`
+> `managed_challenge` | `block` | `js_challenge` | `challenge` | `none`
+
+The action to be applied for a decision, if the decision's action is not supported by a zone.
+
+`default_action` must be supported by all zones.
+
+**Example:**
+
+Consider your zone config supports the actions `managed_challenge` and `js_challenge`. Your `default_action` is `managed_action`. If you create the following decision:
+
+```
+sudo cscli decisions add --ip 192.168.1.1 --type ban
+```
+
+Since the zone doesn't support `ban` decision type, it'll be inserted into the IP list given by `default_action`. In this case it'll be the list for `managed_challenge`.
+
+You can completely ignore such decisions by setting `default_action` to `none`. It won't be inserted into any list then.
+
+**Note:**
+
+Following table is mapping of decision type to it's destination IP list.
+
+| Decision Type | Default Action |
+| ------------- | ----------------- |
+| captcha | managed_challenge |
+| ban | block |
+| js_challenge | js_challenge |
+
+
+:::warning
+`challenge` action is deprecated in favour of `managed_challenge`.
+:::
+
+#### `zones`
+> [ ][ZoneConfig](https://github.com/crowdsecurity/cs-cloudflare-bouncer/blob/20c902ee1e95fe13135dd493d7e96840bafc931b/pkg/cfg/config.go#L21-L25)
+
+This block contains config for each zone to be managed by the component. The zone must be accessible from the parent account.
+
+##### `zone_id`
+> string
+
+The id of the zone.
+
+##### `actions`
+> [ ]string
+
+List of actions to be supported by this zone. If the zone is not subscribed to premium plan, then only a single action can be given.
+
+The supported action must include the `default_action` of the parent account.
+
+Valid choice includes either of
+- `block`
+- `js_challenge`
+- `challenge`
+- `managed_challenge`.
+
+The component creates an IP list for each action. IP list is at account level, so multiple zones with same parent account will share lists for particular action.
+
+:::warning
+`challenge` action is deprecated in favour of `managed_challenge`
+:::
+
+**Note:**
+
+Following table is mapping of decision type to it's destination IP list, which are created according to zone actions
+
+
+| Decision Type | Zone Action |
+| ------------- | ----------------- |
+| captcha | managed_challenge |
+| ban | block |
+| js_challenge | js_challenge |
+
+
+
+### `daemon`
+> boolean
+
+:::warning
+This field has now been deprecated and is ignored within the component
+:::
+
+Run the component as a daemon.
+
+### `log_mode`
+> `stdout` | `file`
+
+Where the log contents are written (With `file` it will be written to `log_dir` with the name `crowdsec-cloudflare-bouncer.log`)
+
+### `log_dir`
+> string
+
+Relevant if `log_mode` is `file`. This determines where to create log file.
+
+### `log_level`
+> `trace` | `debug` | `info` | `error`
+
+Log level for the component.
+
+### `compress_logs`
+> `true` | `false`
+
+Compress log files on rotation
+
+### `log_max_size`
+> int (in MB)
+
+Max size of log files before rotation
+
+### `log_max_backups`
+> int
+
+How many backup log files to keep before deletion (can happen before `log_max_age` is reached)
+
+### `log_max_age`
+> int (in days)
+
+Max age of backup files before deletion (can happen before `log_max_backups` is reached)
+
+## Troubleshooting
+ - Metrics can be seen at http://localhost:2112/metrics
+ - Logs are in `/var/log/crowdsec-cloudflare-bouncer.log` (Default unless changed in config)
+ - You can view/interact directly in the ban list either with `cscli`
+ - Service can be started/stopped with `systemctl start/stop crowdsec-cloudflare-bouncer`
diff --git a/crowdsec-docs/unversioned/bouncers/cloudflare-workers.mdx b/crowdsec-docs/unversioned/bouncers/cloudflare-workers.mdx
deleted file mode 100644
index 3e5031173..000000000
--- a/crowdsec-docs/unversioned/bouncers/cloudflare-workers.mdx
+++ /dev/null
@@ -1,837 +0,0 @@
----
-id: cloudflare-workers
-title: CrowdSec Cloudflare Worker
-toc_max_heading_level: 3
----
-
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-import useBaseUrl from '@docusaurus/useBaseUrl';
-import RemediationSupportBadges from '@site/src/components/remediation-support-badge';
-
-
-
-
-
-
-
-
-
-
-
-
-
-📚 Documentation
-💠 Hub
-💬 Discourse
-
-
-
-
-## Overview
-This **Remediation Component** (aka Bouncer) uses **Cloudflare Workers** to `block` or `challenge` incoming requests.
-- It uses decisions taken by your **CrowdSec Security Engine** and/or **Blocklists** you subscribed to.
-- It can be directly plugged to **CrowdSec Blocklists** via a CrowdSec **Blocklist as a Service Integration**.
-
-The bouncer uses **Cloudflare Workers** in combination with **Cloudflare Workers KV** (KeyValue store).
-
-#### Useful links
-
-* **Register** this **remediation component** into your **Security engine**: [Here](/u/bouncers/intro).
-* OR setup a **Blocklist as a Service** endpoint for a **remediation component**: [Here](/u/integrations/remediationcomponent).
-
-:::warning
-This Remediation Component heavily relies on Cloudflare Workers and KV store.
-It works best on a paid Workers subscription.
-More explanation in the chapter [Test with Cloudflare free plan](#appendix-test-with-cloudflare-free-plan)
-:::
-
-## Operational modes
-
-This Remediation Component can operate in two modes:
- - [**Daemon Mode**](#daemon-mode): A Go process runs continuously on a host/vm, periodically syncing decisions from your CrowdSec Security Engine to Cloudflare.
- - [**Autonomous Mode**](#autonomous-mode): A Go process creates/delete an autonomous Cloudflare Worker that periodically syncs decisions within Cloudflare itself.
-
-### Daemon Mode
-
-This mode is recommended if you are using a **Security Engine** and want to relay all/part of the decisions (and subscribed blocklists) to Cloudflare.
-It provides more **control** and **flexibility** over the decision synchronization process.
-It requires the Bouncer (Go process) to run continuously on a host/VM, usually alongside your CrowdSec Security Engine.
-
-:::info
-The Workers and KV created by the bouncer will be cleaned up from Cloudflare upon launch error OR bouncer stoppage.
-:::
-
-
-
-### Autonomous Mode
-
-This mode is recommended if you want a **minimal footprint** deployment, without having the bouncer process running on your host/VM.
-💡 It is ideal if you want to directly plug a **Blocklist integrations** into Cloudflare.
-
-*It can also be plugged to a Security Engine, but woould require an open connection from Cloudflare to your LAPI. We recommend using [Daemon mode](#daemon-mode) in a usecase where a Security Engine is involved.*
-
-#### ⚙️ Init / Removal on CloudFlare
-
-Creation of necessary **Cloudflare Workers** and **KV stores** is done once at init time.
-And can be cleaned up by running the bouncer with the appropriate instruction* (more details int the installation section).*
-
-The init phase create two workers and one KV store.:
- - The **remediation worker**, which applies the decisions to incoming requests:
- - It uses the **KV store** to lookup decisions.
- - It is bound to **worker routes** to protect your selected zones.
- - The **decisions sync worker**, which periodically fetches and caches decisions and updates the **KV store**.
-
-The cleanup phase deletes all the created components.
-
-
-
-#### ⚙️ Periodic decision sync within Cloudflare
-
-Once initialized, the decisions sync worker runs periodically based on a cron schedule defined in the configuration.
-
-
-
-## Installation
-
-:::warning
-After configuring and starting the Remediation Component, please see the [setting up worker fail mode](#setting-up-the-worker-route-fail-mode) section.
-:::
-
-### Prerequisites
-
-Before installing the CrowdSec Cloudflare Worker Remediation Component, you need a **Cloudflare API token** with the required permissions to create and manage Workers, KV stores, and other Cloudflare resources
-
-For instructions on generating a Cloudflare API token with the correct permissions, see [Generating a Cloudflare API Token](#generating-a-cloudflare-api-token).
-
-### Packages Installation
-
-Packages for crowdsec-cloudflare-worker-bouncer [are available on our repositories](/u/getting_started/installation/linux#repository-installation). You need to pick the package accord to your firewall system :
-
-
-
-
-```bash
-sudo apt install crowdsec-cloudflare-worker-bouncer
-```
-
-
-
-
-```bash
-sudo yum install crowdsec-cloudflare-worker-bouncer
-```
-
-
-
-
-
-Then run the following commands to setup your Remediation Component:
-
-
-
-
-```bash
-sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
-sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't alread
-sudo systemctl start crowdsec-cloudflare-worker-bouncer # the Remediation Component now syncs the crowdsec decisions with cloudflare components.
-```
-
-
-
-
-```bash
-sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
-sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't alread
-sudo crowdsec-cloudflare-worker-bouncer -S -c /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # deploy in autonomous mode - no daemon needed
-```
-
-In autonomous mode, the Go process deploys the configuration to Cloudflare and exits. All decision synchronization is handled by Cloudflare scheduled workers. No systemd service is required.
-
-
-
-
-:::warning
-
-Please configure your server to emit real IPs rather than cloudflare IPs in logs, so crowdsec can function properly. See how to [here](https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs)
-
-:::
-
-:::info
-
-If your Remediation Component is not installed on the same machine than LAPI, don't forget to set the `crowdsec_lapi_url` and `crowdsec.lapi_key` in the configuration file `/etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml`
-
-:::
-
-:::note
-
-You need to run `sudo crowdsec-cloudflare-worker-bouncer -d` to cleanup existing cloudflare components created by Remediation Component before editing the config files.
-
-:::
-
-:::note
-
-You can run `sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml` to generate the configuration by discovering all the accounts and the zones associated with the provided tokens.
-
-:::
-
-### Manual Installation
-
-#### Assisted
-
-Download the [latest release](https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer/releases).
-
-
-
-
-```bash
-tar xzvf crowdsec-cloudflare-worker-bouncer.tgz
-cd crowdsec-cloudflare-worker-bouncer/
-sudo ./install.sh
-sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided tokens
-sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't already
-sudo systemctl start crowdsec-cloudflare-worker-bouncer # the Remediation Component now syncs the crowdsec decisions with cloudflare components.
-```
-
-
-
-
-```bash
-tar xzvf crowdsec-cloudflare-worker-bouncer.tgz
-cd crowdsec-cloudflare-worker-bouncer/
-sudo ./install.sh
-sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided tokens
-sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't already
-sudo crowdsec-cloudflare-worker-bouncer -S -c /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # deploy in autonomous mode - no daemon needed
-```
-
-
-
-
-#### From source
-
-:warning: requires go >= 1.23
-
-
-
-
-```bash
-git clone https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer
-cd cs-cloudflare-worker-bouncer
-make release
-cd crowdsec-cloudflare-worker-bouncer-*
-./crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
-sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't already
-sudo systemctl start crowdsec-cloudflare-worker-bouncer
-```
-
-
-
-
-```bash
-git clone https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer
-cd cs-cloudflare-worker-bouncer
-make release
-cd crowdsec-cloudflare-worker-bouncer-*
-./crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
-sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't already
-./crowdsec-cloudflare-worker-bouncer -S -c /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # deploy in autonomous mode - no daemon needed
-```
-
-
-
-
-
-## How it works
-
-The Remediation Component can operate in two modes:
-
-### Daemon Mode (default)
-
-The Remediation Component does the following:
-
-1. Create a Cloudflare Worker and a Worker KV per configured account.
-2. Create a Worker Route(s) per configured zone. Any request matching the route would be handled by the worker.
-3. For every matching incoming request, the worker checks whether it's IP, Country and AS have a decision against. It checks for this in it's KV store. If found it performs the corresponding remediation.
-4. The Remediation Component runs as a daemon and periodically updates the KV store with the latest decisions from CrowdSec's **Security Engine** OR **Blocklist Integration**.
-
-*Note that in the following Schema, a Blocklist as a Service Integration can be substituted to the Security Engine.*
-
-
-
-
-
-### Autonomous Mode
-
-:::info
-Autonomous mode is ideal for users who prefer not to run a continuous process on their host/VM.
-Combined with [Blocklist as a Service (BLaaS)](/u/integrations/remediationcomponent), this provides the minimal footprint deployment, only running setup/cleanup commands when needed.
-:::
-
-In autonomous mode (enabled with the `-S` flag), the Remediation Component functions without requiring a continuously running Go daemon process. Instead:
-
-1. Two Cloudflare Workers are deployed:
- - `crowdsec-cloudflare-worker-bouncer` (Remediation Worker) - applies cached decisions to incoming requests (same as daemon mode)
- - `decisions-sync-worker` (Blocklist updater Worker) - periodically fetches and caches security decisions using Cloudflare scheduled tasks
-
-
-
-2. The Go process only needs to run once for initial setup and configuration deployment
-
-3. All decision synchronization is handled automatically by the Blocklist updater Worker using Cloudflare's scheduled tasks
-
-
-
-4. This mode reduces infrastructure requirements as no persistent daemon is needed
-
-
-
-
-#### Reset all decisions from Cloudflare KV store
-
-In autonomous mode, you can reset all decisions without redeploying all the infrastructure (with the `-S` flag).
-In order to do so, add a `RESET` key (with a `true` value) to the KV store.
-The next time the sync worker runs, it will clear all existing decisions and repopulate them from CrowdSec LAPI.
-
-
-### Metrics
-
-The worker writes metric data points to a [Workers Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/) dataset, tracking:
- - Number of requests processed
- - Number of requests blocked
- - Number of requests that threw an exception in the worker
- - Average request processing latency
-
-:::info
-Since `v0.0.18`, metrics are stored in a **Workers Analytics Engine** dataset instead of a **D1** database. Make sure your Cloudflare token has the `Account Analytics: Read` permission (see [the permissions table](#generating-a-cloudflare-api-token)). Without it the metric poll returns a `403` and metrics are disabled, but remediation enforcement is unaffected.
-
-If you are upgrading from an older version, the legacy `CROWDSECCFBOUNCERDB` D1 database is no longer used and can be deleted manually from the Cloudflare dashboard.
-:::
-
-The dataset name defaults to `crowdsec_cloudflare_bouncer` and can be customized with the [`worker.analytics_dataset`](#workeranalytics_dataset) option.
-
-**In Daemon Mode**, the running process:
-- Polls the Analytics Engine SQL API on the regular push schedule
-- Exposes metrics through the Prometheus endpoint
-- Automatically pushes metrics to CrowdSec for visualization with `cscli`
-
-**In Autonomous Mode**, since there is no running daemon process:
-- Metrics are collected in the Analytics Engine dataset
-- Metrics are **NOT pushed to CrowdSec**
-
-## Configuration explained
-
-```yaml
-crowdsec_config:
- lapi_key: ${API_KEY}
- lapi_url: ${CROWDSEC_LAPI_URL}
- update_frequency: 10s
- include_scenarios_containing: []
- exclude_scenarios_containing: []
- only_include_decisions_from: []
- insecure_skip_verify: false
- key_path: "" # Used for TLS authentification with CrowdSec LAPI
- cert_path: "" # Used for TLS authentification with CrowdSec LAPI
- ca_cert_path: "" # Used for TLS authentification with CrowdSec LAPI
-
-cloudflare_config:
- accounts:
- - id:
- zones:
- - zone_id: # crowdflare.co.uk
- actions: # Supported Actions [captcha, ban]
- - captcha
- default_action: captcha # Supported Actions [captcha, ban, none]
- routes_to_protect: []
- turnstile:
- enabled: true
- rotate_secret_key: true
- rotate_secret_key_every: 168h0m0s
- mode: managed # Supported Modes "managed"|"invisible"|"non-interactive"
- token:
- account_name: owner@example.com
- worker:
- log_only: false # If true, allow all requests, but still keep track of what would have been blocked in the metrics
- script_name: ""
- kv_namespace_name: "" # KV namespace title; change when running multiple bouncers on the same Cloudflare account
- decisions_sync_script_name: "" # Decisions sync worker script name; change when running multiple bouncers on the same Cloudflare account
- analytics_dataset: "" # Workers Analytics Engine dataset name for metrics (default: crowdsec_cloudflare_bouncer)
- logpush: null
- tags: []
- compatibility_date: ""
- compatibility_flags: []
- observability: # Optional Workers Observability (logs/traces); omit to leave Cloudflare defaults in place
- enabled: true
- head_sampling_rate: 1.0
- traces:
- enabled: true
- head_sampling_rate: 1.0
- decisions_sync_worker: # Configuration for autonomous decisions sync worker
- cron: '*/5 * * * *' # Cron schedule for syncing decisions (e.g., "*/5 * * * *" for every 5 minutes)
-
-log_level: info
-log_media: "stdout"
-log_dir: "/var/log/"
-ban_template_path: "" # set to empty to use default template
-
-prometheus:
- enabled: true
- listen_addr: 127.0.0.1
- listen_port: "2112"
-```
-
-
-## Cloudflare Configuration
-
-**Background:** In Cloudflare, each user can have access to multiple accounts. Each account can own/access multiple zones. In this context a zone can be considered as a domain. Each domain registered with cloudflare gets a distinct `zone_id`.
-
-### Generating a Cloudflare API Token
-
-For obtaining the `token`:
-
-:::warning
-Ensure the `token` you are generating is a **user** API token these are found via clicking "my profile" and `API Tokens`. If you are in the `Account API Tokens` section then this is the incorrect place and these tokens have different rate limits which may cause issues whilst operating this Remediation Component.
-:::
-
-1. Sign in as a user who has access to the desired account.
-
-Then click [this link](https://dash.cloudflare.com/profile/api-tokens?permissionGroupKeys=%5B%7B%22key%22%3A%22account_settings%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22challenge_widgets%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22user_details%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22workers_kv_storage%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22workers_routes%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22workers_scripts%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22zone%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22dns%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22account_analytics%22%2C%22type%22%3A%22read%22%7D%5D&name=) and create the token.
-
-Alternatively, you can go to [Tokens](https://dash.cloudflare.com/profile/api-tokens) and create the token.
-
-The Remediation Component requires the following permissions to function:
-
-| Permission Group | Item | Permission |
-| ---------------- | ------------------ | ---------- |
-| Account | Turnstile | Edit |
-| Account | Workers KV Storage | Edit |
-| Account | Workers Scripts | Edit |
-| Account | Account Settings | Read |
-| Account | Account Analytics | Read |
-| User | User Details | Read |
-| Zone | DNS | Read |
-| Zone | Workers Routes | Edit |
-| Zone | Zone | Read |
-
-
-:::info
-By default, the token will be scopped to all accounts / zones you have access to.\
-We recommend scoping the token only to the required accounts and zones.
-:::
-
-:::warning
-
-This remediation component require each configured to have at least one `A` or `AAAA` records.\
-If you have zones without them (eg, with only `CNAME` records), exclude them from the scope.\
-The bouncer will try to automatically ignore such zones, but if it fails to do so for any reason, you might incur higher KV storage charges.
-:::
-
-To automatically generate config, check the helper section below.
-
-## Helpers
-
-The binary has built in helper scripts to do various operations.
-
-### Auto config generator
-
-Generates config by discovering all the accounts and the zones associated with provided list of tokens.
-
-Example Usage:
-
-```bash
-sudo crowdsec-cloudflare-worker-bouncer -g ,... -o cfg.yaml
-cat cfg.yaml > /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
-```
-
-:::note
-This script only generates cloudflare related config. By default it refers to the config at `/etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml` for crowdsec configuration.
-:::
-
-Using custom config:
-```bash
-sudo crowdsec-cloudflare-worker-bouncer -c ./cfg.yaml -g ,...
-```
-
-### Cloudflare Cleanup
-
-This deletes all the Cloudflare infrastructure which was created by the Remediation Component.
-
-Example Usage:
-```bash
-sudo crowdsec-cloudflare-worker-bouncer -d
-```
-
-## Setting up the worker route fail mode
-
-The Remediation Component creates worker routes to make the workers act as a reverse proxy for your origin servers. The worker routes are created with the failover mode set to `Fail Closed`. **There's no public Cloudflare API we can use to change/update it to `Fail Open` mode**.
-
-With `Fail Closed` mode, Routes in fail closed mode will display a Cloudflare 1027 error page to visitors if there's an error within the worker. This error could be triggered due to quotas exceeding your plan etc. **Cloudflare doesn't mention all the possible scenarios which could trigger this error page**.
-
-Thus **we recommend you to manually override the failover mode to `Fail Open`** for all the worker routes created by our Remediation Component. With `Fail Open` mode the requests would bypass the worker and be served directly from your origin servers. Thus your website would continue to function even if there's an error within the worker.
-
-This can be done by following the steps below:
-
-1. Log in to the Cloudflare dashboard and select your account.
-2. For all the websites configured with the Remediation Component, do the following:
-3. Click on the website's name to open the Website's Overview page.
-4. Click on the Worker Routes tab from the left menu.
-
-
-
-5. Click on the route created by the Remediation Component.
-6. Click on the Edit button.
-7. Click on the Request limit failure mode. Check the Fail open button.
-
-
-
-## Appendix: Test with Cloudflare free plan
-Using Cloudflare's free plan with our Remediation Component requires to understand the constraints of the CloudFlare freeplan.
-Despite these constraints, it's entirely feasible to leverage the Remediation Component for enhanced security.
-
-In this section we'll guide you through:
- - An overview of the Cloudflare free plan's limitations and their impact on Remediation Component functionality
- - A walkthrough for deploying the Remediation Component within these constraints successfully
-
-### Understanding Cloudflare Free Plan Limitations
-Our Remediation Component integrates with Cloudflare Workers and Workers KeyValue storage, subject to specific thresholds under the free plan.
-For the complete detailed information, refer to Cloudflare's official documentation:
- - [KeyValue storage limits by plan](https://developers.cloudflare.com/kv/platform/limits/)
- - [Workers limits by plan](https://developers.cloudflare.com/workers/platform/limits/)
-
-Key limitations to note for Remediation Component operation on the free plan include:
- - KV write: Up to 1K per day
- - Worker Requests:Up to 100k per day or 1K per minute
-
-*KV write limit of 1K per day*:
-It's the primary limiting factor as the full decisions list (blocklist) passed on to the Remediation Component often exceeds tens of thousands of IPs.
- - It implies that the initial population of decisions in the Worker's KV will be truncated to 1K
- - However, it will still periodically receive new decisions and remove expired ones.
- - So, eventually you'll have many more than 1K IPs in the KV but it still diminishes the immediate effectiveness of the Remediation Component
-
-The *request quota*:
-While the request quota might seem ample, it's essential to remember that both legitimate traffic and potential attack patterns contribute to this total.
- - ⚠️ It's primordial to [properly setup the failmode](#setting-up-the-worker-route-fail-mode)
- - With the failmode set to passthrough, when you reach the Worker request limits your service will stay available, but the Remediation Component won't apply remediation anymore
-
-### Quick Guide : Configuring the Remediation Component on Cloudflare's Free Plan
-To adapt to the free plan's constraints, we can prioritize local decision-making and manual intervention over broader community-driven blocklists.
-Here's how to set it up:
-
-1. *Configuration Setup*: Begin by [auto-generating the Remediation Component configuration](#auto-config-generator).
-2. *Limiting Decision Sources*: Modify the configuration to prioritize decisions generated by your Security Engine and added manually.
- - Using the config parameter [crowdsec.only_include_decisions_from](#only_include_decisions_from)
- ```yaml
-crowdsec_config:
- [...]
- only_include_decisions_from: ["cscli", "crowdsec"]
- ```
-3. *Failmode Configuration*: It's crucial to [configure the failmode properly](#setting-up-the-worker-route-fail-mode) to ensure your service remains operational even when request quotas are reached.
-4. *Testing with manual decisions*: Verify the functionality by adding decisions manually, which should be promptly reflected in KV storage and enforced by the Remediation Component.
- ```bash
- sudo cscli decisions add --ip 192.168.1.1 --type captcha
- ```
- check your decisions has been added using:
-```bash
- sudo cscli decisions list --origin cscli
-```
- And within a few seconds it will be sent to the KV and the proper remediation should be applied to the requests from the specified IP
-
-## Configuration Reference
-
-### `crowdsec_config`
-
-Used to nest the configuration related to crowdsec.
-
-#### `lapi_url`
-> string
-
-The URL of CrowdSec LAPI. It should be accessible from the Remediation Component.
-
-#### `lapi_key`
-> string
-
-It can be obtained by running the following on the machine CrowdSec LAPI is deployed on.
-
-```bash
-sudo cscli -oraw bouncers add cloudflarebouncer # -oraw flag can discarded for human friendly output.
-```
-
-#### `update_frequency`
-> string (That is parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
-
-The Remediation Component will poll the CrowdSec every `update_frequency` interval. (default: 10s)
-
-#### `include_scenarios_containing`
-> [ ]string
-
-Ignore IPs banned for triggering scenarios not containing either of provided word.
-
-```yaml title="Example"
-include_scenarios_containing: ["ssh", "http"]
-```
-
-#### `exclude_scenarios_containing`
-> [ ]string
-
-Ignore IPs banned for triggering scenarios containing either of provided word.
-
-```yaml title="Example"
-exclude_scenarios_containing: ["ssh", "http"]
-```
-
-#### `only_include_decisions_from`
-> [ ]string
-
-Only include IPs banned due to decisions orginating from provided sources.
-
-```yaml title="Example"
-only_include_decisions_from: ["cscli", "crowdsec"]
-```
-
-#### `insecure_skip_verify`
-> boolean
-
-Skip verification of the LAPI certificate, usually used for self-signed certificates
-
-#### `key_path`
-> string
-
-Path to the private key file to use for TLS authentication with CrowdSec LAPI.
-
-#### `cert_path`
-> string
-
-Path to the certificate file to use for TLS authentication with CrowdSec LAPI.
-
-#### `ca_cert_path`
-> string
-
-Path to the CA certificate file to use for TLS authentication with CrowdSec LAPI.
-
-### `cloudflare_config`
-
-Cloudflare configuration.
-
-#### `accounts[].id`
-> string
-
-The ID of the Cloudflare account.
-
-#### `accounts[].zones[].zone_id`
-> string
-
-The ID of the Cloudflare zone.
-
-#### `accounts[].zones[].actions`
-> `captcha` | `ban`
-
-Supported actions for the zone.
-
-#### `accounts[].zones[].default_action`
-> `captcha` | `ban` | `none`
-
-Default action to take for the zone.
-
-#### `accounts[].zones[].routes_to_protect`
-> [ ]string
-
-List of routes to protect within the zone. Example value ["*example.com/*"]
-
-#### `accounts[].zones[].turnstile.enabled`
-> boolean
-
-Enable or disable turnstile for the zone.
-
-#### `accounts[].zones[].turnstile.rotate_secret_key`
-> boolean
-
-Rotate the secret key for turnstile.
-
-#### `accounts[].zones[].turnstile.rotate_secret_key_every`
-> string (That is parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
-
-Duration for rotating the secret key. Values should be in the format of `1h2m3s`. Example value `168h0m0s` for 7 days.
-
-#### `accounts[].zones[].turnstile.mode`
-
-Mode for turnstile. Supported values ["managed", "invisible", "non-interactive"]. See [cloudflare-docs](https://developers.cloudflare.com/turnstile/reference/widget-types/) for more details.
-
-#### `accounts[].zones[].token`
-> string
-
-Cloudflare account token.
-
-#### `accounts[].zones[].account_name`
-> string
-
-Account name.
-
-#### `worker.log_only`
-> bool
-
-If true, allow all requests but keep track of what would have been blocked in the metrics.
-
-Defaults to `false`
-
-#### `worker.script_name`
-> string
-
-Name to use for the worker script.
-
-Default to `crowdsec-cloudflare-worker-bouncer`.
-
-#### `worker.kv_namespace_name`
-> string
-
-Title of the Worker KV namespace used to create/locate the decision store.
-
-Change this when running multiple bouncer instances on the same Cloudflare account so each instance uses its own KV namespace.
-
-Default to `CROWDSECCFBOUNCERNS`.
-
-#### `worker.decisions_sync_script_name`
-> string
-
-Name to use for the autonomous decisions sync worker script.
-
-Change this when running multiple bouncer instances on the same Cloudflare account so each instance uses its own sync worker.
-
-Default to `crowdsec-decisions-sync-worker`.
-
-#### `worker.analytics_dataset`
-> string
-
-Name of the [Workers Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/) dataset the worker writes metric data points to. See the [Metrics](#metrics) section.
-
-Must match `^[a-zA-Z_][a-zA-Z0-9_]{0,63}$`.
-
-Default to `crowdsec_cloudflare_bouncer`.
-
-#### `worker.logpush`
-> bool
-
-Enable logpush for the worker.
-
-Default to no value.
-
-#### `worker.compatibility_date`
-> string
-
-See https://developers.cloudflare.com/workers/configuration/compatibility-dates/.
-
-Default to no value
-
-#### `worker.compatibility_flags`
-> list of strings
-
-See https://developers.cloudflare.com/workers/configuration/compatibility-flags/.
-
-Default to no value.
-
-#### `worker.observability`
-> object
-
-Optional [Workers Observability](https://developers.cloudflare.com/workers/observability/logs/workers-logs/) (logs and traces) configuration. Omit the block to leave the Cloudflare defaults in place.
-
-If a deployed worker cannot have observability applied, a warning is logged but the deploy is not aborted.
-
-```yaml title="Example"
-observability:
- enabled: true
- head_sampling_rate: 1.0 # Sampling rate for head-based observability (0.0 to 1.0)
- traces:
- enabled: true
- head_sampling_rate: 1.0
-```
-
-#### `decisions_sync_worker.cron`
-> string
-
-Cron expression that defines how often the decisions sync worker runs in autonomous mode. This controls the frequency at which the worker fetches the latest decisions from CrowdSec LAPI and updates the KV store.
-
-The cron expression follows standard cron syntax with 5 fields: `minute hour day month day_of_week`
-
-Example values:
-- `*/1 * * * *` - Every minute (default)
-- `*/5 * * * *` - Every 5 minutes
-- `*/10 * * * *` - Every 10 minutes
-
-:::note
-This setting only applies to autonomous mode (when using the `-S` flag). In daemon mode, the `update_frequency` setting is used instead.
-:::
-
-Default to `*/5 * * * *` (every 5 minutes).
-
-
-
-### `prometheus`
-
-Prometheus configuration.
-
-#### `enabled`
-> boolean
-
-Enable or disable Prometheus metrics.
-
-#### `listen_addr`
-> string
-
-Address to listen for Prometheus metrics. Example value `127.0.0.1`
-
-#### `listen_port`
-> string
-
-Port to listen for Prometheus metrics. Example value `2112`
-
-### Others
-
-#### `ban_template_path`
-> string
-
-Path to the ban template file. If not provided, the default template is used. This HTML would be rendered to requests when they are banned.
-
-#### `log_level`
-> `info` | `debug` | `error` | `warning` | `trace`
-
-Log level of the Remediation Component.
-
-#### `log_mode`
-> `stdout` | `file`
-
-Where the log contents are written (With `file` it will be written to `log_dir` with the name `crowdsec-cloudflare-worker-bouncer.log`)
-
-#### `log_dir`
-
-Relevant if `log_mode` is `file`. This determines where to create log file.
-
-
-## Troubleshooting
- - Metrics can be seen at http://localhost:2112/metrics
diff --git a/crowdsec-docs/unversioned/bouncers/cloudflare.mdx b/crowdsec-docs/unversioned/bouncers/cloudflare.mdx
index 1da5d061f..0a6347487 100644
--- a/crowdsec-docs/unversioned/bouncers/cloudflare.mdx
+++ b/crowdsec-docs/unversioned/bouncers/cloudflare.mdx
@@ -1,6 +1,7 @@
---
id: cloudflare
-title: Cloudflare
+title: CrowdSec Cloudflare Worker Bouncer
+toc_max_heading_level: 3
---
import Tabs from '@theme/Tabs';
@@ -8,7 +9,6 @@ import TabItem from '@theme/TabItem';
import useBaseUrl from '@docusaurus/useBaseUrl';
import RemediationSupportBadges from '@site/src/components/remediation-support-badge';
-
@@ -19,505 +19,802 @@ import RemediationSupportBadges from '@site/src/components/remediation-support-b
-📚 Documentation
+📚 Documentation
💠 Hub
-💬 Discourse
+💬 Discourse
-
+:::tip
+ We recommend using the **Self-Hosted Installer** setup method for most users. It is simpler to install and maintain.
+ For comparative details, see the [Setup Methods](#setup-methods) section below.
+
+ Jump directly to the Setup section for your preferred method:
+ [Self-Hosted Installer](#self-hosted-setup) **_(Recommended)_**
+ [CLI Bouncer Daemon](#cli-bouncer-setup)
+:::
+:::tip
+ Direct link to generate the necessary Cloudflare token needed for this bouncer: [Cloudflare API Token](https://dash.cloudflare.com/profile/api-tokens?permissionGroupKeys=%5B%7B%22key%22%3A%22account_settings%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22challenge_widgets%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22user_details%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22workers_kv_storage%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22workers_routes%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22workers_scripts%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22zone%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22dns%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22account_analytics%22%2C%22type%22%3A%22read%22%7D%5D&name=)
+:::
+
+## Overview
+
+This **Remediation Component** uses **Cloudflare Workers** to block or challenge incoming traffic on your Cloudflare zones.
+
+**How it works:**
+- A list of IPs to remediate _(aka decisions)_ is stored in a **Cloudflare KV store**, each IP associated with an action, either:
+ - **Ban** (hard block with a custom HTML page)
+ - **Captcha** (Cloudflare turnstile challenge)
+- This list is kept up to date either by:
+ - A **Sync Worker** that periodically fetches decisions from CrowdSec.
+ - An installed bouncer script that pushes decisions to the KV store via Cloudflare's API.
+
+**There are two ways to deploy this bouncer:**
+- A fully **Self-Hosted** version with a browser-based Install&Config GUI **_(recommended)_**
+- A daemon **CLI Bouncer** running beside your Security Engine or as a standalone process.
+
+**Where do the IPs come from?**
+
+The source of those decisions
+
+- A **[Blocklist Integration Endpoint](/u/integrations/remediationcomponent)**: a URL served by CrowdSec, no infrastructure required on your side. This is the simplest option.
+- A **[Security Engine](/u/bouncers/intro)** you run in your own infrastructure: the Sync Worker connects to your LAPI to pull decisions directly.
+
+:::warning
+This Remediation Component relies on Cloudflare Workers and the KV store. It works best on a paid Workers subscription. See [Appendix: Cloudflare Free Plan](#appendix-test-with-cloudflare-free-plan) for details.
+:::
+
+## Setup Methods
+
+There are two ways to deploy this bouncer. Both end up with the **same Remediation Worker** and **Sync Worker(*)** running inside your Cloudflare account.
+- [Self-Hosted Installer](#self-hosted-setup) **_(Recommended)_**
+ - **Best For:** Blocklist Integration setups, minimal footprint, no server to maintain.
+ - **Setup:** WebUI, no YAML files, no daemon.
+- [CLI Bouncer Daemon](#cli-bouncer-setup)
+ - **Best For:** Security Engine setups, Prometheus metrics, advanced/IAC configuration (multiple instances, custom resource names).
+ - **Setup:** YAML config file, command-line flags, runs as a daemon or one-shot process.
+
+
+Here's a quick comparative overview:
+
+| | Self-Hosted Installer | CLI Bouncer Daemon |
+|---|---|---|
+| **Initial install** | Github Cloudflare integration | Host-based package install |
+| **Setup** | WebUI | config.yaml auto generation and manual edits |
+| **Decision source** | CrowdSec Blocklist Integration or Security Engine | CrowdSec Blocklist Integration or Security Engine |
+| **Decision sync** | Sync Worker | Bouncer daemon or possibility to use Sync Worker |
+| **Metrics** | Cloudflare Analytics Engine Queries | Prometheus metrics & pushed to CrowdSec Console |
+| **Auth to decisions source** | Basic Auth | Basic Auth or MTLS |
+
+:::warning
+After installation, configure the [Worker Route Fail Mode](#setting-up-the-worker-route-fail-mode) to FAIL OPEN to avoid service outages if the worker encounters errors or Cloudflare plan quota overruns.
+:::
+
+## Cloudflare API Token
+
+Both setup methods require a Cloudflare **user** API token with the following permissions.
+
+Click [**🔑 this link**](https://dash.cloudflare.com/profile/api-tokens?permissionGroupKeys=%5B%7B%22key%22%3A%22account_settings%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22challenge_widgets%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22user_details%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22workers_kv_storage%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22workers_routes%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22workers_scripts%22%2C%22type%22%3A%22edit%22%7D%2C%7B%22key%22%3A%22zone%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22dns%22%2C%22type%22%3A%22read%22%7D%2C%7B%22key%22%3A%22account_analytics%22%2C%22type%22%3A%22read%22%7D%5D&name=) to open the Cloudflare token creation page with the required permissions pre-selected, or create one manually at [Tokens](https://dash.cloudflare.com/profile/api-tokens) with:
+
+| Permission Group | Item | Permission |
+| ---------------- | ------------------ | ---------- |
+| Account | Turnstile | Edit |
+| Account | Workers KV Storage | Edit |
+| Account | Workers Scripts | Edit |
+| Account | Account Settings | Read |
+| Account | Account Analytics | Read |
+| User | User Details | Read |
+| Zone | DNS | Read |
+| Zone | Workers Routes | Edit |
+| Zone | Zone | Read |
+
+:::info
+By default the token is scoped to all accounts and zones you have access to. We recommend scoping it only to the accounts and zones you intend to protect.
+:::
+
+:::warning
+Each configured zone must have at least one `A` or `AAAA` DNS record. Zones with only `CNAME` records should be excluded from the scope — the bouncer tries to ignore them automatically, but failure to do so may result in higher KV storage charges.
+:::
+
+---
-:::danger
+## Self-Hosted Setup
-This bouncer isn't actively supported anymore, due to changes to Cloudflare's API rate limitations.
+The self-hosted setup uses a Cloudflare github integration to deploy a worker acting as the central install and configuration GUI for the Cloudflare bouncer elements.
-You should instead look at the [Cloudflare Workers Bouncer](/u/bouncers/cloudflare-workers).
+The steps are:
+- [Deploying the Installer Worker](#deploy-the-installer) to your Cloudflare account via GitHub or Gitlab
+ - One time action
+ - The installer will update automatically when the repository is updated
+- [Installing the bouncer and binding your zones via the Installer GUI](#configure-via-the-installer-ui)
+ - Easy One click or batch actions on you select zones
+ - Easy install/cleanup process
+Everything runs inside Cloudflare. No server, no daemon, no YAML files.
+
+### Deploy the Installer
+
+Click the button below to clone the installer into your GitHub or GitLab account and deploy it as a Cloudflare Worker:
+
+[](https://deploy.workers.cloudflare.com/?url=https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer-install)
+
+:::note
+The Cloudflare deploy flow forks the repository into your GitHub or GitLab account before deploying — you need an account on one of these platforms.
:::
-A Remediation Component that syncs the decisions made by CrowdSec with CloudFlare's firewall. Manages multi user, multi account, multi zone setup. Supports IP, Country and AS scoped decisions.
+Once deployed the Installer Worker will appear in the Workers & Pages section of your Cloudflare dashboard.
+Cloudflare gives you the URL of your Installer Worker. Open it to reach the installer GUI.
+
+
+
+{/* TODO: test if it does really clone, or explain how to deploy their own fork */}
+
+### Configure via the Installer UI
+
+Click on your Installer Worker URL to open the installer GUI.
+The UI is a three-step wizard. Work through each section top to bottom.
+
+
+
+{/* ADD SCREENSHOT: Full installer UI with all three sections visible, showing step numbers 1–3 */}
+
+---
+
+#### Step 1 — Cloudflare API Token
+
+:::info
+The Installer never stores your API token or credentials. They are held only in your browser session.
+_If you don't have a token yet, click **Create token ↗** in the UI. (see [Cloudflare API Token](#cloudflare-api-token) above for the permission list)._
+:::
+
+Paste your Cloudflare API token. The installer **validates** it immediately and confirms all required permissions are present.
+Upon validation, the installer fetches a list of all zones in your account and their current protection status.
+
+In the following step, you can then select which zones to protect.
+
+
+{/* ADD SCREENSHOT: Step 1 expanded, valid token entered, "Token is valid" message visible, list of zones below */}
+---
+
+#### Step 2 — CrowdSec Integration Endpoint
+
+Paste the URL of your CrowdSec decision source:
+
+- **Blocklist Integration Endpoint** — from the CrowdSec Console under your [Remediation Component integration](/u/integrations/remediationcomponent).
+- **Security Engine LAPI URL** — the URL of your self-hosted LAPI, reachable from Cloudflare's network. And [API key generated for the bouncer](/u/bouncers/intro#generate-an-api-key-for-your-bouncer).
+
+If you had a previous installation, the installer will pre-fill the field with the currently saved endpoint.
+You can edit it to change the endpoint without reinstalling by clicking **edit** and then **update now**.
+
+
+
+
+---
+
+#### Step 3 — Zone Protection
+
+This section lists every zone in your Cloudflare account with its current status.
+
+**Installing a zone:**
+
+You can install/uninstall individual zones or select multiple zones for batch install/uninstall.
+
+
+
+**Turnstile (CAPTCHA):**
+
+On installed zones you can activate the ability to have CAPTCHA decisions handled.
+Toggle **Supports CAPTCHA** on a zone enable a style of Turnstile for it (managed, non-interactive, invisible). Protected zones with Turnstile show a **SUPPORTS CAPTCHA** badge. You can toggle it on or off after installation as well.
+
+
+
+**Removing a zone:**
+
+Click **Remove** next to a protected zone to unbind the Remediation Worker from that zone and delete its Turnstile widget. The shared KV namespace and worker scripts remain in place for other protected zones.
+
+**Cleaning up all infrastructure:**
+
+Click **Uninstall all** to remove all bouncer infrastructure at once: unbind all zones, delete the shared KV namespace, and remove the worker scripts.
+The installer will prompt for confirmation before proceeding.
+
+_The uninstall all also removes infrastructure components from older versions of the cloudflare bouncer (D1 database)_
+
+---
+
+## CLI Bouncer Setup
+
+The CLI bouncer is a Go binary (`crowdsec-cloudflare-worker-bouncer`) that manages Cloudflare infrastructure from the command line using a YAML configuration file.
+
+It supports two modes:
+
+- **Daemon Mode** — the process runs continuously, syncing decisions from your Security Engine to the KV store on a regular interval. Workers and KV are cleaned up automatically when the daemon stops.
+- **Autonomous Mode** — the process deploys the Sync and Remediation Workers once and exits. All subsequent decision syncing is handled by the Sync Worker inside Cloudflare on a cron schedule.
-## Installation
+### Installing the CLI Bouncer
-### Repository
+#### From CrowdSec Repositories
-Packages for crowdsec-cloudflare-bouncer [are available on our repositories](/u/getting_started/installation/linux#repository-installation). You need to pick the package accord to your firewall system :
+Packages for `crowdsec-cloudflare-worker-bouncer` are [available on our repositories](/u/getting_started/installation/linux#repository-installation):
+ { label: 'Debian/Ubuntu', value: 'debian' },
+ { label: 'RHEL/Centos/Fedora', value: 'rhel' },
+ ]}
+>
```bash
-sudo apt install crowdsec-cloudflare-bouncer
+sudo apt install crowdsec-cloudflare-worker-bouncer
```
```bash
-sudo yum install crowdsec-cloudflare-bouncer
+sudo yum install crowdsec-cloudflare-worker-bouncer
```
+Then set up the bouncer:
-Then run the following commands to setup your bouncer:
-
+
+
```bash
-sudo crowdsec-cloudflare-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
-sudo crowdsec-cloudflare-bouncer -s # this sets up IP lists and firewall rules at cloudflare for the provided config.
-sudo systemctl start crowdsec-cloudflare-bouncer # the bouncer now syncs the crowdsec decisions with cloudflare components.
+# Auto-generate config from your Cloudflare tokens
+sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+# Review config and set crowdsec_config.lapi_key
+sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+# Start the daemon
+sudo systemctl start crowdsec-cloudflare-worker-bouncer
```
-:::warning
-
-Please configure your server to emit real IPs rather than cloudflare IPs in logs, so crowdsec can function properly. See how to [here](https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs)
+
+
-:::
+```bash
+# Auto-generate config from your Cloudflare tokens
+sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+# Review config and set crowdsec_config.lapi_key
+sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+# Deploy workers to Cloudflare and exit — no daemon needed
+sudo crowdsec-cloudflare-worker-bouncer -S -c /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+```
-:::info
+In autonomous mode the Go process deploys the configuration to Cloudflare and exits. All decision synchronization is handled by Cloudflare scheduled workers.
-If your component is not installed on the same machine than LAPI, don't forget to set the `crowdsec_lapi_url` and `crowdsec_lapi_key` in the configuration file `/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml`
+
+
+:::warning
+Configure your origin server to emit real visitor IPs rather than Cloudflare IPs in logs, so CrowdSec can function properly. See [Restoring original visitor IPs](https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs).
:::
-:::note
-
-You need to run `sudo crowdsec-cloudflare-bouncer -d` to cleanup exisiting cloudflare components created by component before editing the config files.
-
+:::info
+If the bouncer is not installed on the same machine as LAPI, set `crowdsec_config.lapi_url` and `crowdsec_config.lapi_key` in the configuration file.
:::
:::note
-
-You can run `sudo crowdsec-cloudflare-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml` to generate the configuration by discovering all the accounts and the zones associated with the provided tokens.
-
+Run `sudo crowdsec-cloudflare-worker-bouncer -d` to clean up existing Cloudflare infrastructure before editing the config file.
:::
+#### Manual Installation
-### Manual
-
-#### Assisted
+Download the [latest release](https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer/releases).
-Download the [latest release](https://github.com/crowdsecurity/cs-cloudflare-bouncer/releases).
+
+
```bash
-tar xzvf crowdsec-cloudflare-bouncer.tgz
-cd crowdsec-cloudflare-bouncer/
+tar xzvf crowdsec-cloudflare-worker-bouncer.tgz
+cd crowdsec-cloudflare-worker-bouncer/
sudo ./install.sh
-sudo crowdsec-cloudflare-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml # auto-generate cloudflare config for provided tokens
-sudo crowdsec-cloudflare-bouncer -s # this sets up IP lists and firewall rules at cloudflare for the provided config.
-sudo systemctl start crowdsec-cloudflare-bouncer # the bouncer now syncs the crowdsec decisions with cloudflare components.
+sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+sudo systemctl start crowdsec-cloudflare-worker-bouncer
```
-#### From source
+
+
```bash
-make release
-cd crowdsec-cloudflare-bouncer-vX.X.X
+tar xzvf crowdsec-cloudflare-worker-bouncer.tgz
+cd crowdsec-cloudflare-worker-bouncer/
sudo ./install.sh
+sudo crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+sudo crowdsec-cloudflare-worker-bouncer -S -c /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
```
-Rest of the steps are same as of the above method.
-
-
-## Container
-
-Make sure you have docker or podman installed. In this guide we will use docker, but podman would work as a drop in replacement too.
-### Setup
-
-```bash
-docker run crowdsecurity/cloudflare-bouncer \
- -g , > cfg.yaml # auto-generate cloudflare config for provided space separated tokens
-```
+
+
-You can then review the contents of the file `cfg.yaml` and make any necessary changes.
+#### From Source
-```
-vim cfg.yaml # review config and set `crowdsec_lapi_key`
-```
+:::note
+Requires Go >= 1.23
+:::
-The `crowdsec_lapi_key` can be obtained by running the following:
+
+
```bash
-sudo cscli -oraw bouncers add cloudflarebouncer # -oraw flag can discarded for human friendly output.
+git clone https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer
+cd cs-cloudflare-worker-bouncer
+make release
+cd crowdsec-cloudflare-worker-bouncer-*
+./crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+sudo systemctl start crowdsec-cloudflare-worker-bouncer
```
-The `crowdsec_lapi_url` must be accessible from the container.
-
-### Runtime
+
+
```bash
- docker run \
- -v $PWD/cfg.yaml:/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml \
- -p 2112:2112 \
- crowdsecurity/cloudflare-bouncer
+git clone https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer
+cd cs-cloudflare-worker-bouncer
+make release
+cd crowdsec-cloudflare-worker-bouncer-*
+./crowdsec-cloudflare-worker-bouncer -g , -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
+./crowdsec-cloudflare-worker-bouncer -S -c /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
```
+
+
-## Configuration
+### Daemon Mode
-Configuration file can be found at `/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml`
+The Go process runs continuously and:
-```yaml
-# CrowdSec Config
-crowdsec_lapi_url: http://localhost:8080/
-crowdsec_lapi_key: ${API_KEY}
-crowdsec_update_frequency: 10s
-include_scenarios_containing: [] # ignore IPs banned for triggering scenarios not containing either of provided word, eg ["ssh", "http"]
-exclude_scenarios_containing: [] # ignore IPs banned for triggering scenarios containing either of provided word
-only_include_decisions_from: [] # only include IPs banned due to decisions orginating from provided sources. eg value ["cscli", "crowdsec"]
-
-#Cloudflare Config.
-cloudflare_config:
- accounts:
- - id:
- token:
- ip_list_prefix: crowdsec
- default_action: managed_challenge
- total_ip_list_capacity: # only this many latest ip scoped decisions would be kept
-
- zones:
- - actions:
- - managed_challenge # valid choices are either of managed_challenge, js_challenge, block
- zone_id:
-
- update_frequency: 30s # the frequency to update the cloudflare IP list
-
-# Component Config
-daemon: true
-log_mode: file
-log_dir: /var/log/
-log_level: info # valid choices are either debug, info, error
-log_max_size: 40
-log_max_age: 30
-log_max_backups: 3
-compress_logs: true
+1. Creates a Cloudflare Worker and a KV namespace per configured account.
+2. Creates Worker Routes per configured zone — all matching requests are handled by the worker.
+3. Periodically polls your Security Engine or Blocklist Integration and updates the KV store with the latest decisions.
+4. For every incoming request, the Remediation Worker checks the IP, country, and AS against the KV store and applies the matching remediation.
-prometheus:
- enabled: true
- listen_addr: 127.0.0.1
- listen_port: 2112
-```
+*A Blocklist Integration endpoint can be substituted for the Security Engine in the diagram below.*
-## Making changes to configuration
+
-The component creates Cloudflare infra (IP lists, rules etc) according to your config file.
+:::info
+The Workers and KV created by the bouncer are cleaned up from Cloudflare automatically on daemon stop or launch error.
+:::
-Before changing the config, always run the following command to clear old infra:
+### Autonomous Mode
-```
-sudo crowdsec-cloudflare-bouncer -d
-```
+The Go process deploys the infrastructure once and exits. No persistent daemon is needed.
-### Upgrading from v0.0.X to v0.1.Y
+Two Cloudflare Workers are deployed:
-During v0.0.X there was no `managed_challenge` action, instead `challenge` action was used by bouncer. This is deprecated since v0.1.0 .
+- `crowdsec-cloudflare-worker-bouncer` (Remediation Worker) — applies cached decisions to incoming requests.
+- `decisions-sync-worker` (Sync Worker) — periodically fetches decisions from CrowdSec using Cloudflare scheduled tasks.
-This section assumes you used the default config (generated via `crowdsec-cloudflare-bouncer -g ,` )
+
-After upgrading the component from v0.0.X to v0.1.Y , run the following commands to migrate to `managed_challenge`.
+Once deployed, the Sync Worker runs on the configured cron schedule and keeps the KV store current.
-```bash
-sudo crowdsec-cloudflare-bouncer -d
-sudo crowdsec-cloudflare-bouncer -g , -o
-sudo systemctl restart crowdsec-cloudflare-bouncer
-```
+
+
-## Cloudflare Configuration
+#### Resetting Decisions
-**Background:** In Cloudflare, each user can have access to multiple accounts. Each account can own/access multiple zones. In this context a zone can be considered as a domain. Each domain registered with cloudflare gets a distinct `zone_id`.
+To reset all decisions in the KV store without redeploying the infrastructure, add a `RESET` key with value `true` to the KV namespace via the Cloudflare dashboard. On the next sync cycle the worker will clear all existing decisions and repopulate from CrowdSec.
+### Metrics
-For obtaining the `token`:
-1. Sign in as a user who has access to the desired account.
-2. Go to [Tokens](https://dash.cloudflare.com/profile/api-tokens) and create the token. The component requires the following permissions to function.
-
+The Remediation Worker writes metric data points to a [Workers Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/) dataset, tracking:
-To automatically generate config for cloudflare check the helper section below.
+- Number of requests processed
+- Number of requests blocked
+- Number of requests that threw an exception
+- Average request processing latency
+:::info
+Since `v0.0.18`, metrics are stored in a Workers Analytics Engine dataset instead of a D1 database. Make sure your Cloudflare token has `Account Analytics: Read` permission (see the [permissions table](#cloudflare-api-token)). Without it the metric poll returns a `403` and metrics are disabled, but remediation enforcement is unaffected.
-:::note
-If the zone is subscribed to a paid Cloudflare plan then it can be configured to support multiple types of actions. For free plan zones only one action is supported. The first action is applied as default action.
+If upgrading from an older version, the legacy `CROWDSECCFBOUNCERDB` D1 database is no longer used and can be deleted manually from the Cloudflare dashboard.
:::
-## Helpers
+The dataset name defaults to `crowdsec_cloudflare_bouncer` and can be customized with [`worker.analytics_dataset`](#workeranalytics_dataset).
-The component binary has built in helper scripts to do various operations.
+**In Daemon Mode**, the running process polls the Analytics Engine SQL API, exposes metrics via Prometheus, and pushes them to CrowdSec for `cscli` visualization.
-### Auto config generator
+**In Autonomous Mode**, metrics are collected in the Analytics Engine dataset but are **not pushed to CrowdSec**.
-Generates component config by discovering all the accounts and the zones associated with provided list of tokens.
+### CLI Helpers
-Example Usage:
+#### Auto Config Generator
+
+Generates a configuration file by discovering all accounts and zones associated with your tokens:
```bash
-sudo crowdsec-cloudflare-bouncer -g ,... -o /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml
+sudo crowdsec-cloudflare-worker-bouncer -g , -o cfg.yaml
+cat cfg.yaml > /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
```
:::note
-This script only generates cloudflare related config. By default it refers to the config at `/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml` for crowdsec configuration.
+This only generates Cloudflare-related config. CrowdSec LAPI config must be set manually in the output file.
:::
-Using custom config:
+Using a custom config path:
```bash
-sudo crowdsec-cloudflare-bouncer -c /path/to/config/file -g ,...
+sudo crowdsec-cloudflare-worker-bouncer -c ./cfg.yaml -g ,
```
-### Cloudflare Setup
+#### Cloudflare Cleanup
-This only creates the required IP lists and firewall rules at cloudflare and exits.
+Deletes all Cloudflare infrastructure created by the bouncer:
-Example Usage:
```bash
-sudo crowdsec-cloudflare-bouncer -s
+sudo crowdsec-cloudflare-worker-bouncer -d
```
-### Cloudflare Cleanup
+---
+
+## Setting Up the Worker Route Fail Mode
-This deletes all IP lists and firewall rules at cloudflare which were created by the component.
+Worker routes are created with **Fail Closed** mode by default. In this mode, any worker error results in a Cloudflare 1027 error page shown to visitors — including errors caused by plan quota overruns.
+
+There is no public Cloudflare API to change this. **We recommend manually switching all bouncer-created routes to Fail Open**, so that if the worker encounters an error, traffic bypasses it and reaches your origin server normally.
+
+1. Log in to the Cloudflare dashboard and select your account.
+2. Open the website's Overview page.
+3. Click **Worker Routes** in the left menu.
+
+
+
+4. Click the route created by the bouncer, then click **Edit**.
+5. Under **Request limit failure mode**, select **Fail open**.
+
+
+
+---
+
+## Appendix: Test with Cloudflare Free Plan
+
+Using the free plan is feasible but requires understanding its constraints.
+
+### Free Plan Limitations
+
+| Limit | Value | Impact |
+|---|---|---|
+| KV writes | 1,000 / day | Initial blocklist population is truncated to 1K IPs |
+| Worker requests | 100K / day or 1K / min | Heavy traffic may exhaust quota |
+
+The KV write limit is the primary constraint — large blocklists (tens of thousands of IPs) will be truncated on first sync. Incremental updates still flow in over time, so coverage grows gradually.
+
+When the request quota is exhausted, the worker stops applying remediation. This makes [setting Fail Open](#setting-up-the-worker-route-fail-mode) essential — without it your site returns error pages to all visitors once the quota is hit.
+
+### Recommended Free Plan Configuration
+
+1. **Auto-generate config**: [use the config generator](#auto-config-generator).
+2. **Limit decision sources** to your local Security Engine only:
+
+```yaml
+crowdsec_config:
+ only_include_decisions_from: ["cscli", "crowdsec"]
+```
+
+3. **Set Fail Open** on all worker routes: [instructions above](#setting-up-the-worker-route-fail-mode).
+4. **Test with a manual decision**:
-Example Usage:
```bash
-sudo crowdsec-cloudflare-bouncer -d
+sudo cscli decisions add --ip 192.168.1.1 --type captcha
+sudo cscli decisions list --origin cscli
```
-## How it works
+Within a few seconds the decision appears in the KV store and the remediation is enforced.
-The service polls the CrowdSec Local API for new / deleted decisions. It then makes API calls to Cloudflare to update IP lists and firewall rules depending upon the decision.
+---
## Configuration Reference
-### `crowdsec_lapi_url`
-> string
+### `crowdsec_config`
-The URL of CrowdSec LAPI. It should be accessible from the component.
+```yaml
+crowdsec_config:
+ lapi_key: ${API_KEY}
+ lapi_url: ${CROWDSEC_LAPI_URL}
+ update_frequency: 10s
+ include_scenarios_containing: []
+ exclude_scenarios_containing: []
+ only_include_decisions_from: []
+ insecure_skip_verify: false
+ key_path: "" # TLS client key for LAPI authentication
+ cert_path: "" # TLS client cert for LAPI authentication
+ ca_cert_path: "" # CA cert to trust the LAPI certificate
-### `crowdsec_lapi_key`
-> string
+cloudflare_config:
+ accounts:
+ - id:
+ zones:
+ - zone_id:
+ actions:
+ - captcha
+ default_action: captcha # captcha | ban | none
+ routes_to_protect: []
+ turnstile:
+ enabled: true
+ rotate_secret_key: true
+ rotate_secret_key_every: 168h0m0s
+ mode: managed # managed | invisible | non-interactive
+ token:
+ account_name: owner@example.com
+ worker:
+ log_only: false
+ script_name: ""
+ kv_namespace_name: ""
+ decisions_sync_script_name: ""
+ analytics_dataset: ""
+ logpush: null
+ tags: []
+ compatibility_date: ""
+ compatibility_flags: []
+ observability:
+ enabled: true
+ head_sampling_rate: 1.0
+ traces:
+ enabled: true
+ head_sampling_rate: 1.0
+ decisions_sync_worker:
+ cron: '*/5 * * * *'
+
+log_level: info
+log_media: "stdout"
+log_dir: "/var/log/"
+ban_template_path: ""
-API key to authenticate with the LAPI.
+prometheus:
+ enabled: true
+ listen_addr: 127.0.0.1
+ listen_port: "2112"
+```
-### `cert_path`
+#### `crowdsec_config.lapi_url`
> string
-Path to the certificate file used to authenticate with the LAPI.
+URL of CrowdSec LAPI. Must be accessible from the bouncer.
-### `key_path`
+#### `crowdsec_config.lapi_key`
> string
-Path to the key file used to authenticate with the LAPI.
-
-### `ca_path_file`
-> string
+Bouncer API key. Obtain it by running on the LAPI machine:
-Path to the CA file used to trust the LAPI certificate.
+```bash
+sudo cscli -oraw bouncers add cloudflarebouncer
+```
-### `crowdsec_update_frequency`
-> string (That is parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
+#### `crowdsec_config.update_frequency`
+> string (parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
-The component will poll the CrowdSec every `update_frequency` interval.
+How often the bouncer polls CrowdSec. Default: `10s`.
-### `include_scenarios_containing`
-> [ ]string
+#### `crowdsec_config.include_scenarios_containing`
+> []string
-Ignore IPs banned for triggering scenarios not containing either of provided word.
+Only include decisions for IPs that triggered scenarios containing one of these words.
```yaml title="Example"
include_scenarios_containing: ["ssh", "http"]
```
-### `exclude_scenarios_containing`
-> [ ]string
+#### `crowdsec_config.exclude_scenarios_containing`
+> []string
-Ignore IPs banned for triggering scenarios containing either of provided word.
+Exclude decisions for IPs that triggered scenarios containing one of these words.
```yaml title="Example"
exclude_scenarios_containing: ["ssh", "http"]
```
-### `only_include_decisions_from`
-> [ ]string
+#### `crowdsec_config.only_include_decisions_from`
+> []string
-Only include IPs banned due to decisions orginating from provided sources.
+Only include decisions originating from these sources.
```yaml title="Example"
only_include_decisions_from: ["cscli", "crowdsec"]
```
-### `cloudflare_config`
-> [CloudflareConfig](https://github.com/crowdsecurity/cs-cloudflare-bouncer/blob/20c902ee1e95fe13135dd493d7e96840bafc931b/pkg/cfg/config.go#L34-L37)
+#### `crowdsec_config.insecure_skip_verify`
+> boolean
-This block contains cloudflare specific config.
+Skip TLS certificate verification for LAPI. Use for self-signed certificates.
-#### `update_frequency`
-> string (That is parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
+#### `crowdsec_config.key_path` / `cert_path` / `ca_cert_path`
+> string
-The frequency at which to update the cloudflare resources.
+Paths to TLS client key, certificate, and CA certificate for mutual TLS authentication with LAPI.
-```yaml title="Example"
-update_frequency: "10s"
-```
+### `cloudflare_config`
-#### `accounts`
-> [ ][AccountConfig](https://github.com/crowdsecurity/cs-cloudflare-bouncer/blob/20c902ee1e95fe13135dd493d7e96840bafc931b/pkg/cfg/config.go#L26-L33)
+#### `accounts[].id`
+> string
-List of account of configs
+Cloudflare account ID.
-##### `id`
+#### `accounts[].zones[].zone_id`
> string
-id of cloudflare account
+Cloudflare zone ID.
-##### `token`
-> string
+#### `accounts[].zones[].actions`
+> `captcha` | `ban`
-cloudflare token to use to access the account.
+Remediations supported by this zone.
-##### `ip_list_prefix`
-> string
+#### `accounts[].zones[].default_action`
+> `captcha` | `ban` | `none`
-The prefix to use for naming the IP lists created by the bouncer. The name of IP list will be of the form `ip_list_prefix`+`action`.
+Remediation applied when a decision's type is not in `actions`. Set to `none` to ignore such decisions.
-##### `total_ip_list_capacity`
-> int
+#### `accounts[].zones[].routes_to_protect`
+> []string
-Limit the number of items in IP lists. This is required for avoiding limit of 10k items for lists.
+Routes within the zone to protect. Example: `["*example.com/*"]`
-##### `default_action`
-> `managed_challenge` | `block` | `js_challenge` | `challenge` | `none`
+#### `accounts[].zones[].turnstile.enabled`
+> boolean
-The action to be applied for a decision, if the decision's action is not supported by a zone.
+Enable Turnstile (CAPTCHA) for this zone.
-`default_action` must be supported by all zones.
+#### `accounts[].zones[].turnstile.rotate_secret_key`
+> boolean
-**Example:**
+Automatically rotate the Turnstile secret key.
-Consider your zone config supports the actions `managed_challenge` and `js_challenge`. Your `default_action` is `managed_action`. If you create the following decision:
+#### `accounts[].zones[].turnstile.rotate_secret_key_every`
+> string (parseable by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration))
-```
-sudo cscli decisions add --ip 192.168.1.1 --type ban
-```
+Rotation interval. Example: `168h0m0s` (7 days).
-Since the zone doesn't support `ban` decision type, it'll be inserted into the IP list given by `default_action`. In this case it'll be the list for `managed_challenge`.
+#### `accounts[].zones[].turnstile.mode`
+> `managed` | `invisible` | `non-interactive`
-You can completely ignore such decisions by setting `default_action` to `none`. It won't be inserted into any list then.
+Turnstile widget mode. See [Cloudflare docs](https://developers.cloudflare.com/turnstile/reference/widget-types/).
-**Note:**
+#### `accounts[].token`
+> string
-Following table is mapping of decision type to it's destination IP list.
+Cloudflare API token for this account.
-| Decision Type | Default Action |
-| ------------- | ----------------- |
-| captcha | managed_challenge |
-| ban | block |
-| js_challenge | js_challenge |
+#### `accounts[].account_name`
+> string
+Human-readable account name.
-:::warning
-`challenge` action is deprecated in favour of `managed_challenge`.
-:::
+#### `worker.log_only`
+> bool
-#### `zones`
-> [ ][ZoneConfig](https://github.com/crowdsecurity/cs-cloudflare-bouncer/blob/20c902ee1e95fe13135dd493d7e96840bafc931b/pkg/cfg/config.go#L21-L25)
+If `true`, allow all requests but record what would have been blocked in metrics. Default: `false`.
+
+#### `worker.script_name`
+> string
-This block contains config for each zone to be managed by the component. The zone must be accessible from the parent account.
+Name of the Remediation Worker script. Default: `crowdsec-cloudflare-worker-bouncer`.
-##### `zone_id`
+#### `worker.kv_namespace_name`
> string
-The id of the zone.
+Name of the KV namespace. Change this when running multiple bouncer instances on the same account. Default: `CROWDSECCFBOUNCERNS`.
-##### `actions`
-> [ ]string
+#### `worker.decisions_sync_script_name`
+> string
-List of actions to be supported by this zone. If the zone is not subscribed to premium plan, then only a single action can be given.
+Name of the Sync Worker script. Change when running multiple instances. Default: `crowdsec-decisions-sync-worker`.
-The supported action must include the `default_action` of the parent account.
+#### `worker.analytics_dataset`
+> string
-Valid choice includes either of
-- `block`
-- `js_challenge`
-- `challenge`
-- `managed_challenge`.
+Workers Analytics Engine dataset name for metrics. Must match `^[a-zA-Z_][a-zA-Z0-9_]{0,63}$`. Default: `crowdsec_cloudflare_bouncer`.
-The component creates an IP list for each action. IP list is at account level, so multiple zones with same parent account will share lists for particular action.
+#### `worker.logpush`
+> bool
-:::warning
-`challenge` action is deprecated in favour of `managed_challenge`
-:::
+Enable log push for the worker.
-**Note:**
+#### `worker.compatibility_date`
+> string
-Following table is mapping of decision type to it's destination IP list, which are created according to zone actions
+See [Cloudflare compatibility dates](https://developers.cloudflare.com/workers/configuration/compatibility-dates/).
+#### `worker.compatibility_flags`
+> []string
-| Decision Type | Zone Action |
-| ------------- | ----------------- |
-| captcha | managed_challenge |
-| ban | block |
-| js_challenge | js_challenge |
+See [Cloudflare compatibility flags](https://developers.cloudflare.com/workers/configuration/compatibility-flags/).
+#### `worker.observability`
+> object
+Optional [Workers Observability](https://developers.cloudflare.com/workers/observability/logs/workers-logs/) configuration. Omit to leave Cloudflare defaults in place.
-### `daemon`
-> boolean
+```yaml title="Example"
+observability:
+ enabled: true
+ head_sampling_rate: 1.0
+ traces:
+ enabled: true
+ head_sampling_rate: 1.0
+```
-:::warning
-This field has now been deprecated and is ignored within the component
+#### `decisions_sync_worker.cron`
+> string
+
+Cron schedule for the Sync Worker in autonomous mode. Standard 5-field cron syntax.
+
+Examples:
+- `*/1 * * * *` — every minute
+- `*/5 * * * *` — every 5 minutes (default)
+- `*/10 * * * *` — every 10 minutes
+
+:::note
+Applies only to autonomous mode. In daemon mode, `crowdsec_config.update_frequency` controls sync frequency.
:::
-Run the component as a daemon.
+### `prometheus`
-### `log_mode`
-> `stdout` | `file`
+#### `enabled`
+> boolean
-Where the log contents are written (With `file` it will be written to `log_dir` with the name `crowdsec-cloudflare-bouncer.log`)
+Enable Prometheus metrics endpoint.
-### `log_dir`
+#### `listen_addr`
> string
-Relevant if `log_mode` is `file`. This determines where to create log file.
+Address to bind. Example: `127.0.0.1`.
-### `log_level`
-> `trace` | `debug` | `info` | `error`
+#### `listen_port`
+> string
-Log level for the component.
+Port to bind. Example: `2112`.
-### `compress_logs`
-> `true` | `false`
+### Others
-Compress log files on rotation
+#### `ban_template_path`
+> string
-### `log_max_size`
-> int (in MB)
+Path to a custom HTML template rendered for banned requests. Leave empty to use the default.
-Max size of log files before rotation
+#### `log_level`
+> `info` | `debug` | `error` | `warning` | `trace`
-### `log_max_backups`
-> int
+#### `log_media`
+> `stdout` | `file`
-How many backup log files to keep before deletion (can happen before `log_max_age` is reached)
+With `file`, logs are written to `log_dir/crowdsec-cloudflare-worker-bouncer.log`.
-### `log_max_age`
-> int (in days)
+#### `log_dir`
+> string
-Max age of backup files before deletion (can happen before `log_max_backups` is reached)
+Log directory when `log_media` is `file`.
## Troubleshooting
- - Metrics can be seen at http://localhost:2112/metrics
- - Logs are in `/var/log/crowdsec-cloudflare-bouncer.log` (Default unless changed in config)
- - You can view/interact directly in the ban list either with `cscli`
- - Service can be started/stopped with `systemctl start/stop crowdsec-cloudflare-bouncer`
+
+- Prometheus metrics: `http://localhost:2112/metrics`
+
diff --git a/crowdsec-docs/unversioned/bouncers/intro.md b/crowdsec-docs/unversioned/bouncers/intro.md
index 13302a18d..2d2876dad 100644
--- a/crowdsec-docs/unversioned/bouncers/intro.md
+++ b/crowdsec-docs/unversioned/bouncers/intro.md
@@ -42,6 +42,8 @@ Remediation Components interact with [crowdsec's Local API](/docs/next/local_api
For your remediation components to communicate with the local API, you have to generate an API token with `cscli` and put it in the associated configuration file:
+### Generate an API Key for your Bouncer
+
```bash
sudo cscli bouncers add testBouncer
Api key for 'testBouncer':