From b6af49f1f12eb0918174d64708fac58484a7f402 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 3 Jun 2026 12:05:13 +0000 Subject: [PATCH] Add optional ntfy ban alerts to CrowdSec variants When configuring CrowdSec, optionally wire up an ntfy push notification via CrowdSec's HTTP notification plugin: writes /etc/crowdsec/notifications/ntfy.yaml and references it from the default profile in profiles.yaml. Alerts fire on a ban decision (after repeated failed attempts), not on every failed login. Document the behavior in SCRIPT-VARIANTS.md, including why Authelia (email-only) doesn't cover failed-login push. Both crowdsec variants verified with 'bash -n' and a --dry-run --unattended pass (exit 0). https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK --- SCRIPT-VARIANTS.md | 20 ++++++++++++++ ubuntu-post-install-24.04-crowdsec.sh | 39 +++++++++++++++++++++++++++ ubuntu-post-install-26.04-crowdsec.sh | 39 +++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/SCRIPT-VARIANTS.md b/SCRIPT-VARIANTS.md index c4a6506..0032911 100644 --- a/SCRIPT-VARIANTS.md +++ b/SCRIPT-VARIANTS.md @@ -28,6 +28,26 @@ complete, standalone script). - Enforcement via `crowdsec-firewall-bouncer-iptables` - **Geo-blocking + community IP-reputation blocklists** — the capability that fail2ban and Authelia both lack + - **Optional ntfy alerts on bans** — when configuring CrowdSec the script + can wire up an [ntfy](https://ntfy.sh/) push notification (via CrowdSec's + HTTP notification plugin). It writes `/etc/crowdsec/notifications/ntfy.yaml` + and references it from the default profile in + `/etc/crowdsec/profiles.yaml`. The same script can also install a + self-hosted **ntfy server** (separate menu option), so alerts can stay on + your own infrastructure. + +### A note on "notification of failed attempts" + +CrowdSec alerts fire on a **ban decision** — i.e. once an IP crosses the +failed-attempt threshold for a scenario (e.g. `crowdsecurity/ssh-bf`), not on +every individual failed login. That gives you one actionable "X banned for Y" +push instead of a flood. To alert on a single failed login you'd lower the +scenario threshold or write a custom scenario, but the ban-level alert is the +recommended default. + +Authelia, by contrast, only sends **email/SMTP** notifications (for password +reset and 2FA device registration) — it has no built-in "failed login" push, +which is why CrowdSec → ntfy is the path used here. ## Notes on the security layers diff --git a/ubuntu-post-install-24.04-crowdsec.sh b/ubuntu-post-install-24.04-crowdsec.sh index 1e2948f..d235992 100644 --- a/ubuntu-post-install-24.04-crowdsec.sh +++ b/ubuntu-post-install-24.04-crowdsec.sh @@ -4748,6 +4748,45 @@ labels: echo " Subscribe to community/3rd-party blocklists at:" echo " https://app.crowdsec.net/" + # Optional: push ban alerts to ntfy + prompt_yn "Send CrowdSec ban alerts to an ntfy topic? (y/n):" "n" CS_NTFY + if [ "$CS_NTFY" = "y" ] || [ "$CS_NTFY" = "Y" ]; then + prompt_text " ntfy topic URL (e.g. https://ntfy.sh/my-crowdsec):" "https://ntfy.sh/crowdsec-alerts" CS_NTFY_URL + sudo mkdir -p /etc/crowdsec/notifications + NTFY_FILE="/etc/crowdsec/notifications/ntfy.yaml" + NTFY_CONTENT="type: http +name: ntfy +log_level: info +format: | + {{range . -}} + {{range .Decisions -}} + {{.Value}} banned: {{.Scenario}} for {{.Duration}} + {{end -}} + {{end -}} +url: $CS_NTFY_URL +method: POST +headers: + Title: CrowdSec ban + Priority: high + Tags: rotating_light" + if echo "$NTFY_CONTENT" | sudo tee "$NTFY_FILE" > /dev/null; then + echo " ✓ Created ntfy notification ($NTFY_FILE)" + # Wire the notification into the default profile (only once) + if ! grep -qE "^\s*- ntfy" /etc/crowdsec/profiles.yaml 2>/dev/null; then + sudo awk '1; /^on_success:/ && !d {print "notifications:"; print " - ntfy"; d=1}' \ + /etc/crowdsec/profiles.yaml | sudo tee /etc/crowdsec/profiles.yaml.new > /dev/null \ + && sudo mv /etc/crowdsec/profiles.yaml.new /etc/crowdsec/profiles.yaml + echo " ✓ Enabled ntfy alerts in CrowdSec default profile" + else + echo " ✓ ntfy already referenced in CrowdSec profile" + fi + echo " ℹ Alerts fire when an IP is banned (after repeated failed attempts)," + echo " not on every individual failed login." + else + echo " ⚠ Failed to write ntfy notification config" + fi + fi + # Restart services to apply prompt_yn "Restart CrowdSec to apply changes? (y/n):" "y" RESTART_CS if [ "$RESTART_CS" = "y" ] || [ "$RESTART_CS" = "Y" ]; then diff --git a/ubuntu-post-install-26.04-crowdsec.sh b/ubuntu-post-install-26.04-crowdsec.sh index 2c40761..44c971a 100644 --- a/ubuntu-post-install-26.04-crowdsec.sh +++ b/ubuntu-post-install-26.04-crowdsec.sh @@ -4728,6 +4728,45 @@ labels: echo " Subscribe to community/3rd-party blocklists at:" echo " https://app.crowdsec.net/" + # Optional: push ban alerts to ntfy + prompt_yn "Send CrowdSec ban alerts to an ntfy topic? (y/n):" "n" CS_NTFY + if [ "$CS_NTFY" = "y" ] || [ "$CS_NTFY" = "Y" ]; then + prompt_text " ntfy topic URL (e.g. https://ntfy.sh/my-crowdsec):" "https://ntfy.sh/crowdsec-alerts" CS_NTFY_URL + sudo mkdir -p /etc/crowdsec/notifications + NTFY_FILE="/etc/crowdsec/notifications/ntfy.yaml" + NTFY_CONTENT="type: http +name: ntfy +log_level: info +format: | + {{range . -}} + {{range .Decisions -}} + {{.Value}} banned: {{.Scenario}} for {{.Duration}} + {{end -}} + {{end -}} +url: $CS_NTFY_URL +method: POST +headers: + Title: CrowdSec ban + Priority: high + Tags: rotating_light" + if echo "$NTFY_CONTENT" | sudo tee "$NTFY_FILE" > /dev/null; then + echo " ✓ Created ntfy notification ($NTFY_FILE)" + # Wire the notification into the default profile (only once) + if ! grep -qE "^\s*- ntfy" /etc/crowdsec/profiles.yaml 2>/dev/null; then + sudo awk '1; /^on_success:/ && !d {print "notifications:"; print " - ntfy"; d=1}' \ + /etc/crowdsec/profiles.yaml | sudo tee /etc/crowdsec/profiles.yaml.new > /dev/null \ + && sudo mv /etc/crowdsec/profiles.yaml.new /etc/crowdsec/profiles.yaml + echo " ✓ Enabled ntfy alerts in CrowdSec default profile" + else + echo " ✓ ntfy already referenced in CrowdSec profile" + fi + echo " ℹ Alerts fire when an IP is banned (after repeated failed attempts)," + echo " not on every individual failed login." + else + echo " ⚠ Failed to write ntfy notification config" + fi + fi + # Restart services to apply prompt_yn "Restart CrowdSec to apply changes? (y/n):" "y" RESTART_CS if [ "$RESTART_CS" = "y" ] || [ "$RESTART_CS" = "Y" ]; then