Skip to content

DISABLE_COLLECTIONS ignored when DISABLE_AGENT=true — LAPI-only container keeps unremovable default collections #4563

Description

@aversag

What happened?

In a LAPI-only container (DISABLE_AGENT=true, no agent, no acquisition — CrowdSec used purely as a decision store fed by CAPI, with a remote bouncer enforcing decisions), the default collections baked into the image (crowdsecurity/linux and its dependencies: sshd, whitelist-good-actors, plus the related parsers/scenarios/contexts/postoverflows) are present in /etc/crowdsec and show up in cscli collections list.

Setting DISABLE_COLLECTIONS=crowdsecurity/linux — the documented way to drop default collections — has no effect, because the removal runs inside prepare_hub(), which returns early when the agent is disabled (build/docker/docker_start.sh):

prepare_hub() {
    if istrue "$DISABLE_AGENT"; then
        return
    fi
    ...
    ## Remove collections, parsers, scenarios & postoverflows
    if [ "$DISABLE_COLLECTIONS" != "" ]; then
        cscli_if_clean collections remove "$DISABLE_COLLECTIONS" --force
    fi
    ...
}

However, the collections arrive independently of the agent, via the staging populate step, which is not gated on DISABLE_AGENT:

if [ ! -e "/etc/crowdsec/local_api_credentials.yaml" ] && [ ! -e "/etc/crowdsec/config.yaml" ]; then
    ...
    rsync -av --ignore-existing /staging/etc/crowdsec/* /etc/crowdsec
fi

So the copy is unconditional but the removal knob is agent-gated → in a LAPI-only container there is no declarative way to remove the baked-in collections. On an emptyDir config this repeats on every boot.

What did you expect to happen?

One of:

  • DISABLE_COLLECTIONS (and DISABLE_PARSERS / DISABLE_SCENARIOS / …) still honored when DISABLE_AGENT=true, so a LAPI-only deployment can clean up hub items it doesn't use; or
  • the staging populate of hub items skipped when the agent is disabled (a pure LAPI has no use for scenarios/parsers); or
  • at minimum, this behavior documented.

Visible symptom: cscli collections list on a LAPI-only engine advertises SSH scenarios that can never fire (no acquisition). It's misleading during audits and feeds "Security Engine: no activity" confusion in the Console.

How can we reproduce it (as minimally and precisely as possible)?

docker run -d --name cs-lapi \
  -e DISABLE_AGENT=true \
  -e DISABLE_COLLECTIONS="crowdsecurity/linux" \
  crowdsecurity/crowdsec:v1.7.7

docker exec cs-lapi cscli collections list
# crowdsecurity/linux, crowdsecurity/sshd, crowdsecurity/whitelist-good-actors
# are still installed despite DISABLE_COLLECTIONS

Same on Kubernetes via the official helm chart with agent.enabled=false (LAPI-only).

Anything else we need to know?

Current workarounds are all post-copy — e.g. a lifecycle.postStart hook running cscli collections remove crowdsecurity/linux --force (which cascades all deps cleanly, confirmed via --dry-run). With an emptyDir config this has to re-run every boot. An agent-independent DISABLE_*, or skipping the hub-item staging when the agent is off, would remove the need for that.

Related but distinct (both agent-side): #1910 (COLLECTIONS not authoritative), #1331 (install/remove ordering). This one is specifically the DISABLE_AGENT / LAPI-only path.

Crowdsec version

crowdsec/v1.7.7-981e6166-docker

OS version

alpine (docker) - 3.21.6

Enabled collections and parsers

crowdsecurity/linux, crowdsecurity/sshd, crowdsecurity/whitelist-good-actors
(all baked-in image defaults; no acquisition configured)

Acquisition config

none — LAPI-only (DISABLE_AGENT=true)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions