Plan a local decision import
This guide was reviewed against CrowdSec Security Engine 1.8.2 and firewall bouncer 0.0.36 on 2026-10-28. Use patched releases, Python 3.11+, curl, util-linux flock, a working local API (LAPI) and an authorized local cscli installation. The example targets a Linux host with systemd.
Importing IPs creates ban decisions; a remediation component must consume and enforce them. This is an operator-managed import, not a native Data-Shield Hub collection or a Console subscription. Keep existing CrowdSec detection and firewall policies. A Console account is not used by this procedure.
Measure database, API, memory and bouncer capacity with the complete feeds before production. Both profiles overlap, so importing both can create multiple decisions for one IP. A bouncer's enforced IP count may therefore be smaller than the sum. Deploy one profile if that is your policy; the example shows both with separate reasons for provenance and rollback.
Validate both full feeds first
Standard
113,445 unique IPv4 addresses in this published snapshot.
https://raw.githubusercontent.com/duggytuxy/Data-Shield_IPv4_Blocklist/refs/heads/main/prod_data-shield_ipv4_blocklist.txtCritical
122,242 unique IPv4 addresses in this published snapshot.
https://raw.githubusercontent.com/duggytuxy/Data-Shield_IPv4_Blocklist/refs/heads/main/prod_critical_data-shield_ipv4_blocklist.txtPublished 28 Oct 2026, 15:31 UTC. Check live counts and SHA-256.
The public Linux staging helper resolves GitHub main, downloads both files at that immutable commit, checks canonical public IPv4 records, ordering and duplicates, and compares counts, bytes and SHA-256 with the public snapshot. It checks main and snapshot again before writing anything. It rejects a publication older than six hours, a partial file or a publication race. If the website has not caught up with GitHub, retry later.
The helper only writes a new local bundle. It does not invoke CrowdSec or nftables. Use a private directory controlled by the importing administrator. Verified HTTPS and matching publication metadata establish file consistency, not that every member is malicious.
curl --fail --show-error --location --proto '=https' --tlsv1.2 \
https://data-shield.eu/downloads/data-shield-linux.py \
--output data-shield-linux.py
python3 data-shield-linux.py --help
# Review the downloaded source before installing it.
sudo install -o root -g root -m 0755 data-shield-linux.py /usr/local/sbin/data-shield-linux.pyImport with bounded lifetimes and separate reasons
Create the private working directory, then save the following script as /usr/local/sbin/data-shield-crowdsec-update, owned by root and mode 0750. Run it with the local account authorized for LAPI, usually root. Do not copy or expose LAPI credentials.
sudo install -d -o root -g root -m 0700 /var/lib/data-shield-crowdsec#!/bin/sh
set -eu
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export PATH
umask 077
exec 9>/run/lock/data-shield-crowdsec.lock
flock -n 9 || exit 75
work=$(mktemp -d /var/lib/data-shield-crowdsec/run.XXXXXX)
trap 'rm -rf -- "$work"' EXIT
trap 'exit 1' HUP INT TERM
python3 /usr/local/sbin/data-shield-linux.py --output "$work/bundle"
for profile in standard critical; do
cscli decisions import --input "$work/bundle/$profile.txt" \
--format values --scope Ip --type ban --duration 3h \
--reason "data-shield-$profile" --batch 1000
doneThe import command accepts one IP per line with --format values. The reviewed implementation uses origin cscli-import, checks local allowlists and submits batches. Keep those exclusions; account for skipped allowlisted addresses when checking totals. A batch size of 1,000 limits each API request, not the full import size.
Both files are validated before the first import, but LAPI imports are not an atomic replacement. If a later batch or the second profile fails, earlier batches may already be active. Do not delete the existing decisions first. Monitor the final imported count, exclusions, exit status and duration for each profile.
With a successful refresh every two hours and a three-hour decision duration, an IP removed from the source stops being renewed and its previously imported decisions expire within three hours of their last import, plus the bouncer's propagation interval. Other CrowdSec decisions for that IP can still apply. Repeated source failures eventually let these imported bans expire. This deliberately favors bounded retention over indefinite stale blocking; alert on the first missed run.
Verify the bouncer and the traffic path
Use the supported firewall bouncer for your platform. Its nftables backend can manage its own rules or work with existing sets. Review its actual configuration before deployment: it must receive cscli-import decisions of scope Ip and type ban, including both dedicated reasons. An origin filter that excludes imports prevents enforcement. Do not reconfigure an existing bouncer blindly.
Test with an actual current feed member from the validated bundle. Replace MEMBER_IP below. Confirm the reason, origin and remaining duration, then check the bouncer's active membership and packet counters on the intended input or forwarding path. A listed decision alone does not prove blocking. Use an isolated test path and preserve management access.
sudo cscli decisions list --ip MEMBER_IP
sudo cscli bouncers list
sudo cscli metrics show bouncersThe CLI list view can group or limit results. Do not use its default displayed row count as a complete-feed audit. Compare the successful import totals with the bundle manifest, subtract documented local allowlist exclusions, and test removals after expiry. Keep imported source membership distinct from CrowdSec's behavior-based detections.
Refresh every two hours
After a successful manual run, create these two dedicated units. The service must finish well before the next refresh and before the three-hour decision lifetime. Monitor failed units and the journal through your existing alerting. This timer changes only your consumer; it does not request a new Data-Shield source collection.
[Unit]
Description=Import verified Data-Shield CrowdSec decisions
Wants=network-online.target
After=network-online.target crowdsec.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/data-shield-crowdsec-update
TimeoutStartSec=45min
UMask=0077[Unit]
Description=Refresh Data-Shield CrowdSec decisions every two hours
[Timer]
OnBootSec=5min
OnUnitActiveSec=2h
RandomizedDelaySec=2min
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl start data-shield-crowdsec.service
sudo systemctl enable --now data-shield-crowdsec.timer
sudo systemctl list-timers data-shield-crowdsec.timer
sudo journalctl -u data-shield-crowdsec.service -n 40 --no-pagerRemove only this integration
Stop the dedicated timer and any running importer before deleting these decisions. Reserve the two reason strings exclusively for this integration. The delete filters below target its origin and decision scenario; avoid --all or broad IP deletion, which could affect unrelated security decisions.
sudo systemctl disable --now data-shield-crowdsec.timer
sudo systemctl stop data-shield-crowdsec.service
sudo cscli decisions delete --origin cscli-import --scenario data-shield-standard
sudo cscli decisions delete --origin cscli-import --scenario data-shield-criticalWait for the bouncer to process removals and verify that unrelated decisions and rules remain. Remove only the dedicated units and updater if no longer required.
Validation scope. Commands and lifecycle were checked against official documentation and versioned CrowdSec source. The staging helper was tested with complete published feeds and invalid inputs. No live CrowdSec instance was installed or certified; test full-feed capacity, local exclusions, partial failures and expiration in your staging environment.
BETTER DATA. TOGETHER.
Need a correction?
Report a documentation issue or request a review of an address. Keep credentials and private configuration out of public issues.