Skip to content

New tutorial: Running a CrowdSec AppSec WAF with Nginx on a Hetzner Cloud server#1444

Open
KEYDALTR wants to merge 2 commits into
hetzneronline:masterfrom
KEYDALTR:add-crowdsec-appsec-waf-nginx-tutorial
Open

New tutorial: Running a CrowdSec AppSec WAF with Nginx on a Hetzner Cloud server#1444
KEYDALTR wants to merge 2 commits into
hetzneronline:masterfrom
KEYDALTR:add-crowdsec-appsec-waf-nginx-tutorial

Conversation

@KEYDALTR
Copy link
Copy Markdown

Summary

This PR adds a new English-language tutorial, crowdsec-appsec-waf-nginx-hetzner-cloud, that shows how to set up CrowdSec AppSec as a Web Application Firewall in front of Nginx on a Hetzner Cloud CX22 running Ubuntu 24.04 LTS, using the OWASP Core Rule Set (CRS) for inband blocking of SQLi, XSS, LFI, RCE, and Log4Shell payloads.

Why this tutorial

The repository currently has one tutorial dedicated to CrowdSec — how-to-set-up-crowdsec-and-protect-ssh — which covers the log-based firewall bouncer for SSH. It does not cover the AppSec (WAF) component, which is a separate part of the CrowdSec stack that works at the HTTP layer instead of the IP layer. The Coolify-specific CrowdSec tutorials in the repo also do not cover standalone Nginx + AppSec.

This tutorial complements the existing SSH-focused content by walking through:

  • Installing Nginx and the crowdsec-nginx-bouncer
  • Enabling the AppSec listener (127.0.0.1:7422)
  • Installing the OWASP CRS collection and creating an inband AppSec config (the default CRS config in the CrowdSec hub only registers rules as out-of-band, which does not block requests in real time — the tutorial explains this)
  • Wiring the bouncer's APPSEC_URL and ALWAYS_SEND_TO_APPSEC to the listener
  • Verifying with SQLi / XSS / path traversal / Log4Shell payloads that actually return HTTP 403
  • Reading cscli metrics to see which CRS rule IDs fired
  • Reducing false positives with the CRS exclusion plugins (WordPress, Nextcloud, phpMyAdmin, …)

Testing

Every command in the tutorial was executed end-to-end on a fresh Hetzner Cloud CX22 running Ubuntu 24.04.3 LTS. The verification section in Step 6 reports the exact HTTP codes observed during the test run (normal: 200, sqli/xss/traversal/log4shell: 403). cscli metrics and cscli alerts list outputs match the expected CRS anomaly-score block behaviour.

Files added

tutorials/crowdsec-appsec-waf-nginx-hetzner-cloud/01.en.md

~2150 words, one language (English). Frontmatter follows the repository template. No images are used.

DCO

I have read and understood the Contributor's Certificate of Origin available at the end of https://raw.githubusercontent.com/hetzneronline/community-content/master/tutorial-template.md and I hereby certify that I meet the contribution criteria described in it.

Signed-off-by: Egemen KEYDAL egemenkeydaltr@gmail.com

EgemenKEYDAL and others added 2 commits April 23, 2026 18:00
…loud server

This tutorial walks through setting up CrowdSec's AppSec component as a Web
Application Firewall in front of Nginx on Ubuntu 24.04, using the OWASP Core
Rule Set for inband detection and blocking of SQL injection, XSS, LFI, RCE,
and Log4Shell payloads. It complements the existing SSH-oriented CrowdSec
tutorial and covers a component not yet documented in the repository.

Verified end-to-end on a Hetzner Cloud CX22 running Ubuntu 24.04.3 LTS.

Signed-off-by: Egemen KEYDAL <egemenkeydaltr@gmail.com>
@svenja11
Copy link
Copy Markdown
Collaborator

Thank you for your contribution @KEYDALTR!

I tested the tutorial and almost everything worked, I only have a few notes:

  • I noticed the tutorial uses root instead of a sudo user. In most cases, using sudo is preferred to reduce the risk of accidental system-wide changes. Was there a specific reason for choosing root? If not, could you please update the commands to use sudo where appropriate?

  • In step 4, the final command did not return any output for me (output was empty):
    journalctl -u crowdsec --since "1 minute ago" | grep -E "inband|appsec"
    Can you please check if something is missing in the tutorial or if this is expected.
    If it is expected, can you please add a note.

  • In step 8, you refer to custom/crs-inband.yaml. Did you mean the file /etc/crowdsec/appsec-configs/crs-inband.yaml?

@svenja11 svenja11 added the needs action Something has to be updated label Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs action Something has to be updated

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants