Deployment guide

CrowdSec 1.8.1

Overview

CrowdSec is an open-source, behaviour-based intrusion detection and prevention engine. The crowdsec agent reads your logs, runs them through detection scenarios (SSH brute force, user enumeration, port scans and more) and records a decision, usually a ban, in its Local API. The firewall bouncer pulls those decisions from the Local API and drops traffic from banned addresses in nftables, the host firewall. The instance also subscribes to the CrowdSec community blocklist through the Central API, so addresses that attack other CrowdSec users are blocked before they reach you.

This SecureAnyCloud AMI runs CrowdSec 1.8.1 on Ubuntu 24.04 on Amazon EC2. It is one version of the SecureAnyCloud WAF and Email Security listing on AWS Marketplace. Select it as the software version when you subscribe and launch. The image is headless, with no web interface. You operate it with the cscli command line over SSH.

What you get:

  • CrowdSec 1.8.1 and the nftables firewall bouncer 0.0.36 from the official CrowdSec apt repository, with the repository signing key and both packages pinned by checksum. They are not held, so apt upgrade keeps them patched.
  • Detection out of the box. The Linux and SSH collections are installed, and the agent reads the system log and the SSH authentication log, so an SSH brute-force attack against the instance is banned within seconds.
  • Per-instance secrets. On first boot, your instance creates its own Local API machine login and password, its own firewall bouncer API key and its own Central API registration. None of them ships in the image, and no two instances share one.
  • Authentication on the Local API. The agent logs in with its machine password and the bouncer with its API key. A request with a wrong or missing key is refused.
  • Loopback only. The Local API (127.0.0.1:8080) and the Prometheus metrics endpoint (127.0.0.1:6060) are not reachable from the network. SSH on port 22 is the only open port.
  • No lock-out. The source address of every successful SSH login is added to a CrowdSec allowlist for 30 days, which also lifts any ban on it, so the firewall bouncer never locks you out of your own instance.
  • Instance metadata blocked. The CrowdSec services cannot reach the EC2 instance metadata service. The instance requires IMDSv2.

Prerequisites

Before you launch, make sure you have:

  • An AWS account subscribed to the SecureAnyCloud WAF and Email Security listing on AWS Marketplace.
  • An EC2 key pair in the Region you launch in.
  • A security group that allows inbound TCP 22 from your own address. No other inbound port is needed.
1

Launch the instance

  • Open the listing on AWS Marketplace, choose Continue to Subscribe, then Continue to Configuration.
  • In Software version, choose CrowdSec 1.8.1 on Ubuntu 24.04, choose your Region, then choose Continue to Launch.
  • Choose an instance type. m5.large is recommended. CrowdSec itself is light, so smaller types work for a single host.
  • Choose your VPC, subnet, key pair and a security group that opens TCP 22 to your address only.
  • Launch the instance.

First boot takes about a minute. It creates the instance's own credentials, registers with the Central API and then starts the engine and the firewall bouncer.

You can also allowlist your management addresses before first boot by using user data. Each line of /etc/sac/crowdsec-allowlist is an IPv4 or IPv6 address or CIDR range that CrowdSec never bans:

#cloud-config write_files: - path: /etc/sac/crowdsec-allowlist permissions: "0644" content: | <your-mgmt-cidr>

Alternatively, launch from the AWS CLI with the AMI ID of the version you chose:

aws ec2 run-instances \
  --image-id <ami-id> \
  --instance-type m5.large \
  --key-name <key-name> \
  --security-group-ids <security-group-id> \
  --subnet-id <subnet-id> \
  --metadata-options HttpTokens=required \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=crowdsec}]'
2

Connect to your instance

Connect over SSH as the ubuntu user (the SSH login user on Ubuntu 24.04) with your key pair:

ssh -i <key-name>.pem ubuntu@<public-ip>

The login message names the main commands and the instance notes file.

3

Check the services and the ports

Check that the engine and the firewall bouncer, which run as two system services, are active:

systemctl is-active crowdsec crowdsec-firewall-bouncer crowdsec-firstboot
active active active

Confirm the installed versions:

sudo cscli version 2>&1 | head -1 sudo crowdsec-firewall-bouncer -version 2>&1 | head -1
version: v1.8.1-debian-pragmatic-amd64-909b5157 version: v0.0.36-debian-pragmatic-amd64-4c315193cd4f19e3937cdee2f15183ec4d602f56

Confirm that only SSH listens on the network. The Local API (8080) and the metrics endpoint (6060) listen on 127.0.0.1:

sudo ss -ltnp | awk 'NR==1 || /crowdsec|sshd/'
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess LISTEN 0 4096 127.0.0.1:6060 0.0.0.0:* users:(("crowdsec",pid=7823,fd=24)) LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:* users:(("crowdsec",pid=7823,fd=14)) LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=985,fd=3),("systemd",pid=1,fd=109)) LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=985,fd=4),("systemd",pid=1,fd=110))
4

Your instance notes

Read the notes file that first boot writes for root. It holds no secrets. It tells you where this instance's credentials are and how to use them.

sudo cat /root/crowdsec-info.txt

The end of the file names this instance's own Local API machine and shows whether the Central API registration worked:

CROWDSEC_VERSION=1.8.1 CROWDSEC_MACHINE=<this instance's machine name> CROWDSEC_FIREWALL_BOUNCER=crowdsec-firewall-bouncer CROWDSEC_CENTRAL=registered

The credentials themselves are in root-only files (mode 0600):

  • /etc/crowdsec/local_api_credentials.yaml: the agent's Local API machine login and password
  • /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml.local: the firewall bouncer's API key
  • /etc/crowdsec/online_api_credentials.yaml: this instance's Central API registration
5

The Local API and its authentication

Check that the agent can log in to its Local API:

sudo cscli lapi status
Loaded credentials from /etc/crowdsec/local_api_credentials.yaml Trying to authenticate with username "<this instance's machine name>" on http://127.0.0.1:8080/ You can successfully interact with Local API (LAPI)

The health endpoint answers on loopback:

curl -s -w '\n%{http_code}\n' http://127.0.0.1:8080/health
{"status":"up"} 200

Every other Local API call needs credentials. Confirm that a request without a bouncer key is refused with HTTP 403:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/v1/decisions
403

List the registered machine and bouncer. There is exactly one of each, created on this instance's first boot:

sudo cscli machines list
sudo cscli bouncers list
6

The community blocklist

Each instance registers itself with the CrowdSec Central API on its first boot. The registration shares the attacks your instance sees (the attacking address and the scenario, never your logs) and pulls the community blocklist, which the bouncer enforces like any other ban. Check the Central API status and the decisions by origin:

sudo cscli capi status
sudo cscli metrics show decisions
You can successfully interact with Central API (CAPI) Sharing signals is enabled Pulling community blocklist is enabled Pulling blocklists from the console is enabled +------------------------------------------+ | Local API Decisions | +----------------+--------+--------+-------+ | Reason | Origin | Action | Count | +----------------+--------+--------+-------+ | generic:scan | CAPI | ban | 6548 | | ssh:bruteforce | CAPI | ban | 7365 | | ssh:exploit | CAPI | ban | 1087 | +----------------+--------+--------+-------+

A brand-new registration can receive an empty list on its first pull. The engine logs received 0 new entries (expected if you just installed crowdsec). The list fills on a later pull, which happens every two hours or when the engine restarts.

Decisions with origin CAPI come from the community blocklist. If the instance has no internet route when it first boots, the engine runs with local detection only and the notes file says CROWDSEC_CENTRAL=not-registered. Register it later with sudo cscli capi register, then run sudo systemctl restart crowdsec.

To stop sharing signals and pulling the community blocklist, empty the Central API registration file and restart the engine. The engine then runs with local detection only:

sudo truncate -s 0 /etc/crowdsec/online_api_credentials.yaml
sudo systemctl restart crowdsec
7

Detection and bans

Confirm that the agent reads the system log and the SSH authentication log:

sudo cscli metrics show acquisition
+------------------------+------------+--------------+----------------+------------------------+-------------------+ | Source | Lines read | Lines parsed | Lines unparsed | Lines poured to bucket | Lines whitelisted | +------------------------+------------+--------------+----------------+------------------------+-------------------+ | file:/var/log/auth.log | 143 | 26 | 117 | 96 | - | | file:/var/log/syslog | 92 | - | 92 | - | - | +------------------------+------------+--------------+----------------+------------------------+-------------------+

Confirm that the Linux and SSH collections are installed:

sudo cscli collections list
crowdsecurity/linux ✔️ enabled 0.4 /etc/crowdsec/collections/linux.yaml crowdsecurity/sshd ✔️ enabled 0.9 /etc/crowdsec/collections/sshd.yaml crowdsecurity/whitelist-good-actors ✔️ enabled 0.4 /etc/crowdsec/collections/whitelist-good-actors.yaml

List the alerts and the bans the engine has made. Within minutes of launch, an internet-facing instance usually shows SSH brute-force attempts here:

sudo cscli alerts list
sudo cscli decisions list

The firewall bouncer keeps the banned addresses in nftables sets in the crowdsec and crowdsec6 tables and drops their traffic on the input and forward hooks. List the tables:

sudo nft list tables
table ip crowdsec table ip6 crowdsec6
8

Never lock yourself out

The firewall bouncer drops every banned address, including on port 22. Three safeguards keep you from banning yourself:

  • Successful SSH logins. When you log in over SSH, a PAM hook adds your source address to the allowlist sac-ssh-logins for 30 days (renewed at every login) and lifts any ban on it. Failed logins are never allowlisted.
  • Private ranges. Addresses in 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 are never banned, so bastion hosts and VPN gateways inside your VPC are safe.
  • Your own allowlist. Add your office or VPN ranges to the sac-admins allowlist, or put them in /etc/sac/crowdsec-allowlist with user data before first boot (Step 1).

Inspect the allowlists:

sudo cscli allowlists list
sudo cscli allowlists inspect sac-ssh-logins

To add a range permanently, run:

sudo cscli allowlists add sac-admins <your-mgmt-cidr> -d "office"

Adding an address to an allowlist also deletes any active ban on it.

If you are locked out before your first successful login (for example, because you connect from a shared address on the community blocklist), connect from another address or through AWS Systems Manager Session Manager. Then run sudo cscli decisions delete --ip <your address>.

9

Ban and unban by hand

Add, list and delete a manual decision:

sudo cscli decisions add --ip 192.0.2.10 --duration 4h --reason "manual block"
sudo cscli decisions list --ip 192.0.2.10
sudo cscli decisions delete --ip 192.0.2.10

The bouncer applies a new decision within about ten seconds. It removes the ban when the decision is deleted or expires.

10

Protect your other services

Install the collection that matches each service you run on the instance, point the agent at the service's log, then reload the engine. For example, for nginx:

sudo cscli collections install crowdsecurity/nginx
sudo tee /etc/crowdsec/acquis.d/nginx.yaml <<'EOF' filenames: - /var/log/nginx/access.log - /var/log/nginx/error.log labels: type: nginx EOF
sudo systemctl reload crowdsec

Browse the available collections with sudo cscli collections list -a.

To protect other hosts, run a bouncer there and register it against this Local API (sudo cscli bouncers add <name>). The Local API listens on loopback only, so you decide how to expose it. For example, change listen_uri in /etc/crowdsec/config.yaml and allow the port from those hosts only.

11

Updates

CrowdSec and the firewall bouncer come from the official CrowdSec apt repository, so they update with the rest of the system. Run:

sudo apt update && sudo apt upgrade

The detection content (parsers, scenarios and collections) updates daily through crowdsec-hubupdate.timer. Check the timer:

systemctl list-timers crowdsec-hubupdate.timer --no-pager
12

Security notes

  • The CrowdSec services run with a systemd IPAddressDeny for the instance metadata addresses only (169.254.169.254, fd00:ec2::254 and 168.63.129.16). The hub and the Central API stay reachable.
systemctl show -p IPAddressDeny crowdsec crowdsec-firewall-bouncer
IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32
  • The CrowdSec services do not start until first boot has created this instance's credentials.
  • SSH accepts keys only. Password logins are refused.
  • CrowdSec writes its logs to /var/log/crowdsec.log, /var/log/crowdsec_api.log and /var/log/crowdsec-firewall-bouncer.log.

Support and licensing

CrowdSec and the CrowdSec firewall bouncer are open source under the MIT licence. Copies are in /usr/share/doc/sac/crowdsec/LICENSE and /usr/share/doc/sac/crowdsec-firewall-bouncer/LICENSE.

SecureAnyCloud provides 24/7 support for this image. Email sales@secureanycloud.com.

CrowdSec is a trademark of its owner. SecureAnyCloud is not affiliated with or endorsed by CrowdSec.

Deploy on AWS

Launch CrowdSec 1.8.1 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS