services: abuseipdb-bouncer: build: . # To pull a pre-built image instead of building locally: # image: developingchet/cs-abuseipdb-bouncer:latest container_name: abuseipdb-bouncer restart: unless-stopped environment: # --- Required --- # URL of the CrowdSec Local API. Use the Docker service name if CrowdSec # runs on the same Docker network, or a hostname/IP for a remote LAPI. - CROWDSEC_LAPI_URL=${CROWDSEC_LAPI_URL:-http://crowdsec:8080} # Bouncer API key from: docker exec crowdsec cscli bouncers add abuseipdb-bouncer - CROWDSEC_LAPI_KEY=${CROWDSEC_LAPI_KEY} # AbuseIPDB v2 API key from: https://www.abuseipdb.com/account/api - ABUSEIPDB_API_KEY=${ABUSEIPDB_API_KEY} # Read either key from a file instead (Docker / Kubernetes secrets). # The path is inside the container; mount the file read-only. - CROWDSEC_LAPI_KEY_FILE=${CROWDSEC_LAPI_KEY_FILE:-} - ABUSEIPDB_API_KEY_FILE=${ABUSEIPDB_API_KEY_FILE:-} # mTLS alternative to CROWDSEC_LAPI_KEY: set the certificate and key # paths (inside the container) and leave CROWDSEC_LAPI_KEY empty. - CROWDSEC_LAPI_TLS_CERT_PATH=${CROWDSEC_LAPI_TLS_CERT_PATH:-} - CROWDSEC_LAPI_TLS_KEY_PATH=${CROWDSEC_LAPI_TLS_KEY_PATH:-} - CROWDSEC_LAPI_TLS_CA_CERT_PATH=${CROWDSEC_LAPI_TLS_CA_CERT_PATH:-} # --- Optional --- # Comma-separated IPs/CIDRs that are never reported. - IP_WHITELIST=${IP_WHITELIST:-} # Daily report quota (free=1000, webmaster=3000, premium=50000). - ABUSEIPDB_DAILY_LIMIT=${ABUSEIPDB_DAILY_LIMIT:-1000} # Pre-check each IP with /check before reporting to skip whitelisted IPs. # Uses one /check API call per decision. Leave false on the free tier. - ABUSEIPDB_PRECHECK=${ABUSEIPDB_PRECHECK:-false} # Skip decisions shorter than this many seconds (0 = disabled). # Set to 300 to ignore test/simulation decisions (5-minute bans). - ABUSEIPDB_MIN_DURATION=${ABUSEIPDB_MIN_DURATION:-0} # Per-IP cooldown matching AbuseIPDB's 15-minute deduplication window. - COOLDOWN_DURATION=${COOLDOWN_DURATION:-15m} # LAPI polling frequency. Lower values increase load on the LAPI. - POLL_INTERVAL=${POLL_INTERVAL:-30s} # HTTP timeout for LAPI requests. - LAPI_TIMEOUT=${LAPI_TIMEOUT:-10s} # Worker pool size and queue length. - WORKER_COUNT=${WORKER_COUNT:-4} - WORKER_BUFFER=${WORKER_BUFFER:-256} # How often expired cooldowns are pruned and the retry queue is checked. - JANITOR_INTERVAL=${JANITOR_INTERVAL:-5m} - RETRY_CHECK_INTERVAL=${RETRY_CHECK_INTERVAL:-30s} # Usage-metrics telemetry pushed to the LAPI. - USAGE_METRICS_ENABLED=${USAGE_METRICS_ENABLED:-true} - USAGE_METRICS_INTERVAL=${USAGE_METRICS_INTERVAL:-30m} # Log level: trace, debug, info, warn, error - LOG_LEVEL=${LOG_LEVEL:-info} # Log format: json (structured, for SIEM) or text (human-readable) - LOG_FORMAT=${LOG_FORMAT:-json} # Set to true only if your CrowdSec LAPI uses a self-signed certificate. - TLS_SKIP_VERIFY=${TLS_SKIP_VERIFY:-false} # Persistent state directory (bbolt database). - DATA_DIR=/data # Metrics / health probes server. The image's HEALTHCHECK needs it enabled. - METRICS_ENABLED=${METRICS_ENABLED:-true} # Metrics / health probes address (set to empty string to disable). # Listens on all container interfaces so the published port below can # reach it; the port is published on the host's loopback only. - METRICS_ADDR=${METRICS_ADDR:-:9090} # Optional path to a YAML config file (alternative to environment vars). # - CONFIG_FILE=/etc/cs-abuseipdb/config.yaml volumes: # Named volume for bbolt state.db (quota + cooldown persistence). # State persists across container restarts. - bouncer-state:/data ports: # Metrics, /healthz and /readyz — bind to loopback only. - "127.0.0.1:9090:9090" tmpfs: # Scratch space required by the Go runtime (distroless has no writable /tmp). - /tmp:size=10M,uid=65532,gid=65532,mode=1777 read_only: true security_opt: - no-new-privileges:true - "seccomp:./security/seccomp-bouncer.json" cap_drop: - ALL networks: # Replace with your CrowdSec Docker network name. # To find it: docker inspect crowdsec | jq -r '.[0].NetworkSettings.Networks | keys[0]' - crowdsec-net volumes: # Docker seeds this volume from the image's /data directory on first creation. # Ownership (UID 65532) is baked into the image — no manual chown required. bouncer-state: driver: local networks: crowdsec-net: # Set to false and add driver: bridge to create a new network instead. external: true