← All articles
an empty train station with two doors open

CrowdSec Security Engine: AppSec, Multi-Machine Deployment, and Advanced Configuration

Security 2026-02-14 · 5 min read crowdsec security waf appsec intrusion-prevention multi-machine
By Selfhosted Guides Editorial TeamSelf-hosting practitioners covering open source software, home lab infrastructure, and data sovereignty.

If you have already deployed CrowdSec for basic log-based intrusion prevention, you are using maybe thirty percent of what it can do. CrowdSec's Security Engine includes an application security component that acts as a web application firewall, supports centralized multi-machine deployments through its Local API architecture, and provides a scenario development framework for writing custom detection logic. This guide covers the advanced features that turn CrowdSec from a Fail2ban replacement into a real security platform.

Photo by selcuk sarikoz on Unsplash

CrowdSec security engine logo

The AppSec Component: CrowdSec as a WAF

CrowdSec's AppSec (Application Security) component is a web application firewall that inspects HTTP requests before they reach your application. Unlike the log-based detection engine that reacts after an attack is logged, AppSec operates inline -- it evaluates every incoming request and can block malicious traffic in real-time.

How AppSec Differs From Log-Based Detection

Traditional CrowdSec workflow: Attack happens, gets logged, CrowdSec reads the log, creates a ban decision, bouncer enforces it on the next request. The first attack always succeeds.

AppSec workflow: Request arrives at the reverse proxy, the bouncer sends it to CrowdSec's AppSec engine for inspection, malicious requests are blocked immediately. The first attack is caught.

Enabling AppSec

AppSec works through a supported bouncer (the Traefik, Nginx, or HAProxy bouncer). The bouncer sends request details to CrowdSec for inspection rather than just checking IP-based decisions.

Install the AppSec rules:

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

Configure the AppSec component in your CrowdSec acquisition config:

# /etc/crowdsec/acquis.d/appsec.yaml
listen_addr: 0.0.0.0:7422
appsec_config: crowdsecurity/appsec-default
name: myAppSec
source: appsec
labels:
  type: appsec

Then configure your bouncer to forward requests to the AppSec endpoint. For the Nginx bouncer:

# In nginx config
crowdsec_appsec_url http://localhost:7422;
crowdsec_appsec_action ban;  # or captcha, or log

What AppSec Catches

The default rule sets cover:

You can write custom AppSec rules to match your application's specific attack surface.

Multi-Machine LAPI Deployment

For anything beyond a single server, CrowdSec supports a centralized deployment model using its Local API (LAPI) architecture.

The Architecture

Instead of running a full CrowdSec instance on every machine, you designate one machine as the LAPI server and run lightweight agents on everything else:

This means a ban decision on any machine is immediately enforced across all machines.

Docker Compose: Centralized LAPI

# On the LAPI server
services:
  crowdsec-lapi:
    image: crowdsecurity/crowdsec:latest
    environment:
      COLLECTIONS: >-
        crowdsecurity/linux
        crowdsecurity/nginx
        crowdsecurity/traefik
        crowdsecurity/http-cve
        crowdsecurity/appsec-virtual-patching
      DISABLE_AGENT: "false"
    volumes:
      - crowdsec_config:/etc/crowdsec
      - crowdsec_data:/var/lib/crowdsec/data
      - /var/log:/var/log:ro
    ports:
      - "8080:8080"   # LAPI port
      - "7422:7422"   # AppSec port
      - "6060:6060"   # Prometheus metrics
    restart: unless-stopped

volumes:
  crowdsec_config:
  crowdsec_data:

Registering Remote Agents

On the LAPI server, generate a registration token:

docker exec crowdsec-lapi cscli machines add worker-01 --auto
# Note the password output

On the remote machine, configure the agent to point to the central LAPI:

# /etc/crowdsec/config.yaml.local on the remote agent
api:
  client:
    credentials_path: /etc/crowdsec/local_api_credentials.yaml

# /etc/crowdsec/local_api_credentials.yaml
url: http://lapi-server:8080
login: worker-01
password: "the-generated-password"

Registering Remote Bouncers

Similarly, bouncers on any machine can connect to the central LAPI:

# On the LAPI server
docker exec crowdsec-lapi cscli bouncers add nginx-bouncer-web01
# Use the generated API key in the bouncer's configuration

Writing Custom Parsers

When your logs do not match any existing parser from the Hub, you need to write your own. Parsers use Grok patterns (similar to Logstash) to extract structured data from log lines.

Parser Structure

# /etc/crowdsec/parsers/s01-parse/my-app.yaml
name: my-company/my-app-logs
description: "Parse my custom application logs"
filter: "evt.Parsed.program == 'my-app'"
onsuccess: next_stage
nodes:
  - grok:
      pattern: '%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} \[%{DATA:module}\] %{IP:source_ip} - %{GREEDYDATA:message}'
      apply_on: message
    statics:
      - meta: log_type
        value: my-app
      - meta: source_ip
        expression: evt.Parsed.source_ip

Test your parser without deploying it:

echo '2026-02-14T10:30:00Z ERROR [auth] 192.168.1.100 - Failed login for user admin' | \
  sudo cscli explain --type my-app --log -

The cscli explain command shows you exactly how CrowdSec processes a log line through each parser stage, which is invaluable for debugging.

Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.

Writing Custom Scenarios

Once your parser extracts structured data, scenarios define what constitutes an attack.

# /etc/crowdsec/scenarios/my-app-bruteforce.yaml
type: leaky
name: my-company/my-app-bruteforce
description: "Detect brute force login attempts on my app"
filter: "evt.Meta.log_type == 'my-app' && evt.Meta.level == 'ERROR' && evt.Parsed.message contains 'Failed login'"
groupby: evt.Meta.source_ip
capacity: 10
leakspeed: 1m
blackhole: 10m
reprocess: true
labels:
  service: my-app
  type: bruteforce
  remediation: true

This scenario uses the "leaky bucket" model: it tolerates up to 10 failed logins per minute from a single IP. The bucket leaks at one event per minute, so sustained low-rate attacks are also caught. The blackhole period prevents re-triggering for 10 minutes after a ban.

Scenario Types

Allowlisting and Tuning

False positives are the enemy of any IPS. CrowdSec provides several allowlisting mechanisms.

IP Allowlists

# /etc/crowdsec/parsers/s02-enrich/my-whitelist.yaml
name: my-company/my-whitelist
description: "Whitelist internal and VPN IPs"
whitelist:
  reason: "Internal network and VPN"
  ip:
    - "10.0.0.0/8"
    - "172.16.0.0/12"
    - "192.168.0.0/16"
    - "203.0.113.50"  # Office static IP
  cidr:
    - "100.64.0.0/10"  # Tailscale

Expression-Based Allowlists

For more granular control, use expression-based whitelists that evaluate parsed event data:

whitelist:
  reason: "Monitoring system health checks"
  expression:
    - "evt.Meta.http_user_agent contains 'UptimeKuma'"
    - "evt.Meta.http_path == '/health' && evt.Meta.source_ip in ['10.0.0.5']"

Prometheus Metrics

CrowdSec exposes Prometheus metrics on port 6060 by default, giving you visibility into:

Add CrowdSec to your Prometheus scrape config:

- job_name: 'crowdsec'
  static_configs:
    - targets: ['crowdsec:6060']

Build a Grafana dashboard to track attack trends, bouncer activity, and parser health across your entire infrastructure.

Production Hardening

Secure the LAPI

In multi-machine deployments, the LAPI port should only be accessible to trusted agents and bouncers. Use firewall rules or a VPN (WireGuard/Tailscale) to restrict access. Never expose port 8080 to the public internet.

Enable TLS for Agent-LAPI Communication

For deployments across untrusted networks, configure TLS on the LAPI:

# config.yaml.local
api:
  server:
    tls:
      cert_file: /etc/crowdsec/ssl/cert.pem
      key_file: /etc/crowdsec/ssl/key.pem

Monitor Decision Counts

An unusually high number of decisions can indicate either a real attack surge or a parser misconfiguration causing false positives. Set up alerts for decision count spikes.

Regular Hub Updates

sudo cscli hub update && sudo cscli hub upgrade

New vulnerability signatures and parser improvements ship through the Hub regularly. Automate updates with a weekly cron job, but review changelogs for breaking changes.

The Bottom Line

CrowdSec's Security Engine is more than a log-based IPS. The AppSec component provides real-time request inspection, the LAPI architecture scales to any number of machines with centralized decision-making, and the parser/scenario framework lets you build detection for any application. If you are running CrowdSec only for SSH brute force protection, you are leaving most of its capability on the table. Deploy AppSec behind your reverse proxy, centralize your LAPI, and write custom scenarios for your applications. The security posture improvement is significant and the operational overhead is minimal.

Get free weekly tips in your inbox. Subscribe to Self-Hosted Weekly