Skip to main content

Install CrowdSec on Cloudways

New to CrowdSec? Start with the introduction to understand the components and prerequisites.

๐Ÿงช This is an experimental way to run CrowdSec on Cloudways. It works well for detection and WordPress-level remediation. Firewall-level remediation is not possible because Cloudways limits user permissions. We hope Cloudways will support firewall remediation in the future.

Prefaceโ€‹

Cloudways is a managed hosting platform that makes it easy to run websites and apps across multiple cloud providers. It provides SSH access with limited permissions.

You can still run the Security Engine on Cloudways to detect behavior on services like Nginx and Apache, and use our WordPress plugin for remediation (including the blocklist feature). This guide is more detailed than others because Cloudways requires extra steps.

We'll walk you through these steps:

  1. Install CrowdSec using the static build
  2. Set up acquisition and detection collections
  3. Run behavior detection on your past logs to see what would have been flagged
  4. Make CrowdSec run as a user-level service
  5. Connect it to the WordPress plugin to block detected attackers

Install CrowdSec from the static buildโ€‹

In this section, you will download the latest static build, set up the directory structure, and create configuration for the Local API and Central API.

Set up the CrowdSec static buildโ€‹

For this setup we'll put CrowdSec in the /home/master/crowdsec folder.

Get the static buildโ€‹

  • Go to the latest release page
  • Scroll down past the changelog, in the Assets section copy the link to the crowdsec-release.tgz file
  • Ensure you are in the /home/master folder
cd /home/master
  • Download it into /home/master, for example:
wget https://github.com/crowdsecurity/crowdsec/releases/download/v1.6.3/crowdsec-release.tgz
  • Extract the archive:
tar -xvzf crowdsec-release.tgz
  • Rename the extracted folder to crowdsec:
mv crowdsec-v1.6.3 crowdsec

Create the folder hierarchyโ€‹

  • cd into the crowdsec folder:
cd crowdsec
  • Tweak the test_env script to create the necessary folders and config:
sed -i 's|BASE="./tests"|BASE="/home/master/crowdsec"|' test_env.sh
  • Run the script:
./test_env.sh
  • Check one config file symlink to make sure the tweak worked:
ls -la config/parsers/s00-raw/syslog-logs.yaml 

Should output config/parsers/s00-raw/syslog-logs.yaml -> /home/master/crowdsec/config/hub/parsers/s00-raw/crowdsecurity/syslog-logs.yaml

Create the configโ€‹

We will use the template config, update a few ports to avoid conflicts, and configure the Local API and Central API.

  • We'll use the dev.yml template to create our config.yaml:
mv dev.yml config.yaml

Update the configurationโ€‹

/home/master/crowdsec/config.yaml

We need to edit the config file for this static install, avoid conflicts, and set up the Local API.

  • First, replace all ./ with /home/master/crowdsec/ in the config.yaml file
sed -i 's|./|/home/master/crowdsec/|g' config.yaml

Open /home/master/crowdsec/config.yaml with your preferred terminal editor and make the following changes:

  • Update log_media and add log dir
common:
log_media: file ## Change this from stdout to file
log_dir: ./logs ## Add this line, ensure it is indented correctly
  • Then uncomment and replace the hubdir with the correct path:
[...]
hub_dir: /home/master/crowdsec/config/hub
  • Finally, change the local API port to 19443 in order to avoid conflicts
[...]
api:
server:
listen_uri: 127.0.0.1:19443

Create quality-of-life aliasesโ€‹

To make the CLI easier to use, create aliases for cscli and crowdsec so you do not need full paths each time.

  • Add the following to your /home/master/.bash_aliases file:
alias cscli="/home/master/crowdsec/cscli -c /home/master/crowdsec/config.yaml"
alias crowdsec="/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml"
  • Reload your bash profile:
source /home/master/.bashrc

Initialize CAPI (Central API) credentialsโ€‹

Initialize the CAPI credentials with:

cscli capi register

This will generate /home/master/crowdsec/config/online_api_credentials.yaml. Keep this file safe.

The output will instruct you to restart the service, but we'll do that later.

Reset LAPI (Local API) credentialsโ€‹

  • Remove the existing machine and create a new one in auto:
cscli machines list  //ignore the warning it's normal for now
  • You should see something like this
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Name IP Address Last Update Status Version OS Auth Type Last Heartbeat
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
test 2024-09-12T10:04:52Z โœ”๏ธ ? password โš ๏ธ -
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  • Delete the test machine
cscli machines delete test_env
  • Create a new default one with --force to override the existing credentials file
cscli machines add my_logprocessor --auto --force 
  • Check that the credential file has the proper port : cat ./config/local_api_credentials.yaml
url: http://127.0.0.1
login: my_logprocessor
password: 321QSd54QERG321sq54AZEqs45AZDQSd654z65fps

Setup acquisitions and detection collectionsโ€‹

Acquisition configuration indicates to CrowdSec what log files it should look at.
The Detection collections include parsers config and bad behavior detection scenarios for given services.

In our case we'll look at the nginx logs and apache2 logs.

  • We'll use wildcards to work with any application name of your application folder: ls /home/master/applications
  • Replace the content of the config/acquis.yaml file (with you editor of choice) with the following:
filenames:
- /home/master/applications/**/logs/nginx_*.log
labels:
type: nginx
---
filenames:
- /home/master/applications/**/logs/apache_*.log
labels:
type: apache2

Getting collectionsโ€‹

Now we'll install the collections for nginx and apache2.
You can find our catalog on our Hub.

  • Run the following command to install the collections:
cscli collections install crowdsecurity/nginx crowdsecurity/apache2

Making the collections auto updateโ€‹

CrowdSec collection often get updated with the behavior detections.
CrowdSec teams create and currate community scenarios allowing its users to benefit from the latest vulnerabilities detection. We'll allow hub auto-update with a cron:

  • Create a hub_update.sh file in the crowdsec folder:
#!/bin/sh

test -x /home/master/crowdsec/cscli || exit 0

# splay hub upgrade and crowdsec reload
sleep "$(seq 1 300 | shuf -n 1)"

/home/master/crowdsec/cscli -c /home/master/crowdsec/config.yaml --error hub update

upgraded=$(/home/master/crowdsec/cscli -c /home/master/crowdsec/config.yaml --error hub upgrade)
if [ -n "$upgraded" ]; then
# Providing env context to the cron job
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus
systemctl --user reload crowdsec
fi

exit 0
  • Add it to crontab, every day at 6 for example
0 6 * * * sh /home/master/crowdsec/hub_update.sh

Make sure log rotation not breaking acquisitionโ€‹

As CrowdSec is not running as root in our current context, there could be some race conditions with log rotation file creation making the acquisition fail. Future versions of CrowdSec might address this issue, but for now, we can use a simple script to ensure the acquisition is not broken.

  • Create a script to ensure the acquisition is not broken
vi /home/master/crowdsec/check_rotation.sh
#!/bin/sh

# Set the path to your CrowdSec log file
LOG_FILE="/home/master/crowdsec/logs/crowdsec.log"

# Get today's date in the format used in the logs (UTC time)
TODAY=$(date -u +"%Y-%m-%d")

# Define the error pattern to search for
ERROR_PATTERN='level=warning .* died : Unable to open file .*: permission denied'

# Search for the error in today's logs
if grep "$TODAY" "$LOG_FILE" | grep -qE "$ERROR_PATTERN"; then
# Log the action
echo "$(date): Error found, restarting CrowdSec service" >> /home/master/crowdsec/logs/crowdsec_rotation_fail.log

# Providing env context to the cron job
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus
# Restart the CrowdSec service
systemctl restart --user crowdsec

# Log the completion
echo "$(date): CrowdSec service restarted successfully" >> /home/master/crowdsec/logs/crowdsec_rotation_fail.log
else
# Log that no action was taken
echo "$(date): No error found, no action taken" >> /home/master/crowdsec/logs/crowdsec_rotation_fail.log
fi

Make the check run every day at 00:01

1 0 * * * sh /home/master/crowdsec/check_rotation.sh

Run a behavior detection on your past logs to see what it would have foundโ€‹

We can run the behavior detection on the past logs to catch alerts that happened in the past.
We'll run it on the nginx access logs and the first archive of nginx access logs (previous day)

  • Run the behavior detection on the past logs:
./crowdsec -c config.yaml -dsn file:///home/master/applications/\*\*/logs/nginx_*.access.log --type nginx --no-api
  • Note that dsn parameter take the file://*/ protocol and an absolute path
  • After you ran the detection, detected alerts should be listed in:
cscli alerts list

Make CrowdSec service run at user levelโ€‹

We want CrowdSec to run in the background and start at boot.
For this we'll add a systemd service in the user level.

Create the systemd service for userโ€‹

  • At the time of writing (for v1.6.3) you can use the following content:
  • Create and edit ~/.config/systemd/user/crowdsec.service
[Unit]
Description=Crowdsec agent

[Service]
WorkingDirectory=/home/master/crowdsec
Type=notify
Environment=LC_ALL=C LANG=C
ExecStartPre=/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml -t -error
ExecStart=/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml
#ExecStartPost=/bin/sleep 0.1
ExecReload=/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml -t -error
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

Enable the service to run at bootโ€‹

For a user level process to keep running after you close the connection we need to activate the "linger"

  • Run the following command:
loginctl enable-linger
  • Then have systemctl reload and run crowdsec
systemctl --user daemon-reload
systemctl --user enable --now crowdsec
  • Check the status of the service
systemctl --user status crowdsec
  • In the future you can systemctl --user start crowdsec or stop or restart

Checking that CrowdSec worksโ€‹

We ran a behavior detection on the past logs so we might already have acquisition and parsing metrics. But to check that its working, you can visit your website

  • It should generate lines of logs
  • As soon as new log lines arrive in any of those:
    • You should see the acquisition metrics appear/update
    • And the resulting parser acquisition and metrics
cscli metrics -c config.yaml
  • looking something like
Acquisition Metrics:
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ Source โ”‚ Lines read โ”‚ Lines parsed โ”‚ Lines unparsed โ”‚ Lines poured to bucket โ”‚ Lines whitelisted โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ file:/home/master/applications/abcdefghij/logs/apache_wordpress-1211499-4678369.cloudwaysapps.com.access.log โ”‚ 1 โ”‚ 1 โ”‚ - โ”‚ - โ”‚ - โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

[...]

Parser Metrics:
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ Parsers โ”‚ Hits โ”‚ Parsed โ”‚ Unparsed โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ child-crowdsecurity/apache2-logs โ”‚ 1 โ”‚ 1 โ”‚ - โ”‚
โ”‚ child-crowdsecurity/http-logs โ”‚ 3 โ”‚ 3 โ”‚ - โ”‚
โ”‚ crowdsecurity/apache2-logs โ”‚ 1 โ”‚ 1 โ”‚ - โ”‚
โ”‚ crowdsecurity/dateparse-enrich โ”‚ 1 โ”‚ 1 โ”‚ - โ”‚
โ”‚ crowdsecurity/geoip-enrich โ”‚ 1 โ”‚ 1 โ”‚ - โ”‚
โ”‚ crowdsecurity/http-logs โ”‚ 1 โ”‚ 1 โ”‚ - โ”‚
โ”‚ crowdsecurity/non-syslog โ”‚ 1 โ”‚ 1 โ”‚ - โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Bind it to the WP plugin to block the detected attackersโ€‹

Now that we have CrowdSec running and detecting bad behaviors.
Alerts are raised and decisions to block bad actors are stored in the local DB.
To actually apply a remediation and ban the attackers from your website you need:

  • To create a bouncer API key:
cscli bouncers add my_wp_bouncer
  • You should see something like this:
API key for 'my_wp_bouncer':

OI8BQQqMcasoeuxK2g5lMSHPLVkH1tARqLIW0HS3cIY

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