The Defend-O-Tron exposes its CrowdSec Local API (LAPI) so external systems can share the same live threat intelligence the device has built up. The remote systems run a small piece of software called a bouncer — the bouncer pulls the decision stream from the Defend-O-Tron and applies blocks locally on whatever platform it's running on.
A single Defend-O-Tron can feed many bouncers — your office router, your web servers, branch-office firewalls — all from the same threat picture. The Defend-O-Tron stays out of the data path; only the decisions cross the wire.
Every bouncer setup, regardless of platform, needs the same four things:
| What | Value |
|---|---|
| LAPI endpoint | https://crowdsec.protected.lan/lapi |
| Auth | A bouncer API key (one per remote system, issued by the device) |
| TLS trust | The Defend-O-Tron Root CA installed on the remote system |
| DNS | The remote system must resolve crowdsec.protected.lan |
The rest of this page walks through generating the key, getting TLS and DNS set up on the remote side, then five worked bouncer configurations.
Open the admin interface, click Tools → Terminal, then run:
sudo cscli bouncers add my-web-server
Use a name that makes sense for the remote system (branch-office-router, prod-nginx-01, etc.) — you'll see it in the bouncer list later.
The output prints a long random key:
Api key for 'my-web-server':
abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567
Please keep this key since you will not be able to retrieve it!
Copy this key now. It's shown exactly once — the Defend-O-Tron stores only a hash, so there's no way to look it up afterward. If you lose it, delete the bouncer and re-add it.
crowdsec.protected.lanThe bouncer connects by hostname, not by IP, because TLS certificate validation depends on the hostname matching the certificate.
protected.lan zone resolves automatically.echo "<defend-o-tron-ip> crowdsec.protected.lan" | sudo tee -a /etc/hostsC:\Windows\System32\drivers\etc\hosts (as Administrator)The LAPI is served over HTTPS using the Defend-O-Tron's internal certificate authority. To avoid TLS errors, the remote system needs to trust that CA.
/usr/local/share/ca-certificates/defend-o-tron.crt, then sudo update-ca-certificates./etc/pki/ca-trust/source/anchors/, then sudo update-ca-trust.Pick the tab matching your platform.
For a Debian/Ubuntu Linux box (web server, application server, branch router on Linux) where you want to drop traffic from blocked IPs at the system firewall level.
sudo apt install crowdsec-firewall-bouncer-nftables
(Use crowdsec-firewall-bouncer-iptables instead if your system still uses iptables.)
Edit /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml:
mode: nftables
log_level: info
api_url: https://crowdsec.protected.lan/lapi/
api_key: abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567
update_frequency: 10s
insecure_skip_verify: false
Leave
insecure_skip_verify: false. With the Defend-O-Tron Root CA installed in step 3, TLS verification works correctly. Disabling it defeats the entire point of using HTTPS.
sudo systemctl restart crowdsec-firewall-bouncer
sudo systemctl status crowdsec-firewall-bouncer
sudo journalctl -u crowdsec-firewall-bouncer -n 50
Look for Sync done lines in the logs and a non-empty cs-firewall-bouncer nftables table when you run sudo nft list ruleset.
For an NGINX reverse proxy or web server where you want to reject blocked IPs at the HTTP layer (returning 403 instead of letting them connect to your application).
On Debian/Ubuntu:
sudo apt install crowdsec-nginx-bouncer
The package adds a Lua plugin that NGINX loads on every request.
Edit /etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf:
API_URL=https://crowdsec.protected.lan/lapi/
API_KEY=abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567
BOUNCING_ON_TYPE=all
MODE=stream
UPDATE_FREQUENCY=10
Restart NGINX:
sudo systemctl reload nginx
The bouncer writes its own logs to /var/log/crowdsec-nginx-bouncer.log. A successful sync looks like:
crowdsec-nginx-bouncer | INFO | starting up
crowdsec-nginx-bouncer | INFO | initial decisions fetch: 1842 active
Test by browsing from an unblocked IP (should work normally) and from a known-bad IP listed in cscli decisions list (should get a 403).
For a Traefik v2/v3 reverse proxy where you want CrowdSec decisions enforced as a middleware.
Add to your Traefik static configuration (traefik.yml or equivalent):
experimental:
plugins:
crowdsec-bouncer-traefik-plugin:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.4.2
Add to your Traefik dynamic configuration:
http:
middlewares:
crowdsec:
plugin:
crowdsec-bouncer-traefik-plugin:
enabled: true
logLevel: INFO
updateIntervalSeconds: 60
crowdsecMode: stream
crowdsecLapiScheme: https
crowdsecLapiHost: crowdsec.protected.lan
crowdsecLapiPath: /lapi/
crowdsecLapiKey: abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567
Reference crowdsec@file as a middleware on the routers you want to protect:
http:
routers:
my-app:
rule: Host(`app.example.com`)
service: my-app
middlewares:
- crowdsec
Restart Traefik. Confirm the plugin loaded by checking the Traefik logs for crowdsec-bouncer-traefik-plugin starting.
For a MikroTik RouterOS device where you want CrowdSec decisions applied as address-list entries that your firewall filter rules already consume.
The bouncer runs alongside the MikroTik (on a Linux box, often a Raspberry Pi or small VM), not on RouterOS itself. It bridges the Defend-O-Tron LAPI to the MikroTik API.
Recommended: funkolab/mikrotik-bouncer as a Docker container.
docker run -d --name mikrotik-bouncer --restart=unless-stopped \
-e CROWDSEC_API_URL=https://crowdsec.protected.lan/lapi \
-e CROWDSEC_BOUNCER_API_KEY=abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567 \
-e MIKROTIK_HOST=192.168.88.1 \
-e MIKROTIK_USER=crowdsec \
-e MIKROTIK_PASSWORD=<routeros-api-password> \
-e MIKROTIK_TLS=true \
-e MIKROTIK_BLACKLIST=crowdsec-blocked \
-v /etc/ssl/certs:/etc/ssl/certs:ro \
funkolab/mikrotik-bouncer:latest
Create a dedicated API user on the MikroTik with just the read,write,api rights it needs:
/user/group add name=crowdsec policy=read,write,api
/user add name=crowdsec group=crowdsec password=<set-a-strong-one>
Reference the address list in your firewall filter:
/ip/firewall/filter
add chain=input src-address-list=crowdsec-blocked action=drop comment="CrowdSec block"
add chain=forward src-address-list=crowdsec-blocked action=drop comment="CrowdSec block"
Decisions from the Defend-O-Tron will start populating crowdsec-blocked within 30 seconds of the bouncer starting.
For a pfSense firewall where you want CrowdSec decisions applied as a pfSense alias used by your firewall rules.
crowdsec, click Install on the CrowdSec Bouncer package.https://crowdsec.protected.lan/lapi/abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567The bouncer creates a pfSense alias (typically named crowdsec_blacklists). In Firewall → Rules → WAN, add a block rule near the top that uses this alias as the source. Save and apply.
Confirm the alias is being populated under Firewall → Aliases → IP.
Back on the Defend-O-Tron admin terminal:
sudo cscli bouncers list
You should see your new bouncer with a recent last_pull timestamp and valid status:
Name IP Address Valid Last API pull Type Version Auth Type
my-web-server 203.0.113.7 ✔ 2026-05-15 19:14:22 crowdsec-firewall-bouncer v0.0.30 api-key
If last_pull is empty or very old, jump to the troubleshooting section below.
| Task | Command (on the Defend-O-Tron admin terminal) |
|---|---|
| List all bouncers | sudo cscli bouncers list |
| Remove a bouncer (revokes its key) | sudo cscli bouncers delete <name> |
| Re-issue a key | sudo cscli bouncers delete <name> then sudo cscli bouncers add <name> |
| Pause traffic from a bouncer | Stop the bouncer service on the remote system |
Removing a bouncer with
cscli bouncers deleteimmediately invalidates its API key. The remote system will start failing with 401 errors until you re-add it and update the config.
| Symptom | Likely cause | Fix |
|---|---|---|
tls: failed to verify certificate |
Defend-O-Tron Root CA isn't installed on the remote system | Re-do Step 3 |
401 Unauthorized |
API key is wrong, expired, or revoked | Generate a new key with cscli bouncers add, update the remote config |
no such host: crowdsec.protected.lan |
Remote system can't resolve the LAPI hostname | Re-do Step 2 (DNS or hosts file) |
connection refused |
An upstream firewall between the remote system and the Defend-O-Tron is blocking TCP 443 | Open the path; the LAPI is on standard HTTPS |
last_pull stays empty in cscli bouncers list |
Remote bouncer service isn't started, or is crashing | Check the remote bouncer's service status and logs |
crowdsec.protected.lan resolves automatically.