No introduction found. Create it?
Install with:
helm repo add crowdsec oci://ghcr.io/bjw-s-labs/charts/
helm install crowdsec crowdsec/crowdsec -f values.yamlSee examples from other people.
| Name | Repo | Stars | Version | Timestamp |
|---|---|---|---|---|
| crowdsec | ToaHartor/maisonneux | 43 | 0.20.1 | 2 months ago |
| crowdsec | m00nwtchr/homelab-cluster | 39 | 0.20.1 | 7 months ago |
See the most popular values for this chart:
| Key | Types |
|---|---|
container_runtime (6) containerd | string |
config."config.yaml.local" (5) api:
server:
auto_registration:
enabled: true
token: ${REGISTRATION_TOKEN}
allowed_ranges:
- ${POD_CIDR}
db_config:
type: postgresql
user: ${DB_USERNAME}
password: ${DB_PASSWORD}
db_name: ${DB_NAME}
host: ${DB_HOST}
port: 5432 | string |
config."profiles.yaml" (3) name: default_ip_remediation
debug: false
filters:
- Alert.Remediation == true && Alert.GetScope() == "Ip"
decisions:
- type: ban
duration: 24h
# Only locally-generated alerts reach profiles; CAPI blocklist pulls (15k IPs every 2h) do not
notifications:
- alertmanager
on_success: break | string |
config."console.yaml" (2) share_manual_decisions: false
share_custom: true
share_tainted: true
share_context: true
| string |
config.parsers.s01-parse."envoy-logs.yaml" (2) filter: "evt.Parsed.program startsWith 'envoy' && evt.Parsed.message contains ':authority'"
onsuccess: next_stage
name: hydaz/envoy-logs
description: "Parse Envoy access logs to match nginx parser outputs"
statics:
- parsed: json
expression: UnmarshalJSON(evt.Parsed.message, evt.Unmarshaled, "envoy")
- parsed: time_local
expression: evt.Unmarshaled.envoy["start_time"]
- parsed: remote_addr
expression: Split(evt.Unmarshaled.envoy["x-forwarded-for"], ",")[0]
- parsed: verb
expression: evt.Unmarshaled.envoy["method"]
- parsed: request
expression: evt.Unmarshaled.envoy["x-envoy-origin-path"]
- parsed: http_version
expression: TrimPrefix(evt.Unmarshaled.envoy["protocol"], "HTTP/")
# %v not %.0f: the envoy access-log schema is Envoy Gateway's implicit default,
# so a future release emitting these as strings would silently corrupt status
- parsed: status
expression: Sprintf('%v', evt.Unmarshaled.envoy["response_code"])
- parsed: body_bytes_sent
expression: Sprintf('%v', evt.Unmarshaled.envoy["bytes_sent"])
- parsed: http_user_agent
expression: evt.Unmarshaled.envoy["user-agent"]
- parsed: target_fqdn
expression: evt.Unmarshaled.envoy[":authority"]
- meta: service
value: http
- meta: log_type
value: http_access-log
- meta: source_ip
expression: evt.Parsed.remote_addr
- meta: http_status
expression: evt.Parsed.status
- meta: http_path
expression: evt.Parsed.request
- meta: http_verb
expression: evt.Parsed.verb
- meta: http_user_agent
expression: evt.Parsed.http_user_agent
- meta: target_fqdn
expression: evt.Parsed.target_fqdn | string |
config.parsers.s02-enrich."envoy-418-whitelist.yaml" (2) name: hydaz/envoy-418-whitelist
description: "Whitelist 418 responses from the envoy bouncer to prevent processing already banned IPs"
filter: "evt.Meta.service == 'http' && evt.Meta.log_type == 'http_access-log'"
whitelist:
reason: "envoy bouncer response to already banned ips"
expression:
- "evt.Meta.http_status == '418'" | string |
config.parsers.s02-enrich."pseudo-ipv4-whitelist.yaml" (1) name: hydaz/pseudo-ipv4-whitelist
description: "Cloudflare Pseudo IPv4 rewrites IPv6 clients to class E; a ban on one synthetic address blocks every IPv6 client sharing it"
# Dormant guard: Pseudo IPv4 is off as of 2026-09-02 (XFF carries real IPv6).
# While it was on, the cost of this whitelist was that no IPv6 client was policed at all.
filter: "evt.Meta.service == 'http' && evt.Meta.log_type == 'http_access-log'"
whitelist:
reason: "synthetic address, not a real client"
cidr:
- "240.0.0.0/4" | string |
config.parsers.s02-enrich."spa-api-requests.yaml" (1) name: hydaz/spa-api-requests
description: "One Jellyfin home screen is 46 distinct extensionless API calls in 10s; http-crawl-non_statics caps at 40 per 20s and bans the client"
# 2xx only: these endpoints 401 without a token, and enumeration shows up as 4xx for http-probing
filter: "evt.Meta.target_fqdn in ['jellyfin.${SECRET_DOMAIN}', 'jellyseerr.${SECRET_DOMAIN}'] && evt.Meta.http_verb in ['GET', 'HEAD'] && evt.Meta.http_status startsWith '2'"
statics:
- parsed: static_ressource
value: "true" | string |
config.parsers.s02-enrich."wordpress-api-whitelist.yaml" (1) name: hydaz/wordpress-api-whitelist
description: "Whitelist legitimate WordPress API calls"
filter: "evt.Meta.service == 'http' && evt.Meta.log_type == 'http_access-log'"
whitelist:
reason: "legitimate wordpress api call"
expression:
- "evt.Meta.http_path contains '/wp-json/wp/v2/posts' && evt.Meta.http_path contains 'context=edit' && evt.Meta.http_status == '200'" | string |
config."agent_config.yaml.local" (1) api:
client:
unregister_on_exit: true | string |
config."appsec_config.yaml.local" (1) api:
client:
unregister_on_exit: true | string |
config.notifications."alertmanager.yaml" (1) type: http
name: alertmanager
# Alertmanager already groups before anything reaches discord, so no plugin-side
# batching; max_retry stays because a dropped ban notification is a lost signal
max_retry: 3
# Every value goes through toJson: the URL and user-agent are attacker-controlled
format: |
[{{range $i, $a := .}}{{if $i}},{{end}}{
"labels": {
"alertname": "CrowdsecDecision",
"severity": "warning",
"scenario": {{$a.GetScenario | toJson}},
"source_ip": {{$a.Source.IP | toJson}}
},
"annotations": {
"summary": {{$a.GetScenario | toJson}},
"description": "crowdsec issued a ban; client and request per alert below",
"origin": {{if and $a.Source.Cn $a.Source.AsName}}{{printf "%s / %s" $a.Source.Cn $a.Source.AsName | toJson}}{{else}}{{printf "%s%s" $a.Source.Cn $a.Source.AsName | toJson}}{{end}},
"request": {{if $a.Events}}{{$e := index $a.Events 0}}{{printf "%s %s%s %s (%s)" ($e.GetMeta "http_verb") ($e.GetMeta "target_fqdn") ($e.GetMeta "http_path") ($e.GetMeta "http_status") ($e.GetMeta "http_user_agent") | toJson}}{{else}}"none"{{end}}
},
"startsAt": {{$a.StartAt | toJson}}
}{{end}}]
url: http://vmalertmanager-victoria-metrics.observability.svc.cluster.local:9093/api/v2/alerts
method: POST
headers:
Content-Type: application/json | string |
config.notifications."http.yaml" (1) type: http
name: http_victorialogs
log_level: info
# JSON Lines 格式要求每条记录必须是单行
# 字段说明:
# _msg: 消息内容, _time: 时间戳(毫秒), instance: 实例名
# country: 国家, asname: AS名称, asnumber: AS号
# latitude/longitude: 经纬度, iprange: IP范围
# scenario: 场景, type: 类型, duration: 时长, scope: 范围, ip: IP地址
format: |
{{- range $Alert := . -}}
{{- range .Decisions }}
{"_msg":"CrowdSec Decision: {{.Scenario}}","_time":"{{now | unixEpoch}}000","instance":"k8s","country":{{$Alert.Source.Cn | toJson}},"asname":{{$Alert.Source.AsName | toJson}},"asnumber":"{{$Alert.Source.AsNumber}}","latitude":"{{$Alert.Source.Latitude}}","longitude":"{{$Alert.Source.Longitude}}","iprange":{{$Alert.Source.Range | toJson}},"scenario":{{.Scenario | toJson}},"type":{{.Type | toJson}},"duration":{{.Duration | toJson}},"scope":{{.Scope | toJson}},"ip":{{.Value | toJson}}}
{{- end }}
{{- end -}}
url: http://victoria-logs-server.observability.svc.cluster.local:9428/insert/jsonline?_stream_fields=instance,scenario
method: POST
headers:
Content-Type: application/stream+json
| string |
config.notifications."wecom.yaml" (1) type: http
name: http_wecom
log_level: info
format: |
{{- range $Alert := . -}}
{{- range .Decisions }}
{
"msgtype": "markdown",
"markdown": {
"content": "🚨 **CrowdSec 安全告警**\n> **场景**: {{ .Scenario }}\n> **IP**: {{ .Value }}\n> **国家**: {{ $Alert.Source.Cn }}\n> **ASN**: {{ $Alert.Source.AsName }} ({{ $Alert.Source.AsNumber }})\n> **封禁时长**: {{ .Duration }}\n> **类型**: {{ .Type }}"
}
}
{{- end }}
{{- end -}}
url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${WECOM_BOT_TOKEN}
method: POST
headers:
Content-Type: application/json
| string |
config.postoverflows.s01-whitelist."01-whitelist-home.yaml" (1) name: crowdsec/whitelist-home
description: "Whitelist own infrastructure IP ranges"
whitelist:
reason: "Own infrastructure"
cidr:
- "10.0.0.0/16"
- "${CLUSTER_POD_CIDR}"
- "${CLOUD_NODE_V4_CIDR}"
- "${CLOUD_NODE_V6_CIDR}" | string |
lapi.env[].name (5) TZ | string |
lapi.env[].value (4) ${TIMEZONE} | string |
lapi.env[].valueFrom.secretKeyRef.key (2) csLapiSecret | string |
lapi.env[].valueFrom.secretKeyRef.name (2) crowdsec-lapi-secrets | string |
| boolean | |
| boolean | |
| boolean | |
lapi.persistentVolume.config.accessModes[] (1) - ReadWriteOnce | string |
| string | |
| string | |
| string | |
| boolean | |
lapi.persistentVolume.data.accessModes[] (1) - ReadWriteOnce | string |
lapi.persistentVolume.data.existingClaim (1) crowdsec-data | string |
| string | |
lapi.envFrom[].secretRef.name (3) crowdsec-secret | string |
| string | |
| string | |
| string | |
lapi.strategy.type (3) RollingUpdate | string |
| number | |
lapi.service.annotations."lbipam.cilium.io/ips" (2) ${CROWDSEC_LB_IP} | string |
lapi.service.type (2) LoadBalancer | string |
| string | |
| boolean | |
| boolean | |
| string | |
| string | |
lapi.deployAnnotations."secret.reloader.stakater.com/reload" (1) ${SECRET_KEY_NAME},${PSQL_DB_USER}-db-creds | string |
lapi.extraInitContainers[].envFrom[].secretRef.name (1) crowdsec-init-db-secret | string |
lapi.extraInitContainers[].image (1) ghcr.io/home-operations/postgres-init:18@sha256:b6d3af974df781c673d37e49bdddfa14a6f5be28b18d2cb7713f0449bea4057b | string |
| string | |
lapi.podLabels."app.kubernetes.io/name" (1) crowdsec-lapi | string |
lapi.podSecurityContext.seccompProfile.type (1) RuntimeDefault | string |
lapi.priorityClassName (1) services-important | string |
| boolean | |
| string | |
| boolean | |
| boolean | |
| string | |
agent.acquisition[].podName (4) envoy-external-* | string |
| string | |
| boolean | |
agent.env[].name (4) COLLECTIONS | string |
agent.env[].value (4) crowdsecurity/base-http-scenarios crowdsecurity/http-cve | string |
| boolean | |
| boolean | |
| boolean | |
| string | |
| string | |
| string | |
| string | |
| string | |
| number | |
| string | |
| string | |
agent.hostVarLog (1) false | boolean |
| boolean | |
| boolean | |
agent.podSecurityContext.seccompProfile.type (1) RuntimeDefault | string |
agent.priorityClassName (1) services-important | string |
| number | |
| boolean | |
| string | |
| boolean | |
agent.service.annotations."lbipam.cilium.io/ips" (1) ${CROWDSEC_AGENT_LB_IP} | string |
| string | |
| number | |
| string | |
| number | |
agent.service.type (1) LoadBalancer | string |
| number | |
| number | |
agent.strategy.type (1) RollingUpdate | string |
| boolean | |
| string | |
| boolean | |
| string | |
appsec.acquisitions[].listen_addr (4) 0.0.0.0:7422 | string |
| string | |
| string | |
appsec.acquisitions[].appsec_config (3) crowdsecurity/appsec-default | string |
appsec.acquisitions[].appsec_configs[] (1) - crowdsecurity/appsec-default | string |
| boolean | |
appsec.env[].name (4) COLLECTIONS | string |
appsec.env[].value (4) crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules | string |
| boolean | |
| boolean | |
| string | |
| string | |
| string | |
appsec.strategy.type (2) RollingUpdate | string |
appsec.configs."jellyfin-exclusions.yaml" (1) name: local/jellyfin-exclusions
pre_eval:
- filter: IsOutBand == true && req.URL.Path == "/Sessions/Playing/Progress"
apply:
- RemoveOutBandRuleByID(932370)
| string |
| string | |
appsec.podSecurityContext.seccompProfile.type (1) RuntimeDefault | string |
| number | |
| boolean | |
| string | |
| boolean | |
appsec.service.type (1) ClusterIP | string |
| boolean | |
| string | |
| boolean | |
tls.enabled (2) true | boolean |
| string | |
| string | |
| string | |
| string | |
| string | |
| string | |
| string | |
| string | |
| string | |
controllers.crowdsec.containers.app.image.repository (1) docker.io/crowdsecurity/crowdsec | string |
controllers.crowdsec.containers.app.image.tag (1) v1.8.1@sha256:0f2523fa61ef507f15d953045cface490cc880670c62f2755ced17524107f71a | string |
| boolean | |
| boolean | |
| number | |
| string | |
| number | |
| number | |
| number | |
| number | |
| boolean | |
| boolean | |
| number | |
| string | |
| number | |
| number | |
| number | |
| number | |
| string | |
| string | |
| string | |
| boolean | |
| string | |
| boolean | |
| string | |
| boolean | |
| number | |
| string | |
| number | |
| boolean | |
| number | |
| string | |
deploymentAnnotations."secret.reloader.stakater.com/reload" (1) ${SECRET_KEY_NAME},${PSQL_DB_USER}-db-creds | string |
image.pullPolicy (1) IfNotPresent | string |
image.repository (1) ghcr.io/crowdsecurity/crowdsec | string |
persistence.config-local.advancedMounts.crowdsec.app[].path (1) /etc/crowdsec/config.yaml.local | string |
| boolean | |
persistence.config-local.advancedMounts.crowdsec.app[].subPath (1) config.yaml.local | string |
persistence.config-local.name (1) crowdsec-config-local | string |
persistence.config-local.type (1) configMap | string |
persistence.data.globalMounts[].path (1) /var/lib/crowdsec/data | string |
persistence.data.type (1) emptyDir | string |
persistence.etc-crowdsec.globalMounts[].path (1) /etc/crowdsec | string |
| string | |
| string | |
persistence.tmp.type (1) emptyDir | string |
| string | |
persistence.varlog.type (1) emptyDir | string |
secrets.externalSecret.csLapiSecretKey (1) CROWDSEC_LAPI_SECRET | string |
secrets.externalSecret.name (1) crowdsec-secret | string |
secrets.externalSecret.registrationTokenKey (1) REGISTRATION_TOKEN | string |
| string | |
| string | |
service.app.loadBalancerSourceRanges[] (1) - "10.20.0.147/32" | string |
| number | |
| number | |
service.app.type (1) LoadBalancer | string |