- Shell 45.1%
- Python 42.8%
- Dockerfile 7.7%
- C 4.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo | ||
| .githooks | ||
| .openso/scripts | ||
| .dockerignore | ||
| AGENTS.md | ||
| crowdsec-agent-prepare.sh | ||
| crowdsec-agent-run.sh | ||
| Dockerfile | ||
| entrypoint.crowdsec-agent.sh | ||
| LICENSE | ||
| README.md | ||
| su-exec.c | ||
crowdsec-agent
CrowdSec 1.8.2 agent image. It copies the upstream GeoIP and hub data into the data volume, then runs the agent as a non-root user. The customer stack lives in docker-templates at templates/crowdsec_agent. This repository is the image only.
The upstream image only symlinks /staging/var/lib/crowdsec/data. Those files are root and mode 0600, and so is the staging config under /staging/etc/crowdsec. This image copies a missing data entry, or a symlink, into the writable volume and leaves a regular file that cscli hub upgrade already wrote. On an empty config mount it also copies the staging config.
Image
git.openso.de/openso/crowdsec-agent:main
docker-templates uses git.openso.de/openso/crowdsec-agent with no tag. Docker resolves that reference to :latest. :latest tracks the same build as :main.
| Tag | Contents |
|---|---|
main, latest |
Current Dockerfile on main. Use this reference with no tag. |
v* |
The commit that tag points at. A release tag is optional. |
One image. A newer CrowdSec release is a new FROM tag in this Dockerfile.
Leave the container user unset. The entrypoint starts as root, then drops to CROWDSEC_AGENT_UID:CROWDSEC_AGENT_GID (default 1000:1000). A hardened service keeps read_only: true, drops every capability, and adds SETUID, SETGID, CHOWN, and DAC_OVERRIDE for that seed. docker-templates leaves user unset on crowdsec_agent for this reason. Setting user to 1000:1000 skips the seed and the container exits.
The agent does not publish a port. DISABLE_LOCAL_API=true keeps the local API off. Alerts go to LOCAL_API_URL.
Use
Mount a writable volume at /var/lib/crowdsec/data and a writable config directory at /etc/crowdsec. The upstream start exits when /var/lib/crowdsec/data is not a mount. Put acquisition files in the config directory (acquis.yaml or acquis.d/). Log files the agent reads are separate read-only mounts.
LOCAL_API_URL is required. TZ sets the container clock.
services:
crowdsec_agent:
image: git.openso.de/openso/crowdsec-agent
read_only: true
cap_drop:
- ALL
cap_add:
- SETUID
- SETGID
- CHOWN
- DAC_OVERRIDE
security_opt:
- no-new-privileges:true
init: true
tmpfs:
- /run:rw,noexec,nosuid,nodev,size=64m
- /tmp:rw,noexec,nosuid,nodev,size=128m
- /var/tmp:rw,noexec,nosuid,nodev,size=128m
volumes:
- crowdsec_agent_data:/var/lib/crowdsec/data:rw
- ./appdata/crowdsec_agent/config:/etc/crowdsec:rw
- ./appdata/logs:/var/log/appdata:ro
environment:
TZ: Europe/Berlin
DISABLE_LOCAL_API: "true"
LOCAL_API_URL: http://192.0.2.1:8080
COLLECTIONS: crowdsecurity/traefik
CROWDSEC_AGENT_MACHINE: traefik-crowdsec_agent
healthcheck:
test: ["CMD-SHELL", "cscli lapi status > /dev/null 2>&1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 2m
volumes:
crowdsec_agent_data:
Create ./appdata/crowdsec_agent/config before the first start. The LAPI must already be listening at LOCAL_API_URL. After the first successful cscli lapi register, validate that machine on the LAPI. The login and password are written to /etc/crowdsec/local_api_credentials.yaml on the config mount.
Use the template in docker-templates when this container sits in an app stack. That template also mounts the log directory the acquisition file names.
Environment
The entrypoint reads these. Unset names use the default. LOCAL_API_URL has no default.
| Variable | Default | Purpose |
|---|---|---|
LOCAL_API_URL |
(required) | Remote LAPI. Only http://host[:port][/] or https://host[:port][/]. Empty, CHANGE_ME, a user, a path, a query, or a fragment stops startup. |
CROWDSEC_AGENT_UID |
1000 |
Numeric uid after the seed. |
CROWDSEC_AGENT_GID |
1000 |
Numeric gid after the seed. |
CROWDSEC_AGENT_MACHINE |
container hostname | Machine name for cscli lapi register --machine. Set it before the first registration. |
TZ |
(unset) | Container time zone, for example Europe/Berlin. |
After the uid drop, /docker_start.sh from crowdsecurity/crowdsec 1.8.2 still applies its own variables. This image expects the agent-only set:
| Variable | Default | Purpose |
|---|---|---|
DISABLE_LOCAL_API |
upstream default starts a local API | true is agent-only. The local API stays off and no port is published. |
COLLECTIONS |
(unset) | Space-separated hub collections installed on start. The same collections belong on the remote LAPI. |
DISABLE_AGENT |
(unset) | true skips the agent process. Leave it unset for this image. |
Other upstream variables (PARSERS, SCENARIOS, DSN, LEVEL_INFO, and the rest of that start script) still pass through. They are unchanged from crowdsecurity/crowdsec 1.8.2.
Startup
On start the entrypoint:
- Requires uid 0.
CROWDSEC_AGENT_UIDandCROWDSEC_AGENT_GIDmust be numeric. - Copies each file or directory from
/staging/var/lib/crowdsec/datainto/var/lib/crowdsec/datawhen that name is missing or still a symlink. A regular file or directory already there stays, so a latercscli hub upgradekeeps what it wrote. - Copies
/staging/etc/crowdsecinto/etc/crowdsecwhen that mount has neitherconfig.yamlnorlocal_api_credentials.yaml. - Gives both trees to
CROWDSEC_AGENT_UID:CROWDSEC_AGENT_GID. - Drops to that uid and requires a valid
LOCAL_API_URL. - Replaces the upstream
/does/not/existacquisition placeholder with/dev/nullwhenacquis.yamlstill contains it. Real sources stay inacquis.d/. - Restores
api.client.credentials_pathto/etc/crowdsec/local_api_credentials.yamlwhen a savedconfig.yamldropped it. - When
config.yamlexists andlocal_api_credentials.yamlhas nologin:line, runscscli lapi register -u "${LOCAL_API_URL}" --machine "${CROWDSEC_AGENT_MACHINE}". A file that already haslogin:is left in place. Step 3 copies the stagingconfig.yamlonto an empty mount, so this registration runs on that same start. - Execs
/docker_start.sh. That script calls the same prepare step again after it writes config and beforecrowdsec.
An empty mount registers during the first start that has a valid LOCAL_API_URL. Validate that machine on the LAPI once. If the LAPI is down, the start exits and the next start retries while login: is still missing. Later starts reuse the saved login.
Build
A push to main builds and pushes :main and :latest. A tag v* builds and pushes :<tag> and :latest. The first commit on main is that push, so the first image is produced without a manual build.
The base is crowdsecurity/crowdsec:v1.8.2. yq v4.50.1 is rebuilt with Go 1.26.10 from a source tarball checked by YQ_SHA256. golang.org/x/net v0.60.0, golang.org/x/text v0.42.0, and golang.org/x/sys v0.49.0 replace the versions in that tag so the image scan can clear fixed HIGH findings. Alpine packages in the su-exec stage are pinned. A version bump is a new CrowdSec tag, the Alpine tag, YQ_VERSION, YQ_SHA256, or one of those module pins. Do not resolve a floating tag during the build.
License
MIT. See LICENSE. Maintainer: openso. Source: https://git.openso.de/openso/crowdsec-agent