NPMplus + CrowdPanel — a modern reverse proxy with HTTP/3, WAF and a CrowdSec control panel as HA apps

Hi everyone,

two apps from my repository that belong together: NPMplus as a reverse proxy, and CrowdPanel as a web UI for CrowdSec. Both have been running in production on my system for weeks.

One thing up front, because it matters: the software behind NPMplus is not mine. NPMplus is a project by ZoeyVid — a fork of NGINX Proxy Manager that builds on it with features the original does not carry (and Zoey sends security fixes back upstream — the role-escalation fix in NPM 2.15.0 is theirs). My part is the Home Assistant packaging: manifest, entrypoint, all options in the HA config dialog, translations, documentation, and a few extras such as the country blocking. Credit for the application itself goes to ZoeyVid.


Part 1 — NPMplus

Why a reverse proxy at all?

If you run several services at home — Home Assistant, Nextcloud, a media dashboard — each one lives on its own IP and port, with no certificate and no name. A reverse proxy takes all requests at one point (port 443), decides by domain name where they belong, handles the HTTPS certificate, and forwards them internally.

The result: https://ha.mydomain.com instead of http://192.168.1.42:8123, a valid Let’s Encrypt certificate for everything, and only one entry point exposed to the internet — one you can then actually secure properly.

Why NPMplus instead of NGINX Proxy Manager?

To be fair to the alternative: the official Nginx Proxy Manager app is alive again — v3.0.0 shipped in August 2026 with NPM 2.15.1 — and it needs no configuration at all, so it stays the easier choice if the list below holds nothing you want. The UI is the same in both, so you’ll find your way around immediately. The difference is underneath:

  • HTTP/3 (QUIC) — faster connection setup, especially on mobile: a network change (Wi-Fi → LTE) no longer drops the connection. Runs over UDP 443, which you need to forward in your router as well.
  • Hardened TLS out of the box — what you’d otherwise assemble by hand in custom snippets is preconfigured. ML-KEM is the post-quantum key exchange, Encrypted Client Hello hides the requested hostname from observers.
  • CrowdSec bouncer built in — no extra container, no Lua wiring. Tick the box, paste the API key, done.
  • AppSec/WAF — evaluates a request before it is forwarded, so an attack pattern is caught on the live request instead of after it landed in a log file.
  • Access lists per location — password-protect /admin and leave the rest of the domain open. With NPM it was all or nothing.

What the app adds on top

  • Country blocking directly in nginx, no MaxMind account. Block list or allow list, a ready-made high_risk preset (16 countries), per-hostname exemptions and your own IP deny list.
  • Every option in the HA dialog instead of environment variables — CrowdSec, GoAccess, worker tuning, log rotation. Anything not covered goes through extra_env as KEY=VALUE.
  • crowdsec_lapi_url: "auto" — the app asks the Supervisor for the installed CrowdSec app and resolves its container name itself (the container IP 172.30.33.x changes on every start).
  • Data within reach (expose_data_dir): moves database, certificates, custom_nginx and access lists into /app_configs/<slug>, so Samba and the file editor can get at them. Off by default — the folder then holds the private keys of every certificate.
  • Self-test: docker exec <npmplus> /selftest.sh checks web UI, logs, bouncer config, LAPI, AppSec, key length and certificate lifetime in one run.
  • Watchdog: the Supervisor probes the port and restarts the app if nginx hangs.
  • Logs go to the app log (journald — which is what CrowdSec reads) and/or to /share/npmplus/logs.

About CrowdSec — the most common mix-up

CrowdSec has two halves, and they’re easy to confuse:

NPMplus writes its access log
        ↓  journald
CrowdSec engine reads it → parsers and scenarios → decision "ban 1.2.3.4"
        ↓  LAPI on port 8080, bouncer key
NPMplus bouncer pulls the decisions → blocks 1.2.3.4
  • The engine (LAPI) detects. It is not part of my app — use the official CrowdSec apps.
  • The bouncer enforces. That one is already inside NPMplus, nothing to install.

Without a running engine, all crowdsec_* options do nothing. An extra firewall bouncer doesn’t conflict — it blocks all ports at IP level, the nginx bouncer only HTTP, but in exchange it can show a ban page and a captcha.

Note for people migrating: NPMplus writes a different log format than NPM, so the crowdsecurity/nginx-proxy-manager collection does not match it.


Part 2 — CrowdPanel

Once CrowdSec runs, sooner or later you want to know: who is banned right now, and why can’t my own phone get in anymore? The answer comes from cscli — on the command line, inside the container, with the right config path. That’s what CrowdPanel replaces.

It talks to the local API of an existing CrowdSec installation:

  • Overview — active decisions, alerts from the last 24 hours, top countries and scenarios
  • Decisions — filter by scope, type and origin; remove individually or in bulk
  • New decision — single IP, CIDR range, whole country or a whole network (AS), free-form duration and reason
  • Alerts — grouped by address or scenario, with events and the triggering log line; ban straight from the row
  • IP lookup — active decisions, alert history and allowlist matches for one address
  • Exceptions — allowlists and whitelist parsers in plain text, with an explanation of the difference
  • Two-factor login — TOTP for the direct port, QR code generated locally, backup codes
  • Home Assistant sensors — active decisions, locally detected ones, detections in the last 24 hours
  • Dark/light, DE/EN, HA Ingress (sidebar, no second login), PWA

Scope: CrowdPanel does not replace a bouncer and does not read logs. It manages the decisions in the engine — enforcement stays with the bouncers, for example the one in NPMplus. Not included are cscli bouncers list, machines list, metrics and hub list; those read the local database instead of the API.

Installation

Add the repository to Home Assistant: GitHub - LuckyTriple7/HA-AddOns: Home Assistant Add-ons: Webtop Desktop, Firefox, Claude Code, Signal, Telegram, WhatsApp, Filebox, Playwright · GitHub

Setup, all options and troubleshooting are in the docs: NPMplus · CrowdPanel — both in English and German, amd64 and aarch64.

My Homepage