Self-Hosting a Global Edge WAF: Distributing Traefik Across Edge VPS Nodes with Centralized CrowdSec Banishment for DDoS Mitigation

Public-facing services in 2026 operate in a hostile environment. Automated scanners, credential stuffing bots, layer 7 DDoS floods, and exploit kits continuously target exposed endpoints. At the same time, latency expectations are stricter than ever, and multi-region deployments are the norm rather than the exception.
Many organizations rely on managed edge providers for Web Application Firewall (WAF) and DDoS mitigation. However, there are valid scenarios where self-hosting a global edge layer makes sense:
- Cost predictability at scale
- Full control over routing and inspection logic
- Compliance or data sovereignty constraints
- Homelab and hybrid-cloud deployments
- Specialized routing needs not supported by commercial CDNs
This article outlines a production-grade architecture for self-hosting a global edge WAF using:
- Traefik as the edge reverse proxy and TLS terminator
- CrowdSec for behavioral detection and IP reputation intelligence
- Multiple globally distributed VPS nodes
- Centralized ban propagation for coordinated DDoS mitigation
The result is a distributed edge layer capable of absorbing volumetric noise, blocking malicious actors in near real time, and routing legitimate traffic to origin services.
Architecture Overview
High-Level Design
The architecture consists of the following components:
- Edge VPS Nodes (Global)
- Traefik (reverse proxy + TLS)
- CrowdSec agent
- CrowdSec bouncer (Traefik middleware)
- Node-level firewall (iptables/nftables)
- Central CrowdSec Control Plane
- CrowdSec LAPI (Local API server)
- PostgreSQL backend
- Shared ban database
- Origin Infrastructure
- Application servers
- Private network only (not publicly exposed)
- Global DNS
- Geo-aware or latency-based routing
- Health-checked failover
Traffic Flow
- Client resolves DNS → nearest edge VPS.
- Traffic hits Traefik.
- Traefik middleware queries CrowdSec bouncer.
- If IP is banned → 403 or drop.
- If allowed → forwarded to origin over private network or secure tunnel.
- Logs are parsed by CrowdSec agent.
- Detected malicious behavior → ban decision pushed to central LAPI.
- All edge nodes pull updated ban list.
Component Integration
- Traefik acts as both reverse proxy and WAF entrypoint.
- CrowdSec analyzes access logs and applies detection scenarios.
- CrowdSec LAPI acts as a centralized decision authority.
- Traefik bouncers enforce decisions at request time.
This separation ensures detection is distributed but enforcement is globally synchronized.
Implementation Breakdown
Step 1: Provision Global Edge VPS Nodes
Minimum recommended per node:
- 2 vCPU
- 2–4 GB RAM
- 10 Gbps virtual NIC preferred
- Ubuntu 24.04 LTS or Debian 12
Open only:
- TCP 80
- TCP 443
- SSH (restricted via firewall)
Disable password SSH and enforce key-only access.
Step 2: Deploy Central CrowdSec LAPI
Use a dedicated small VPS or internal server.
Docker Compose for Central LAPI
version: "3.9"
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec-lapi
restart: unless-stopped
environment:
- COLLECTIONS=crowdsecurity/nginx
volumes:
- ./config:/etc/crowdsec
- ./data:/var/lib/crowdsec/data
ports:
- "8080:8080"
depends_on:
- db
db:
image: postgres:15
container_name: crowdsec-db
restart: unless-stopped
environment:
POSTGRES_USER: crowdsec
POSTGRES_PASSWORD: strongpassword
POSTGRES_DB: crowdsec
volumes:
- ./pgdata:/var/lib/postgresql/data
Modify /etc/crowdsec/config.yaml:
db_config:
type: postgresql
user: crowdsec
password: strongpassword
db_name: crowdsec
host: db
port: 5432
Why PostgreSQL?
- Better concurrency
- Durable decision store
- Required for multi-node synchronization
Generate enrollment key:
cscli bouncers add edge-traefik
cscli machines add edge-node-1
Step 3: Deploy Traefik on Edge Nodes
Docker Compose for Edge Node
version: "3.9"
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
command:
- --providers.docker=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --api.dashboard=false
- --log.level=INFO
- --accesslog=true
- --accesslog.filepath=/logs/access.log
- --certificatesresolvers.le.acme.httpchallenge=true
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.le.acme.email=admin@example.com
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./logs:/logs
- ./letsencrypt:/letsencrypt
networks:
- edge
crowdsec:
image: crowdsecurity/crowdsec:latest
restart: unless-stopped
volumes:
- ./logs:/var/log/traefik:ro
environment:
- COLLECTIONS=crowdsecurity/traefik
- ENROLL_KEY=<machine_enroll_key>
- LAPI_URL=https://central-lapi.example.com:8080
networks:
- edge
networks:
edge:
Why enable access logs?
CrowdSec parses logs to detect:
- Layer 7 floods
- Excessive 404 scanning
- Credential stuffing patterns
Step 4: Configure Traefik CrowdSec Bouncer
Use the Traefik plugin bouncer.
Add to static config:
experimental:
plugins:
crowdsec-bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.4.0
Middleware configuration:
http:
middlewares:
crowdsec:
plugin:
crowdsec-bouncer:
crowdsecLapiKey: "<bouncer_key>"
crowdsecLapiHost: "https://central-lapi.example.com:8080"
crowdsecMode: "live"
Attach middleware:
http:
routers:
app:
rule: "Host(`app.example.com`)"
entryPoints:
- websecure
service: app-service
middlewares:
- crowdsec
Why live mode?
- Checks decisions at request time
- Immediate enforcement
- Suitable for fast-moving attacks
Step 5: Protect Origins
Origins must not be publicly accessible.
Options:
- WireGuard tunnels from edge → origin
- Tailscale mesh
- Private VPC peering
Example WireGuard topology:
[Edge Node] --- WG Tunnel --- [Origin]
Firewall origin to allow traffic only from WireGuard subnet.
Observability and Debugging
Metrics
Enable Traefik Prometheus metrics:
--metrics.prometheus=true
--metrics.prometheus.addrouterslabels=true
Monitor:
- Request rate
- 4xx/5xx spikes
- Middleware latency
- TLS handshake errors
CrowdSec metrics:
cscli metrics
Watch for:
- Decisions count
- Alerts per scenario
- API sync failures
Logs
Key log sources:
/logs/access.log(Traefik)- CrowdSec agent logs
- LAPI logs
Common issues:
- Bouncer key mismatch
- Clock drift between nodes
- LAPI unreachable (firewall issue)
- Incorrect real IP header handling
If behind another proxy, set:
--entrypoints.websecure.forwardedHeaders.trustedIPs=0.0.0.0/0
Or restrict to known ranges.
Failure Modes
- Central LAPI down → no new decisions propagate.
- Traefik middleware misconfigured → no enforcement.
- Log parsing disabled → no detection.
Mitigation:
- Run LAPI in HA mode.
- Use health checks.
- Add alerting for decision count drops.
Security Considerations
Attack Surface
Edge nodes expose:
- 80/443
- ACME challenge endpoint
Harden:
- Disable Traefik dashboard.
- Restrict Docker socket access.
- Use rootless containers where possible.
Secrets Management
Avoid plaintext keys in Compose files.
Use:
- Docker secrets
- SOPS + GitOps
- Environment variables injected at runtime
Rotate:
- Bouncer keys
- Enrollment keys
- ACME email credentials
Network Isolation
- Origin accessible only via tunnel.
- LAPI accessible only from edge IP ranges.
- SSH restricted via firewall + fail2ban.
Implement nftables:
nft add rule inet filter input tcp dport {22} ip saddr {trusted_ip} accept
nft add rule inet filter input drop
Performance Considerations
Bottlenecks
- TLS handshakes
- Middleware latency
- Central LAPI API calls
- Disk I/O from logging
Mitigation:
- Enable HTTP/3 in Traefik.
- Use SSD storage.
- Set log rotation.
- Increase file descriptor limits.
Scaling Strategy
Horizontal scaling:
- Add more edge VPS nodes.
- Use GeoDNS or anycast.
Vertical scaling:
- Increase CPU for TLS-heavy workloads.
- Enable OpenSSL acceleration.
CrowdSec scaling:
- Dedicated PostgreSQL cluster.
- LAPI load-balanced behind HAProxy.
Resource Optimization
Disable unnecessary features:
- Traefik dashboard
- Excess debug logging
Tune:
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_tw_reuse=1
Enable connection reuse upstream.
Tradeoffs and Design Decisions
Why Traefik?
- Native Docker integration
- Dynamic configuration
- Middleware ecosystem
- ACME automation
Alternatives:
- Nginx (more manual config)
- Caddy (simpler but fewer advanced routing controls)
- HAProxy (excellent performance but steeper config curve)
Why CrowdSec?
- Behavioral detection vs static rule WAF
- Shared threat intelligence
- API-based ban propagation
- Lightweight footprint
Alternative:
- ModSecurity (heavyweight, rule-based)
- Fail2ban (local-only, not distributed)
What to Avoid
- Exposing origin directly “temporarily”
- Running LAPI on edge nodes
- Sharing Docker socket broadly
- Ignoring time synchronization (use chrony)
Conclusion
A self-hosted global edge WAF architecture built with Traefik and CrowdSec provides:
- Distributed DDoS resistance
- Centralized ban intelligence
- Full routing control
- Cost-efficient global presence
- Cloud-provider independence
By combining globally distributed edge nodes with centralized behavioral intelligence, infrastructure teams can build a production-grade defensive perimeter without relying on proprietary CDN platforms.
This architecture scales horizontally, enforces security decisions consistently across regions, and integrates cleanly into modern containerized workflows. With careful hardening, observability, and performance tuning, it delivers a resilient and transparent edge layer suitable for serious production workloads in 2026.

