← Start of tutorial

WIUNIX ACADEMY

CrowdSec and Nginx: trustworthy logs, private LAPI and reversible IP bans

Page 4 of 5. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Debian13Reviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment7 editable values
11

LET’S BUILD

Inspect acquisition, parsing and bouncer authentication

Generate a request first, then inspect. Loopback events may be whitelisted by the collection; that is expected and is not a failed parser. explain evaluates parsing, not scenario overflow. A recent authenticated bouncer pull plus a real403 test is stronger evidence than a registered row alone.

bash

Dedicated disposable VM · terminal

curl --noproxy '*' --interface '127.0.0.2' --fail http://127.0.0.1:18080/index.html
sleep 1
sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' explain --crowdsec '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec/crowdsec' --file '/srv/academy-crowdsec/logs/access.log' --type nginx
sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' metrics --url 'http://127.0.0.1:18082/metrics' show acquisition
sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' bouncers list
How do I know it worked?

The source path appears in acquisition metrics, Nginx parsing is visible, and the bouncer has queried the local API.

12

LET’S BUILD

Ban only the controlled loopback source

Add a30-second manual decision, wait beyond the one-second live cache, then test. The other request deliberately forges both common client-IP headers; it must still be allowed because its TCP peer is management. Manual ban proves decision enforcement, not automatic scenario detection.

bash

Dedicated disposable VM · terminal

sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' decisions add --ip '127.0.0.2' --type ban --duration 30s --reason academy-test
sleep 2
curl --noproxy '*' --interface '127.0.0.2' --silent --output /dev/null --write-out '%{http_code}\n' http://127.0.0.1:18080/index.html
curl --noproxy '*' --interface 127.0.0.1 --fail -H 'X-Forwarded-For: 127.0.0.2' -H 'X-Real-IP: 127.0.0.2' http://127.0.0.1:18080/index.html
sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' decisions list --ip '127.0.0.2'
How do I know it worked?

First request403; spoofed-header management request academy-ok; decision identifies 127.0.0.2.

13

LET’S BUILD

Recover the exact source and verify expiry

Delete only this source’s test decisions, never all decisions. After the second short decision, verify that expiry also restores access after cache refresh. Keep independent console/SSH access for real deployments; allowlists are not a replacement for a recovery route.

bash

Dedicated disposable VM · terminal

sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' decisions delete --ip '127.0.0.2'
sleep 2
curl --noproxy '*' --interface '127.0.0.2' --fail http://127.0.0.1:18080/index.html
sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' decisions add --ip '127.0.0.2' --duration 5s --reason academy-expiry
sleep 7
curl --noproxy '*' --interface '127.0.0.2' --fail http://127.0.0.1:18080/index.html
How do I know it worked?

Both final requests return academy-ok; the5-second decision no longer blocks after7 seconds.

Understand the real API failure policy

This recipe chooses live mode with a one-second cache and500ms request timeout. In reviewed bouncer1.2.3, failed LAPI requests and non200 API responses allow uncached traffic; this is fail open, not a configurable universal fail-closed guarantee. A cached ban can survive until its cache TTL. A syntactically broken initialization can instead prevent Nginx starting. Stream mode has a different stale-state/timer model and is not tested by this recipe.

In terminalA stop only the foreground lab engine with Ctrl+C; after more than one second request the test file from terminalB. It should remain available while the dedicated error log records the failed API request. Restart terminalA with the same command and repeat ban/unban. Availability during an outage means reputation enforcement is degraded; monitor it. APPSEC_FAILURE_ACTION controls AppSec, not this LAPI failure policy. The initial missing CAPTCHA key/ban-template notices are expected for this ban-only403 configuration; they are not proof of a broken LAPI. Do not hide later API authentication/time-out errors among those notices.

Read bounded diagnostics without exposing keys

Use these panels for the outage test and non-secret logs. Never dump complete Nginx configuration or print the bouncer credential file as a support transcript: expanded configuration and private credentials do not belong in tickets. Restrict and rotate access/error logs; combined logs contain IPs, user agents, referrers and requested paths/query strings. Do not use real personal URLs in this lab.

bash
curl --noproxy '*' --interface '127.0.0.2' --fail http://127.0.0.1:18080/index.html
sudo tail -n 20 '/srv/academy-crowdsec/logs/nginx-error.log'
sudo '/srv/academy-crowdsec/crowdsec-v1.8.1/cmd/crowdsec-cli/cscli' -c '/srv/academy-crowdsec/config/engine.yaml' alerts list
14

LET’S BUILD

Stop only this child Nginx and preserve evidence

The dedicated prefix/config/PID select this child Nginx. Stop terminalA with Ctrl+C. Preserve private state until you have reviewed false positives; do not delete unrelated decisions, services or logs. A fresh root is safer than reusing a half-completed lab. To revoke a compromised dedicated bouncer, use the separate scoped command below and register a replacement in a new protected file; revocation may make live-mode traffic fail open.

bash

Dedicated disposable VM · terminal

sudo nginx -p '/srv/academy-crowdsec/' -c '/srv/academy-crowdsec/config/nginx.conf' -s quit
How do I know it worked?

Only the dedicated Nginx listener exits; private files remain for review.

Explore all tutorials ↗