CrowdSec with Nginx Proxy Manager

CrowdSec with Nginx Proxy Manager on Home Assistant OS: 8 Steps to Ultimate Homelab Security

If you’re running Home Assistant OS with Nginx Proxy Manager as an add-on and have multiple services exposed to the internet โ€” Bitwarden, Nextcloud, Jellyfin, Home Assistant itself โ€” your setup is under constant automated attack. This guide shows you exactly how to deploy CrowdSec with Nginx Proxy Manager entirely within the Home Assistant ecosystem, using official add-ons, no Docker Compose required. ๐Ÿ›ก๏ธ

Setting up CrowdSec with Nginx Proxy Manager as HA add-ons is one of the smartest security moves a homelab owner can make โ€” and after reading this, you’ll have automatic IP banning, firewall-level blocking, and Telegram alerts running in under an hour.


Why the HA Add-on Approach Works So Well

When NPM runs as a Home Assistant add-on, its container is managed by HA Supervisor โ€” not directly by you. You can’t simply mount shared volumes the way you would with a standard Docker Compose setup.

But here’s the elegant part: the official CrowdSec add-on reads the entire host system journal via journald, which includes logs from every other add-on running on the same machine โ€” including Nginx Proxy Manager. ๐Ÿ“‹

This means CrowdSec with Nginx Proxy Manager gets full log visibility without any volume sharing tricks. One add-on, full coverage across all your proxied services.


What You’ll Deploy

Three components, all native to the HA ecosystem:

ComponentRole
CrowdSec add-onAgent + Local API โ€” reads logs, detects attacks, makes ban decisions
CrowdSec Firewall Bouncer add-onEnforces bans at the nftables/firewall level
Telegram notificationsReal-time alerts to your phone ๐Ÿ“ฑ

The Firewall Bouncer is actually more effective than an Nginx-level bouncer โ€” it blocks malicious IPs at the network layer before they even reach NPM. The combination of CrowdSec with Nginx Proxy Manager plus a firewall-level bouncer is as close to a complete first-line defense as you can get in a homelab. ๐Ÿ”ฅ


Prerequisites

  • Home Assistant OS (HAOS) version 8.0 or higher
  • Nginx Proxy Manager running as a HA add-on
  • SSH or Terminal add-on access
  • A Telegram bot token and chat ID

Step 1: Add the CrowdSec Repository to Home Assistant

The CrowdSec apps are not in the default HA store โ€” you need to add the official repository first.

1.1 Open Apps

Go to Settings โ†’ Apps โ†’ Install app (button in the bottom right corner).

1.2 Add the repository

Click the โ‹ฎ menu (top right) โ†’ Repositories โ†’ Add (button in the bottom right corner) โ†’ paste the official URL:

https://github.com/crowdsecurity/home-assistant-addons

Click Add, then close the dialog.

1.3 Refresh the store

Hard-refresh the page (Ctrl+Shift+R). You should now see two new entries:

  • CrowdSec
  • CrowdSec Firewall Bouncer

Step 2: Install and Configure the CrowdSec Add-on

2.1 Install

Find CrowdSec in the list and click Install. This takes a minute or two.

2.2 Configure before first start

Before starting, go to the Configuration tab. Modify the collections section to cover both Home Assistant and NPM traffic:

acquisition: |
  ---
  source: journalctl
  journalctl_filter:
    - "--directory=/var/log/journal/"
  labels:
    type: syslog
disable_lapi: false
remote_lapi_url: ""
agent_username: ""
agent_password: ""
collections:
  - crowdsecurity/home-assistant
  - crowdsecurity/nginx-proxy-manager
  - crowdsecurity/http-cve
parsers: []
scenarios: []
postoverflows: []
parsers_to_disable:
  - crowdsecurity/whitelists
scenarios_to_disable: []
disable_online_api: false

The three collections do the following:

  • crowdsecurity/home-assistant โ€” detects brute-force on HA login page
  • crowdsecurity/nginx-proxy-manager โ€” detects all attacks routed through NPM (this is the core of CrowdSec with Nginx Proxy Manager detection)
  • crowdsecurity/http-cve โ€” detects known CVE exploit attempts across all services

Click Save.

2.3 Start the add-on

Go to the Info tab โ†’ Start. Enable Start on boot and Watchdog.

2.4 Verify it’s running

Open the Log tab and look for:

level=info msg="Starting crowdsec v1.x.x"
level=info msg="Crowdsec Local API listening on 0.0.0.0:8080"
level=info msg="collection 'crowdsecurity/nginx-proxy-manager' installed"

๐Ÿ’ก Enable Show in sidebar on the Info tab โ€” this pins CrowdSec to the HA sidebar for quick access. You can then open the CrowdSec terminal any time directly from the sidebar without navigating through Settings.


Step 3: Verify NPM Logs Are Being Parsed

This is the most important verification step when running CrowdSec with Nginx Proxy Manager as HA add-ons โ€” confirming that journald is actually capturing NPM traffic.

3.1 Open the CrowdSec terminal

Go to Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI button. This opens a black terminal window directly in your browser with a prompt like root@xxxxxxxx-crowdsec:~#. All cscli commands in this guide are entered here.

3.2 Check acquisition metrics

cscli metrics

In the Acquisition Metrics section, look for source:journalctl with non-zero Lines Read values. Send a few test requests to any of your public subdomains and run the command again โ€” the counter should increase.

3.3 Check loaded scenarios

cscli scenarios list

You should see entries like crowdsecurity/nginx-proxy-manager-bf, crowdsecurity/http-probing, crowdsecurity/http-crawl-non_statics. These are the detection patterns active for your CrowdSec with Nginx Proxy Manager setup. โœ…

3.4 Troubleshooting: if Lines Read stays zero

If acquisition metrics show zero even after real traffic, check the acquisition config:

cat /config/.storage/crowdsec/config/acquis.yaml

Make sure the source: journalctl block is present. If the file is missing or empty, the add-on may need a restart after the initial configuration save.


Step 4: Install the CrowdSec Firewall Bouncer Add-on

The agent detects and decides. The bouncer enforces โ€” it’s what actually drops packets from banned IPs at the firewall level.

4.1 Install

Go to Settings โ†’ Apps โ†’ Install app, find CrowdSec Firewall Bouncer and click Install.

4.2 Generate a bouncer API key

Open the CrowdSec terminal: Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI. In the terminal, run:

cscli bouncers add firewall-bouncer

Copy the key immediately โ€” you won’t see it again:

Api key for 'firewall-bouncer':

         a1b2c3d4e5f6g7h8i9...

Please keep this key since you will not be able to retrieve it!

4.3 Find the CrowdSec add-on hostname

Still in the same CrowdSec terminal (Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI):

hostname

Output will look like 424ccef4-crowdsec. This is the internal Docker hostname that the bouncer will use to connect to the CrowdSec LAPI.

4.4 Configure the Firewall Bouncer

Go to Settings โ†’ Apps โ†’ CrowdSec Firewall Bouncer โ†’ Configuration tab:

api_url: "http://424ccef4-crowdsec:8080/"
api_key: "YOUR_KEY_FROM_STEP_4.2"
update_frequency: "10s"
log_level: info

Replace 424ccef4-crowdsec with your actual hostname and paste in your API key. Click Save โ†’ Start โ†’ enable Start on boot.

4.5 Verify the bouncer is connected

cscli bouncers list

firewall-bouncer should appear as active with a recent Last Pull timestamp. ๐ŸŽฏ


Step 5: Test the Full Pipeline

Before trusting this setup in production, test that the full chain โ€” detection โ†’ decision โ†’ block โ€” actually works.

5.1 Add a test ban

In the CrowdSec terminal (Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI):

cscli decisions add --ip 1.2.3.4 --reason "test-ban" --duration 5m

5.2 Verify the decision

cscli decisions list

5.3 Verify the decision is active

Back in the CrowdSec terminal (Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI):

cscli decisions list

If you see 1.2.3.4 in the list with ban type and active duration โ€” the full chain works. CrowdSec detected โ†’ made a decision โ†’ Firewall Bouncer received it and is enforcing it. โœ…

โ„น๏ธ On HAOS the nft command is not available in the standard terminal. Verifying via cscli decisions list is sufficient โ€” if the decision appears here, the Firewall Bouncer is actively enforcing it at the network level.

5.4 Clean up

cscli decisions delete --ip 1.2.3.4

Step 6: Set Up Telegram Notifications ๐Ÿ“ฑ

6.1 Create a Telegram bot

  1. Open Telegram โ†’ search @BotFather โ†’ send /newbot
  2. Follow the prompts and save the bot token (123456789:ABCdef...)
  3. Send any message to your new bot
  4. Open: https://api.telegram.org/botYOUR_TOKEN/getUpdates
  5. Find "chat" โ†’ "id" in the JSON โ€” this is your chat ID

6.2 Create the notification config

Open the CrowdSec terminal (Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI) and run the block below as a whole โ€” copy everything from cat down to and including EOF, paste it in the terminal and press Enter. This creates the file in one shot, no editor needed:

mkdir -p /config/.storage/crowdsec/config/notifications

cat > /config/.storage/crowdsec/config/notifications/telegram.yaml << 'EOF'
type: http
name: telegram_notifications
log_level: info

format: |
  {
    "chat_id": "YOUR_CHAT_ID",
    "text": "๐Ÿšจ *CrowdSec Alert*\n\nIP: {{range .Alerts}}{{range .Decisions}}{{.Value}}{{end}}{{end}}\nReason: {{range .Alerts}}{{range .Decisions}}{{.Reason}}{{end}}{{end}}\nAction: {{range .Alerts}}{{range .Decisions}}{{.Type}}{{end}}{{end}}\nDuration: {{range .Alerts}}{{range .Decisions}}{{.Duration}}{{end}}{{end}}",
    "parse_mode": "Markdown"
  }

url: https://api.telegram.org/botYOUR_BOT_TOKEN/sendMessage
method: POST
headers:
  Content-Type: application/json

group_wait: 5s
group_threshold: 1
EOF

Replace YOUR_CHAT_ID and YOUR_BOT_TOKEN with your actual values.

โš ๏ธ Critical: Always write persistent config to /config/.storage/crowdsec/config/. Files written directly to /etc/crowdsec/ are lost on every add-on restart. This applies to all config changes in your CrowdSec with Nginx Proxy Manager setup.

6.3 Register the notification in profiles

vi /config/.storage/crowdsec/config/profiles.yaml

๐Ÿ’ก vim basics: press i to enter edit mode, make your changes, then press Esc to exit edit mode. To save and quit type :wq and press Enter. To quit without saving type :q!.

Add the notifications line to the default profile:

name: default_ip_remediation
filters:
  - Alert.Remediation == true && Alert.GetScope() == "Ip"
decisions:
  - type: ban
    duration: 4h
notifications:
  - telegram_notifications
on_success: break

6.4 Restart and test

Go to Settings โ†’ Apps โ†’ CrowdSec โ†’ Restart, then in the CrowdSec terminal test the notification:

cscli notifications test telegram_notifications

You should receive a Telegram message within seconds. ๐ŸŽ‰

If nothing arrives and the Log tab shows this fatal error:

level=fatal msg="api server init: plugin broker: loading plugin: while getting process attributes: group: unknown group nobody"

This is a known issue on HAOS โ€” the nobody group doesn’t exist in the container. Fix it in the CrowdSec terminal:

vi /config/.storage/crowdsec/config/config.yaml

Find the plugin_config section:

plugin_config:
  user: nobody
  group: nobody

Change both values to empty strings:

plugin_config:
  user: ""
  group: ""

Save and exit (:wq), then restart the add-on via Settings โ†’ Apps โ†’ CrowdSec โ†’ Restart. CrowdSec will now start without the fatal error and the notification plugin will work. Run the test again:

cscli notifications test telegram_notifications

Step 7: Join the Community Blocklist

Register free at https://app.crowdsec.net/. After registration:

  1. Log in to the console
  2. Go to Engines (left sidebar)
  3. Click + Add Security Engine
  4. You’ll see a command like sudo cscli console enroll cl1234abcd5678efgh... โ€” copy the command with the key but without sudo

Then in the CrowdSec terminal (Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI) paste and run that command:

cscli console enroll cl1234abcd5678efgh...

Restart the add-on via Settings โ†’ Apps โ†’ CrowdSec โ†’ Restart. CrowdSec will now pull a community blocklist โ€” IPs already reported as malicious by thousands of other CrowdSec users. Pre-emptive blocking before a bad actor even tries anything against your server. ๐ŸŒ


Step 8: Monitor Real Alerts

After a few hours, open the CrowdSec terminal (Settings โ†’ Apps โ†’ CrowdSec โ†’ OPEN WEB UI) and check what CrowdSec with Nginx Proxy Manager has already detected:

# Recent alerts with details
cscli alerts list -o human

# Currently banned IPs
cscli decisions list

# Full detection statistics
cscli metrics

Don’t be surprised if you see dozens of blocked IPs within the first 24 hours โ€” brute-force attempts on Bitwarden and Nextcloud, path traversal probes, CVE scanners. The internet is a very noisy place. ๐Ÿ˜ฌ


Bonus: Cloudflare Bouncer โ˜๏ธ

If you’re using Cloudflare as a proxy in front of your services, there’s a powerful extra layer available: the CrowdSec Cloudflare Bouncer pushes banned IPs directly to Cloudflare’s firewall, blocking them before traffic even leaves Cloudflare’s network โ€” one step earlier than the firewall bouncer.

cscli bouncers add cloudflare-bouncer

Then configure with your Cloudflare API token (needs Zone:Firewall Services:Edit permission). Full setup: https://docs.crowdsec.net/docs/bouncers/cloudflare.


What Gets Detected Out of the Box

Once CrowdSec with Nginx Proxy Manager is running with the collections from Step 2, it detects:

Attack TypeServices Protected
๐Ÿ”ด HTTP brute-forceBitwarden, Nextcloud, HA login
๐Ÿ”ด HA login brute-forceHome Assistant directly
๐ŸŸ  Path traversal attemptsAll proxied services
๐ŸŸ  CVE exploit probingNextcloud, Jellyfin
๐ŸŸ  Bad user agentsMasscan, ZGrab, sqlmap
๐ŸŸก Request floodAll services

For more on securing individual services:


What CrowdSec Does NOT Cover

To set honest expectations: CrowdSec with Nginx Proxy Manager is an IPS, not a SIEM. It will not:

  • Monitor file integrity on disk
  • Detect rootkits or suspicious host processes
  • Scan packages for CVE vulnerabilities

For deeper host-level auditing, Wazuh agents are the natural next step after this setup is running.


Conclusion

Deploying CrowdSec with Nginx Proxy Manager inside Home Assistant OS is simpler than it looks. Two add-ons, a few configuration edits in the HA UI, and you get automatic IP banning, firewall-level enforcement, community threat intelligence, and real-time Telegram alerts โ€” all running natively alongside your existing setup. ๐Ÿ 

The journald-based log architecture means CrowdSec with Nginx Proxy Manager gets full visibility into all proxied traffic without any filesystem workarounds. All config is persistent in /config/.storage/crowdsec/ and survives add-on updates and host reboots.

If you take one security step for your homelab this year โ€” make it this one. ๐ŸŒ™


Quick Reference

CommandPurpose
cscli decisions listShow currently blocked IPs
cscli alerts list -o humanShow recent alerts with details
cscli bouncers listShow connected bouncers
cscli metricsShow detection and acquisition stats
cscli scenarios listList loaded detection scenarios
cscli hub update && cscli hub upgradeUpdate all collections
cscli notifications test telegram_notificationsSend test Telegram alert
cscli decisions add --ip X.X.X.X --duration 1hManually ban an IP
cscli decisions delete --ip X.X.X.XRemove a ban

๐Ÿ“ All persistent config: /config/.storage/crowdsec/config/


Also see: Dozzle in Docker for lightweight container log monitoring, and Portainer setup guide if you’re managing additional Docker services alongside Home Assistant.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.