CrowdSec mit Docker installieren: Community-IDS/IPS für deinen Linux-Server
CrowdSec als Docker-Container einrichten: Security Engine analysiert Logs, Firewall-Bouncer blockiert bösartige IPs per iptables – mit Community-Bedrohungsintelligenz und kollektiver Blockliste.

Wer einen Linux-Server oder eine Docker-Umgebung betreibt, kennt das Muster: SSH-Bruteforce-Versuche, automatisierte Web-Scans, CVE-Ausnutzungen – die Angriffe kommen pausenlos. CrowdSec ist ein quelloffenes, community-basiertes IDS/IPS-System (Intrusion Detection und Prevention), das diese Angriffe nicht nur erkennt, sondern aktiv blockiert. Die Besonderheit: Jede Installation teilt erkannte Angreifer-IPs mit der globalen Community und profitiert umgekehrt von einer gemeinsamen Blockliste mit Millionen bekannter Angreifer-Adressen. Mit 13.800+ GitHub-Stars und Version 1.7.8 (Mai 2026) ist CrowdSec kein Zombie-Projekt, sondern aktiv gepflegt. Diese Anleitung richtet die Security Engine als Docker-Container ein und installiert den Firewall-Bouncer nativ auf dem Host – der einzige sichere Weg, da er direkt auf iptables/nftables des Linux-Kernels zugreifen muss.
Voraussetzungen
- Linux-Host mit Root-/sudo-Zugriff – Ubuntu 22.04/24.04 oder Debian 12 empfohlen. Windows und macOS werden für den Firewall-Bouncer nicht unterstützt (kein Linux-Kernel für iptables/nftables).
- Docker Engine v20.10+ mit Docker Compose Plugin v2.x installiert – falls noch nicht vorhanden, hilft die Grundlage-Anleitung zu Docker und Docker Compose auf Linux.
- Mindestens 512 MB RAM für den CrowdSec-Container (Slim-Variante), 1 GB empfohlen für die Vollinstallation mit GeoIP-Datenbank.
- Mindestens 500 MB persistenter Speicher für die Docker-Volumes (
crowdsec-config,crowdsec-data). - Log-Dateien der zu schützenden Dienste müssen dem Container zugänglich sein – SSH-Logs unter
/var/log/auth.logbzw./var/log/secure, Nginx-Logs in/var/log/nginx/. - curl und apt (oder yum/dnf) für die Installation des Firewall-Bouncers auf dem Host.
- Optional: Kostenloser Account auf app.crowdsec.net für die CrowdSec Console (zentrales Monitoring, Community-Blockliste).
CrowdSec-Architektur verstehen
Bevor du startest, lohnt ein kurzer Blick auf die Architektur – sie erklärt, warum zwei separate Installationsschritte nötig sind:
| Komponente | Aufgabe | Laufzeitumgebung |
|---|---|---|
| Security Engine | Liest Logs, erkennt Muster per Parsern/Szenarien, verwaltet Decisions über die Local API (LAPI) | Docker-Container |
| Firewall-Bouncer | Liest Decisions von der LAPI, setzt Blockierungen per iptables/nftables um | Systempaket auf dem Host |
Wichtig: Ohne Bouncer werden Angriffe nur erkannt, aber nicht blockiert. CrowdSec wäre dann ein reines IDS. Erst der Bouncer macht es zum aktiven IPS. Den Bouncer als privilegierten Docker-Container zu betreiben ist technisch möglich, aber ein erhebliches Sicherheitsrisiko und wird von der offiziellen Dokumentation ausdrücklich nicht empfohlen.
| Eigenschaft | Wert |
|---|---|
| Image (offiziell) | crowdsecurity/crowdsec:latest (Docker Hub) |
| Empfohlener Tag | v1.7.8 für Produktion, latest für Lab |
| Slim-Variante | crowdsecurity/crowdsec:slim – ca. 60% kleiner, ohne GeoIP |
| Unterstützte Architekturen | linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6, linux/386 |
| LAPI-Port | 8080 (nur an 127.0.0.1 binden!) |
| Metriken-Port | 6060 (optional, für Prometheus/Grafana) |
| Lizenz | MIT (Detection Rules), Apache 2.0 (Engine) |
Schritt 1: Projektordner und acquis.yaml anlegen
Die acquis.yaml teilt CrowdSec mit, welche Log-Dateien oder Container es überwachen soll. Sie muss vor dem ersten Container-Start existieren, sonst verarbeitet CrowdSec keine Logs und cscli metrics zeigt überall „0".
sudo mkdir -p /opt/crowdsec/crowdsec
cd /opt/crowdsecErstelle jetzt die Log-Quellen-Konfiguration. Das folgende Beispiel überwacht SSH-Logs und Nginx-Logs auf einem typischen Ubuntu/Debian-Host:
# /opt/crowdsec/crowdsec/acquis.yaml
---
# SSH / Authentifizierungs-Logs (Ubuntu/Debian)
filenames:
- /var/log/auth.log
labels:
type: syslog
---
# Nginx Access- und Error-Logs
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginxPasse die Pfade an deine Umgebung an: Auf CentOS/RHEL heißt die Auth-Log-Datei /var/log/secure. Betreibst du Nginx oder Traefik als Docker-Container, kannst du deren Logs stattdessen über ein gemeinsames Docker-Volume einbinden.
Verifizieren: Prüfe, ob die Datei korrekt angelegt wurde und die Log-Pfade auf dem Host existieren:
ls -la /opt/crowdsec/crowdsec/acquis.yaml
# Erwartete Ausgabe: -rw-r--r-- 1 root root ... acquis.yaml
ls /var/log/auth.log /var/log/nginx/access.log
# Beide Dateien müssen vorhanden sein – sonst Pfad in acquis.yaml anpassenSchritt 2: .env-Datei mit Konfiguration erstellen
Alle Secrets und anpassbaren Werte gehören in eine .env-Datei, niemals direkt in die compose.yaml. Generiere einen sicheren alphanumerischen Bouncer-Key – Sonderzeichen wie ! oder # können im YAML-Escaping Probleme verursachen.
# Sicheren 32-Zeichen-Key generieren (nur Hex, keine Sonderzeichen):
openssl rand -hex 16
# /opt/crowdsec/.env
# Zeitzone des Hosts (wichtig für korrekte Log-Zeitstempel-Interpretation)
TZ=Europe/Berlin
# Gruppe für Log-Dateizugriff – mit "id -g" oder "stat /var/log/auth.log" prüfen
GID=1000
# Collections: Space-separiert, mindestens linux + sshd
CROWDSEC_COLLECTIONS=crowdsecurity/linux crowdsecurity/sshd crowdsecurity/nginx
# Bouncer-Key (alphanumerisch, mind. 16 Zeichen) – Ausgabe von openssl rand -hex 16 eintragen
BOUNCER_KEY_FIREWALL=ersetze_mit_deinem_generierten_key
# Optional: CrowdSec-Console-Enrollment-Key (aus app.crowdsec.net)
# ENROLL_KEY=dein-console-key-hierDie GID muss zur Gruppe der Log-Dateien passen. Auf Systemen mit einer docker-Gruppe gehören Logs oft dieser Gruppe. Prüfe das mit stat /var/log/auth.log – der Ausgabe-Wert hinter „Gid:" ist die gesuchte Nummer.
Verifizieren: Datei vorhanden, kein Leerzeichen um das =-Zeichen, kein Sonderzeichen im Bouncer-Key:
cat /opt/crowdsec/.env
# Prüfen: BOUNCER_KEY_FIREWALL=... ist gesetzt und alphanumerischSchritt 3: compose.yaml erstellen
Die compose.yaml bindet die Log-Quellen-Konfiguration als Read-Only-Mount ein und definiert zwei Pflicht-Volumes. Ab CrowdSec v1.7.0 ist das Volume crowdsec-data für /var/lib/crowdsec/data zwingend erforderlich – ohne es gehen alle Decisions, Alerts und Console-Enrollments bei jedem Neustart verloren.
# /opt/crowdsec/compose.yaml
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
restart: unless-stopped
ports:
# LAPI: NUR an 127.0.0.1 binden – niemals 0.0.0.0 exponieren!
- "127.0.0.1:8080:8080"
# Prometheus-Metriken: nur bei Bedarf auskommentieren
# - "127.0.0.1:6060:6060"
environment:
COLLECTIONS: "${CROWDSEC_COLLECTIONS:-crowdsecurity/linux crowdsecurity/sshd}"
GID: "${GID:-1000}"
TZ: "${TZ:-Europe/Berlin}"
# Bouncer automatisch beim Container-Start registrieren:
BOUNCER_KEY_firewall: "${BOUNCER_KEY_FIREWALL}"
# CrowdSec Console (optional):
# ENROLL_KEY: "${ENROLL_KEY}"
volumes:
# Konfigurationsdateien (Parsers, Scenarios, Profiles):
- crowdsec-config:/etc/crowdsec
# Decisions-Datenbank (ab v1.7.0 Pflicht!):
- crowdsec-data:/var/lib/crowdsec/data
# Host-Logs (SSH, System) – Read-Only:
- /var/log:/var/log:ro
# Log-Quellen-Konfiguration:
- ./crowdsec/acquis.yaml:/etc/crowdsec/acquis.yaml:ro
networks:
- crowdsec-net
networks:
crowdsec-net:
name: crowdsec-net
volumes:
crowdsec-config:
crowdsec-data:Ein Hinweis zur Image-Wahl: Für den Produktivbetrieb empfiehlt sich ein gepinntes Tag wie crowdsecurity/crowdsec:v1.7.8 statt :latest, damit Updates kontrolliert eingespielt werden. Die Slim-Variante (:slim) spart Platz, hat aber keine GeoIP-Datenbank – Szenarien, die Geo-Blocking benötigen, schlagen dann lautlos fehl. Für SSH- und Nginx-Schutz reicht :slim problemlos.
Verifizieren: YAML-Syntax prüfen (Docker erkennt Einrückungsfehler beim Start):
cd /opt/crowdsec
docker compose config
# Ausgabe: die zusammengeführte Konfiguration ohne FehlermeldungenSchritt 4: Container starten und Collections prüfen
Beim ersten Start lädt CrowdSec automatisch alle in COLLECTIONS angegebenen Detection-Pakete via cscli hub install herunter. Das dauert je nach Verbindung 30–60 Sekunden.
cd /opt/crowdsec
docker compose up -d
docker compose logs -f crowdsecIm Log solltest du Zeilen wie diese sehen:
time="..." level=info msg="Loaded 1 scenarios"
time="..." level=info msg="Starting processing data"
time="..." level=info msg="Hub installation done"Verifizieren: Container läuft, Collections und Bouncer sind registriert:
docker compose ps
# Erwartete Ausgabe:
# NAME IMAGE STATUS
# crowdsec crowdsecurity/crowdsec:latest Up X minutes
# Installierte Collections prüfen:
docker exec crowdsec cscli collections list
# Erwartete Ausgabe: crowdsecurity/linux, crowdsecurity/sshd, crowdsecurity/nginx – alle "enabled"
# Bouncer bereits registriert (durch BOUNCER_KEY_firewall Env-Var):
docker exec crowdsec cscli bouncers list
# Erwartete Ausgabe: firewall-Bouncer mit Status "valid"
# Metriken: Logs werden gelesen?
docker exec crowdsec cscli metrics
# Zeile "Acquisition" – Lines read sollte > 0 sein nach einigen MinutenZeigt cscli metrics bei der Acquisition überall „0", prüfe die acquis.yaml auf falsche Log-Pfade und stelle sicher, dass die Dateien auf dem Host existieren.
Schritt 5: Firewall-Bouncer auf dem Host installieren
Der Firewall-Bouncer muss als Systempaket direkt auf dem Docker-Host installiert werden – er manipuliert iptables/nftables des Host-Kernels und kann das nicht zuverlässig aus einem Container heraus (ohne gefährlichen privilegierten Modus mit NET_ADMIN-Capability). CrowdSec stellt ein offizielles APT-Repository bereit:
# CrowdSec-Repository einrichten (Debian/Ubuntu):
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
# Firewall-Bouncer installieren – wähle passend zu deinem Kernel:
# Für iptables (Standard auf den meisten Ubuntu/Debian-Systemen):
sudo apt install -y crowdsec-firewall-bouncer-iptables
# Alternativ für nftables:
# sudo apt install -y crowdsec-firewall-bouncer-nftablesDer Bouncer muss jetzt mit dem API-Key konfiguriert werden, den du in der .env-Datei festgelegt hast. Öffne die Bouncer-Konfiguration:
sudo nano /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yamlPasse die folgenden Werte an:
api_url: http://127.0.0.1:8080/
api_key: ersetze_mit_deinem_BOUNCER_KEY_FIREWALL_wert
# Wichtig für Docker-Container-Schutz: DOCKER-USER Chain ergänzen!
iptables_chains:
- INPUT
- FORWARD
- DOCKER-USERDie Chain DOCKER-USER ist entscheidend: Standard-Chains wie INPUT und FORWARD greifen nicht für Docker-Container-Traffic. Ohne DOCKER-USER werden Docker-Container nicht geblockt, obwohl CrowdSec Decisions gesetzt hat.
# Bouncer-Dienst starten und aktivieren:
sudo systemctl enable --now crowdsec-firewall-bouncer
# Status prüfen:
sudo systemctl status crowdsec-firewall-bouncerVerifizieren: Bouncer läuft und kommuniziert mit der LAPI:
sudo systemctl status crowdsec-firewall-bouncer
# Erwartete Ausgabe: active (running) – keine "connection refused"-Fehler
# Bouncer in CrowdSec als aktiv markiert?
docker exec crowdsec cscli bouncers list
# Spalte "Last API pull": sollte aktuellen Zeitstempel zeigen
# Aktive iptables-Rules von CrowdSec:
sudo iptables -L crowdsec-blacklists -n 2>/dev/null || echo "Noch keine Blockierungen aktiv"Schritt 6: Erste Erkennungen und manuelle Tests
Nach der Installation möchtest du natürlich wissen, ob CrowdSec tatsächlich arbeitet. Hier sind die wichtigsten Monitoring-Befehle:
# Erkannte Angriffe (Alerts):
docker exec crowdsec cscli alerts list
# Aktive Blockierungen (Decisions):
docker exec crowdsec cscli decisions list
# Detaillierte Metriken (Logs gelesen, Parsers ausgelöst, Scenarios ausgelöst):
docker exec crowdsec cscli metricsMöchtest du eine IP manuell zur Testblockierung hinzufügen und den Bouncer prüfen:
# Test-IP manuell blockieren (nutze eine IP, die du kontrollierst!):
docker exec crowdsec cscli decisions add --ip 203.0.113.1 --duration 5m --reason "Test"
# Prüfen ob iptables-Rule gesetzt:
sudo iptables -L crowdsec-blacklists -n | grep 203.0.113.1
# Test-Blockierung wieder entfernen:
docker exec crowdsec cscli decisions delete --ip 203.0.113.1Optional: Trägst du die Instanz in die CrowdSec Console ein (Enrollment-Key in der .env setzen und ENROLL_KEY in der compose.yaml einkommentieren), synchronisiert sich die Community-Blockliste automatisch. Nach dem Enrollment einmal neu starten: docker compose restart crowdsec, dann unter app.crowdsec.net prüfen, ob die Instanz erscheint.
Verifizieren: Das System erkennt und blockiert aktiv:
docker exec crowdsec cscli alerts list
# Nach etwas Betrieb: Einträge mit Scenario z. B. "crowdsecurity/ssh-slow-bf"
docker exec crowdsec cscli decisions list
# Aktiv geblockte IPs (falls Angriffe stattfanden)
sudo systemctl status crowdsec-firewall-bouncer
# Muss "active (running)" zeigenSchritt 7: Updates und Hub-Wartung
CrowdSec hat zwei Update-Ebenen, die du regelmäßig bedienen solltest:
cd /opt/crowdsec
# 1. Container-Image aktualisieren:
docker compose pull
docker compose up -d
# 2. Hub-Inhalte aktualisieren (Collections, Parsers, Scenarios):
docker exec crowdsec cscli hub upgrade
# Status nach Update prüfen:
docker compose ps
docker exec crowdsec cscli versionFür den Firewall-Bouncer auf dem Host gilt das normale Paket-Update:
sudo apt update && sudo apt upgrade crowdsec-firewall-bouncer-iptables
sudo systemctl restart crowdsec-firewall-bouncerWie du Container-Updates automatisieren kannst, zeigt die Anleitung zu Docker-Container automatisch aktualisieren mit Diun und WUD.
Verifizieren: Aktuelle Version und laufender Container nach dem Update:
docker exec crowdsec cscli version
# Ausgabe: Version v1.7.8 (oder neuer)
docker compose ps
# STATUS: Up X minutes – kein Neustart-Loop
sudo systemctl status crowdsec-firewall-bouncer
# active (running)Troubleshooting / Typische Fehler
- Decisions verschwinden nach Neustart: Das Volume
crowdsec-datafür/var/lib/crowdsec/datafehlt oder ist nicht gemountet. Ab v1.7.0 zwingend erforderlich. Den Container mitdocker compose down && docker compose up -dneu erstellen (nicht nur neu starten). - Bouncer meldet „connection refused": Die LAPI auf Port 8080 ist an
127.0.0.1gebunden. Auf Linux-Hosts istlocalhost:8080normalerweise erreichbar. Prüfe mitcurl http://127.0.0.1:8080/v1/health– erwartet: HTTP 200. Falls der Container noch startet, kurz warten. - cscli metrics zeigt „0 Lines read" bei Acquisition: Die
acquis.yamlfehlt, ist falsch gemountet oder zeigt auf nicht existierende Pfade. Pfade in deracquis.yamlmüssen den tatsächlichen Pfaden im Container entsprechen (nach dem Mount also/var/log/auth.log). - Docker-Container werden nicht geblockt trotz aktiver Decisions: Die
DOCKER-USERChain fehlt in der Bouncer-Konfiguration (/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml). Sie ist nicht standardmäßig aktiv. Nach der Änderung:sudo systemctl restart crowdsec-firewall-bouncer. - Permission denied beim Log-Lesen: Die
GID-Umgebungsvariable stimmt nicht mit der Gruppe der Log-Dateien überein. Mitstat /var/log/auth.logdie GID prüfen und in der.envanpassen. Danndocker compose up -d --force-recreate. - BOUNCER_KEY_xxx wird ignoriert: Der Key enthält Sonderzeichen (
!,@,#), die im YAML-Escaping Probleme verursachen. Ausschließlich alphanumerische Keys verwenden – am bestenopenssl rand -hex 16nutzen. - cs-firewall-bouncer-Dienst startet nicht: API-Key nicht korrekt in der Bouncer-Config eingetragen oder LAPI noch nicht erreichbar. Mit
sudo journalctl -u crowdsec-firewall-bouncer -n 50die Logs prüfen. - Console-Enrollment wird nicht aktiv: Nach dem ersten Start mit gesetztem
ENROLL_KEYeinmal neu starten:docker compose restart crowdsec. Dann in der Console prüfen, ob die Instanz erscheint.
Häufige Fragen
Brauche ich einen CrowdSec-Account?
Nein, für den Basisbetrieb nicht. CrowdSec läuft vollständig offline ohne Account. Ein kostenloser Account auf app.crowdsec.net ist nur für die CrowdSec Console nötig – also für zentrales Monitoring mehrerer Instanzen und die Synchronisation der Community-Blockliste über den ENROLL_KEY. Der eigentliche Schutz (Log-Analyse, iptables-Blocking) funktioniert ohne Account.
Was ist der Unterschied zwischen Security Engine und Bouncer?
Die Security Engine (der Container) analysiert Log-Dateien, erkennt Angriffsmuster anhand von Szenarien und Parsern und verwaltet eine Liste von Decisions – also IPs, die blockiert werden sollen. Der Bouncer ist die Remediation Component: Er liest diese Decisions über die LAPI und setzt die tatsächliche Blockierung per iptables/nftables um. Ohne Bouncer erkennt CrowdSec alles, tut aber nichts – es bleibt ein reines IDS statt eines IPS.
Kann CrowdSec mit Traefik oder Nginx als Reverse-Proxy arbeiten?
Ja, und das sogar ohne Host-iptables-Zugriff. Es gibt offizielle Bouncer-Plugins für Traefik (traefik-crowdsec-bouncer) und Nginx (crowdsec-nginx-bouncer), die als Middleware im Container laufen und HTTP-Anfragen direkt blockieren können. Diese Variante eignet sich besonders, wenn du keinen root-Zugriff auf den Host-Kernel hast. Die Firewall-Bouncer- und Web-Bouncer-Varianten können auch parallel betrieben werden.
Welche Collections sollte ich mindestens installieren?
Mindestens: crowdsecurity/linux (Basis-Parsers, ohne diese funktioniert nichts korrekt) und crowdsecurity/sshd (SSH-Bruteforce-Schutz, auf nahezu jedem Server relevant). Je nach Dienst zusätzlich: crowdsecurity/nginx für Nginx, crowdsecurity/traefik für Traefik, crowdsecurity/http-cve für bekannte Web-CVEs. Collections können jederzeit nachinstalliert werden: docker exec crowdsec cscli collections install crowdsecurity/http-cve.
Wie prüfe ich, ob CrowdSec tatsächlich etwas erkennt?
Drei Befehle geben dir den vollständigen Überblick: (1) docker exec crowdsec cscli metrics – zeigt, ob Logs gelesen werden (Acquisition-Zeilen sollten Werte > 0 haben). (2) docker exec crowdsec cscli alerts list – zeigt erkannte Angriffe mit Scenario und Zeitstempel. (3) docker exec crowdsec cscli decisions list – zeigt aktiv geblockte IPs. Bouncer-Status auf dem Host: sudo systemctl status crowdsec-firewall-bouncer.
Wie unterscheidet sich CrowdSec von Fail2Ban?
Fail2Ban analysiert ebenfalls Logs und setzt iptables-Regeln, arbeitet aber rein lokal ohne Community-Intelligence. CrowdSec hat eine API-getrennte Architektur (Engine + Bouncer), teilt Bedrohungsdaten mit der globalen Community und bietet deutlich mehr Flexibilität bei den Bouncers (Web, Firewall, Cloud-Anbieter). Der Einstieg ist etwas komplexer, der Schutz aber umfassender. Beide Tools können prinzipiell parallel laufen, was aber zu Konflikten bei iptables-Regeln führen kann.
Fazit
CrowdSec ist eine ernstzunehmende Sicherheitsschicht für jeden Linux-Server mit Docker-Diensten. Die Architektur aus Security Engine und separatem Bouncer ist beim ersten Mal etwas ungewohnt, erklärt sich aber schnell: Der Container analysiert, der Host-Dienst blockiert. Besonders wertvoll ist die Community-Blockliste – jede Installation profitiert von den Erkennungen aller anderen. Der Einrichtungsaufwand von etwa 30 Minuten amortisiert sich schnell, wenn man sieht, wie viele Bruteforce-Versuche und Web-Crawler nach kurzer Zeit automatisch blockiert werden. Wer seine Docker-Dienste hinter einem Reverse-Proxy betreibt, sollte zusätzlich die Web-Bouncer für Traefik oder Nginx in Betracht ziehen – sie ergänzen den Firewall-Bouncer auf der HTTP-Schicht. Eine vollständige Serverhärtung setzt auf mehreren Ebenen an: CrowdSec für aktives IP-Blocking, ergänzt durch UFW-Firewall und Fail2Ban auf der System-Ebene und abgesicherte Docker-Compose-Stacks für die Container-Ebene.
Weiterführende Anleitungen und Quellen
- Linux-Server absichern: UFW-Firewall und Fail2Ban – Basis-Härtung als Ergänzung zu CrowdSec
- Docker Compose absichern: Secrets, Healthchecks und Non-Root – sichere Compose-Stacks im Produktivbetrieb
- Docker und Docker Compose auf Linux installieren – Grundlage für alle Docker-Anleitungen
- Docker-Container automatisch aktualisieren: Diun, WUD und Renovate – CrowdSec-Image aktuell halten
Offizielle Quellen: CrowdSec Docker-Installationsdokumentation, crowdsecurity/crowdsec auf Docker Hub, CrowdSec GitHub Repository, CrowdSec Firewall-Bouncer-Dokumentation.