Hey everyone,
I’m new to crowdsec but been trying to implement it with traefik in docker in my lab environment, so far without success.
My issue is that I don’t really understand how to connect traefik to crowsec with the bounce plugin, I’ve looked though the official documentation and a lot of different github repos from different people, but whatever I try I can’t get it to work.
I’ve setup a simple test were I try and access my debug container from a browser, but when I access it I just get trough, even though I’ve set a manual ban rule for my PCs IP with:
docker exec crowdsec cscli decisions add --ip 192.168.1.10
Any help getting this to work would be greatly appreciated!
Compose file for Traefik:
networks:
docker-proxy:
name: docker-proxy
external: true
crowdsec-network:
name: crowdsec-network
volumes:
traefik-logs:
name: traefik-logs
traefik-certs:
name: traefik-certs
traefik-config:
name: traefik-config
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- docker-proxy
- crowdsec-network
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --api.dashboard=true
- --providers.docker.network=docker-proxy # define default network to monitor for docker provider
# Set up LetsEncrypt
- --certificatesresolvers.letsencrypt.acme.dnschallenge=true
- --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}
- --certificatesresolvers.letsencrypt.acme.caserver=https://acme-v02.api.letsencrypt.org/directory # prod (default)
- --entrypoints.websecure.address=:443
# Set up the TLS configuration for our websecure listener
- --entrypoints.websecure.http.tls.certResolver=letsencrypt
- --entrypoints.websecure.http.tls=true
- --entrypoints.websecure.forwardedHeaders.trustedIPs=${TRUSTED_PROXIES}
# Log configuration
- --log.level=DEBUG
- --log.format=json
- --log.filePath=/var/log/traefik/traefik.log
- --accesslog.format=json
- --accesslog.filePath=/var/log/traefik/access.log
# Crowdsec Plugin
- --experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
- --experimental.plugins.bouncer.version=v1.4.4
labels:
- traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true
- traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecAppsecEnabled=true
- traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecAppsecHost=crowdsec:7422
- traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecLapiKey=${CrowdSecAPIKey}
- traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecAppsecUnreachableBlock=true
ports:
- 443:443
environment:
- CF_DNS_API_TOKEN=${CF_API_TOKEN}
- TZ=Europe/Stockholm # Change this to your timezone
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime:ro
- traefik-config:/traefik
- traefik-certs:/letsencrypt
- traefik-logs:/var/log/traefik
Compose file for Crowdsec:
networks:
docker-proxy:
name: docker-proxy
external: true
crowdsec-network:
name: crowdsec-network
external: true
volumes:
crowdsec-db:
name: crowdsec-db
crowdsec-config:
name: crowdsec-config
traefik-logs: # this will be the name of the volume from trarfic logs
external: true # remove if traefik is running on same stack
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
restart: unless-stopped
environment:
- TZ=Europe/Stockholm # Change this to your timezone
- CUSTOM_HOSTNAME=crowdsec
- COLLECTIONS=crowdsecurity/linux crowdsecurity/traefik crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules crowdsecurity/http-cve
- BOUNCER_KEY_PLUGIN=${BOUNCER_KEY_PLUGIN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- crowdsec-db:/var/lib/crowdsec/data/
- crowdsec-config:/etc/crowdsec/
- traefik-logs:/var/log/traefik:ro
networks:
- crowdsec-network
Compose file for debug container:
services:
whoami:
image: brndnmtthws/nginx-echo-headers
container_name: debug
networks:
- docker-proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.external.rule=Host(`debug.domain.com`)"
- "traefik.http.routers.external.entrypoints=websecure"
- "traefik.http.routers.debug.tls.certresolver=letsencrypt"
- "traefik.http.services.external.loadbalancer.server.port=8080"
networks:
docker-proxy:
name: docker-proxy
external: true
acquis.yaml
filenames:
- /var/log/traefik/*
labels:
type: traefik
---
appsec_config: crowdsecurity/appsec-default
labels:
type: appsec
listen_addr: 0.0.0.0:7422
source: appsec
Logs from the crowdsec container:
time="2025-07-31T23:16:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:16:58 CEST] \"GET /v1/heartbeat HTTP/1.1 200 43.73953ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:16:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:16:58 CEST] \"GET /v1/allowlists?with_content=true HTTP/1.1 200 53.846708ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:17:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:17:58 CEST] \"GET /v1/heartbeat HTTP/1.1 200 44.340742ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:17:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:17:58 CEST] \"GET /v1/allowlists?with_content=true HTTP/1.1 200 53.676975ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:18:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:18:58 CEST] \"GET /v1/heartbeat HTTP/1.1 200 42.056434ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:18:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:18:58 CEST] \"GET /v1/allowlists?with_content=true HTTP/1.1 200 53.776109ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:19:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:19:58 CEST] \"GET /v1/heartbeat HTTP/1.1 200 35.838689ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:19:58+02:00" level=info msg="127.0.0.1 - [Thu, 31 Jul 2025 23:19:58 CEST] \"GET /v1/allowlists?with_content=true HTTP/1.1 200 33.630978ms \"crowdsec/v1.6.11-d64ee2ae-docker\" \""
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : interface conversion: interface {} is nil, not string (1:1)\n | Split(evt.Unmarshaled.traefik.ClientAddr, ':')[0]\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : reflect: call of reflect.Value.Type on zero Value (1:1)\n | int(evt.Unmarshaled.traefik.Duration)\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : interface conversion: interface {} is nil, not string (1:1)\n | Split(evt.Unmarshaled.traefik.RequestProtocol, '/')[1]\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : reflect: call of reflect.Value.Type on zero Value (1:1)\n | int(evt.Unmarshaled.traefik.DownstreamStatus)\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : interface conversion: interface {} is nil, not string (1:1)\n | Split(evt.Unmarshaled.traefik.ClientAddr, ':')[0]\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : reflect: call of reflect.Value.Type on zero Value (1:1)\n | int(evt.Unmarshaled.traefik.Duration)\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : interface conversion: interface {} is nil, not string (1:1)\n | Split(evt.Unmarshaled.traefik.RequestProtocol, '/')[1]\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse
time="2025-07-31T23:20:16+02:00" level=warning msg="failed to run RunTimeValue : reflect: call of reflect.Value.Type on zero Value (1:1)\n | int(evt.Unmarshaled.traefik.DownstreamStatus)\n | ^" id=damp-shape name=child-crowdsecurity/traefik-logs stage=s01-parse