Does anyone know how to create a grafana dashboard with Pangolin and Crowdsec Metrics?
Have you setup crowdsec ports to expose?
Creating a Grafana Dashboard for CrowdSec Metrics
Prerequisites
First, make sure you have:
- Prometheus collecting metrics from CrowdSec
- Grafana installed and configured with your Prometheus data source
- Administrative access to your Grafana instance
Configuring Prometheus for CrowdSec
CrowdSec exposes metrics on port 6060 by default. Make sure your Prometheus configuration includes:
scrape_configs:
- job_name: 'crowdsec'
scrape_interval: 15s
metrics_path: /metrics
static_configs:
- targets: ['172.19.0.5:6060'] #your ip
labels:
instance: crowdsec-main
Creating the CrowdSec Dashboard
Let’s create a comprehensive dashboard that monitors all important CrowdSec metrics. I’ll provide a complete JSON configuration you can import directly.
Dashboard JSON Configuration
In Grafana, go to “Dashboards” → “New” → “Import” and paste the following JSON:
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 22,
"links": [],
"liveNow": false,
"panels": [
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 12,
"panels": [],
"title": "CrowdSec Overview",
"type": "row"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 4,
"x": 0,
"y": 1
},
"id": 2,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(cs_machines)",
"legendFormat": "Machines",
"range": true,
"refId": "A"
}
],
"title": "Active CrowdSec Machines",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 100
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 4,
"x": 4,
"y": 1
},
"id": 4,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(cs_bouncers)",
"legendFormat": "Bouncers",
"range": true,
"refId": "A"
}
],
"title": "Active Bouncers",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 1000
},
{
"color": "red",
"value": 5000
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 4,
"x": 8,
"y": 1
},
"id": 6,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(cs_decisions_total{type=~\"ban|captcha\"})",
"legendFormat": "Active Decisions",
"range": true,
"refId": "A"
}
],
"title": "Active Ban/Captcha Decisions",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "Events processed per second",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 15,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "eventsps"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 12,
"x": 12,
"y": 1
},
"id": 8,
"options": {
"legend": {
"calcs": ["mean", "max"],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_parser_hits_total[5m]))",
"legendFormat": "Parser Hits",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_buckets_created_total[5m]))",
"hide": false,
"legendFormat": "Buckets Created",
"range": true,
"refId": "B"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_buckets_overflowed_total[5m]))",
"hide": false,
"legendFormat": "Buckets Overflowed",
"range": true,
"refId": "C"
}
],
"title": "CrowdSec Processing Rate",
"type": "timeseries"
},
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 7
},
"id": 14,
"panels": [],
"title": "Alerts & Decisions",
"type": "row"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "Alerts",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 20,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "normal"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 8
},
"id": 16,
"options": {
"legend": {
"calcs": ["sum"],
"displayMode": "table",
"placement": "right",
"showLegend": true,
"sortBy": "Total",
"sortDesc": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(increase(cs_alert_dispatched_total[5m])) by (scenario)",
"legendFormat": "{{scenario}}",
"range": true,
"refId": "A"
}
],
"title": "Alerts by Scenario (5m)",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "Decisions",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 20,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "normal"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"id": 18,
"options": {
"legend": {
"calcs": ["sum"],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(increase(cs_decisions_new_total[5m])) by (type, origin)",
"legendFormat": "{{type}} ({{origin}})",
"range": true,
"refId": "A"
}
],
"title": "New Decisions by Type & Origin (5m)",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 1
},
{
"color": "red",
"value": 5
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 16
},
"id": 20,
"options": {
"displayMode": "gradient",
"minVizHeight": 10,
"minVizWidth": 0,
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showUnfilled": true,
"text": {}
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "topk(20, sum(cs_decisions_total{type=\"ban\"}) by (value, reason))",
"legendFormat": "{{value}} - {{reason}}",
"range": true,
"refId": "A"
}
],
"title": "Top 20 Banned IPs with Reason",
"type": "bargauge"
},
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 24
},
"id": 22,
"panels": [],
"title": "Detailed Metrics",
"type": "row"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "reqps"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 25
},
"id": 24,
"options": {
"legend": {
"calcs": ["mean", "max"],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_lapi_route_requests_total[5m])) by (method, path)",
"legendFormat": "{{method}} {{path}}",
"range": true,
"refId": "A"
}
],
"title": "Local API Request Rate",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "ms"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 25
},
"id": 26,
"options": {
"legend": {
"calcs": ["mean", "max", "p95"],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_lapi_route_request_duration_seconds_sum[5m])) by (path) * 1000 / sum(rate(cs_lapi_route_request_duration_seconds_count[5m])) by (path)",
"legendFormat": "Avg - {{path}}",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "histogram_quantile(0.95, sum(rate(cs_lapi_route_request_duration_seconds_bucket[5m])) by (path, le)) * 1000",
"hide": false,
"legendFormat": "p95 - {{path}}",
"range": true,
"refId": "B"
}
],
"title": "Local API Response Time",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 20
},
{
"color": "red",
"value": 50
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 8,
"x": 0,
"y": 33
},
"id": 28,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "100 * (node_memory_MemTotal_bytes{instance=~\"crowdsec.*\"} - node_memory_MemAvailable_bytes{instance=~\"crowdsec.*\"}) / node_memory_MemTotal_bytes{instance=~\"crowdsec.*\"}",
"legendFormat": "Memory Usage",
"range": true,
"refId": "A"
}
],
"title": "CrowdSec Memory Usage",
"type": "gauge"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 60
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 8,
"x": 8,
"y": 33
},
"id": 30,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "100 - (avg by(instance) (irate(node_cpu_seconds_total{mode=\"idle\",instance=~\"crowdsec.*\"}[5m])) * 100)",
"legendFormat": "CPU Usage",
"range": true,
"refId": "A"
}
],
"title": "CrowdSec CPU Usage",
"type": "gauge"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 70
},
{
"color": "red",
"value": 90
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 8,
"x": 16,
"y": 33
},
"id": 32,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "100 * node_filesystem_used_bytes{instance=~\"crowdsec.*\",mountpoint=\"/\"} / node_filesystem_size_bytes{instance=~\"crowdsec.*\",mountpoint=\"/\"}",
"legendFormat": "Disk Usage",
"range": true,
"refId": "A"
}
],
"title": "CrowdSec Disk Usage",
"type": "gauge"
},
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 41
},
"id": 34,
"panels": [],
"title": "Bouncer Activity",
"type": "row"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "reqps"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 42
},
"id": 36,
"options": {
"legend": {
"calcs": ["mean", "max"],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_bouncer_requests_total[5m])) by (name)",
"legendFormat": "{{name}}",
"range": true,
"refId": "A"
}
],
"title": "Bouncer Request Rate",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "ms"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 42
},
"id": 38,
"options": {
"legend": {
"calcs": ["mean", "max", "p95"],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_bouncer_request_duration_seconds_sum[5m])) by (name) * 1000 / sum(rate(cs_bouncer_request_duration_seconds_count[5m])) by (name)",
"legendFormat": "Avg - {{name}}",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "histogram_quantile(0.95, sum(rate(cs_bouncer_request_duration_seconds_bucket[5m])) by (name, le)) * 1000",
"hide": false,
"legendFormat": "p95 - {{name}}",
"range": true,
"refId": "B"
}
],
"title": "Bouncer Response Time",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 5
},
{
"color": "red",
"value": 20
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 50
},
"id": 40,
"options": {
"displayMode": "gradient",
"minVizHeight": 10,
"minVizWidth": 0,
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showUnfilled": true,
"text": {}
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "topk(15, sum(increase(cs_bouncer_request_error_total[24h])) by (name, error))",
"legendFormat": "{{name}} - {{error}}",
"range": true,
"refId": "A"
}
],
"title": "Bouncer Errors (24h)",
"type": "bargauge"
}
],
"refresh": "10s",
"schemaVersion": 37,
"style": "dark",
"tags": ["crowdsec", "security"],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "CrowdSec Security Monitoring",
"uid": "crowdsec-monitoring",
"version": 1,
"weekStart": ""
}
Let me continue with the Grafana dashboard configuration for CrowdSec:
```json
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_bouncer_requests_total[5m])) by (name)",
"legendFormat": "{{name}}",
"range": true,
"refId": "A"
}
],
"title": "Bouncer Request Rate",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "ms"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 42
},
"id": 38,
"options": {
"legend": {
"calcs": ["mean", "max", "p95"],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(cs_bouncer_request_duration_seconds_sum[5m])) by (name) * 1000 / sum(rate(cs_bouncer_request_duration_seconds_count[5m])) by (name)",
"legendFormat": "Avg - {{name}}",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "histogram_quantile(0.95, sum(rate(cs_bouncer_request_duration_seconds_bucket[5m])) by (name, le)) * 1000",
"hide": false,
"legendFormat": "p95 - {{name}}",
"range": true,
"refId": "B"
}
],
"title": "Bouncer Response Time",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 5
},
{
"color": "red",
"value": 20
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 50
},
"id": 40,
"options": {
"displayMode": "gradient",
"minVizHeight": 10,
"minVizWidth": 0,
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showUnfilled": true,
"text": {}
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "topk(15, sum(increase(cs_bouncer_request_error_total[24h])) by (name, error))",
"legendFormat": "{{name}} - {{error}}",
"range": true,
"refId": "A"
}
],
"title": "Bouncer Errors (24h)",
"type": "bargauge"
}
],
"refresh": "10s",
"schemaVersion": 37,
"style": "dark",
"tags": ["crowdsec", "security"],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "CrowdSec Security Monitoring",
"uid": "crowdsec-monitoring",
"version": 1,
"weekStart": ""
}
Understanding the Dashboard Components
Now that you have imported the dashboard, let me explain each section in detail so you fully understand what metrics are being monitored and why they’re important.
1. CrowdSec Overview Section
This section provides a view of your CrowdSec ecosystem:
Active CrowdSec Machines
- Shows how many CrowdSec instances are reporting to the central LAPI
- Useful for ensuring all your security nodes are properly connected
- A sudden drop could indicate network issues or service failures
Active Bouncers
- Displays the number of connected bouncers (like the Traefik bouncer)
- Bouncers are the components that actually enforce decisions
- Important to monitor as they implement your security policies
Active Ban/Captcha Decisions
- Shows the current count of active enforcement actions
- Helps you understand your security posture at a glance
- Spikes may indicate ongoing attacks
CrowdSec Processing Rate
- Tracks three key metrics:
- Parser hits: How many log lines are matching patterns
- Buckets created: When suspicious activity is detected
- Buckets overflowed: When thresholds are exceeded, triggering alerts
- The relationship between these metrics helps identify attack patterns and processing efficiency
2. Alerts & Decisions Section
This section focuses on the security events CrowdSec is detecting:
Alerts by Scenario
- Shows which attack patterns are being detected
- Stacked area chart reveals trends and proportions
- Useful for understanding what types of threats you’re facing
New Decisions by Type & Origin
- Tracks enforcement actions by their type (ban, captcha) and source
- Helps determine if decisions are local or from the CrowdSec community
- Reveals how your security posture changes over time
Top 20 Banned IPs with Reason
- Horizontal bar gauge showing most frequently banned addresses
- Includes the security reason for each ban
- Excellent for identifying persistent attackers and attack patterns
3. Detailed Metrics Section
This section provides deeper insights into CrowdSec’s internal operations:
Local API Request Rate
- Shows traffic to CrowdSec’s Local API by endpoint
- Helps identify which components are most active
- Useful for capacity planning and identifying unusual patterns
Local API Response Time
- Tracks average and 95th percentile response times
- Critical for ensuring CrowdSec remains responsive
- Slowdowns could indicate performance issues or resource constraints
Resource Usage Gauges
- Memory Usage: Shows RAM consumption percentage
- CPU Usage: Monitors processor utilization
- Disk Usage: Tracks storage consumption
- Essential for ensuring CrowdSec has adequate resources
4. Bouncer Activity Section
This section focuses on the components that enforce security decisions:
Bouncer Request Rate
- Shows how frequently bouncers check for new decisions
- Split by bouncer name to track individual components
- Higher rates indicate more active security enforcement
Bouncer Response Time
- Monitors how quickly the API responds to bouncers
- Shows average and 95th percentile latency
- Critical for ensuring real-time protection
Bouncer Errors
- Displays error counts by bouncer and error type
- Helps identify configuration or connectivity issues
- Important for maintaining reliable security enforcement
Customizing Your Dashboard
You may want to customize this dashboard based on your specific CrowdSec deployment. Here are some suggestions:
-
Add Variables: Create dashboard variables for instance names, bouncer types, or time ranges to make the dashboard more flexible.
-
Alert Thresholds: Set up Grafana alerts for critical metrics like:
- CrowdSec service availability
- Bouncer connectivity
- Excessive ban rates
- API response time degradation
-
Additional Panels: Consider adding:
- Geographic visualizations of attack sources
- Correlation with system logs
- Network traffic analysis
- Custom metrics from your bouncers
Troubleshooting Common Issues
If some metrics aren’t appearing correctly, check the following:
-
Metric Availability: Ensure CrowdSec’s metrics endpoint is accessible from Prometheus. Try:
curl http://172.19.0.5:6060/metrics -
Naming Conventions: The dashboard assumes standard metric names. If you’ve customized CrowdSec, you might need to adjust queries.
-
Version Compatibility: This dashboard is designed for CrowdSec v1.3.0+. Earlier versions may use different metric names.
-
Data Retention: Ensure your Prometheus retention period is sufficient for the time ranges in the dashboard.
is it possible to use the grafana cloud instance for that? i dont have grafana installed yet
No. It’s for local. This a direct copy of mine. But surely you can try. No harm. You will have to point appropriate domain to various ports.
my pangolin is on a vps in a datacenter and connected with tailscale.
Is it possible to use the tailscale ip to connect the prometheus over the internet to get the crowdsec metrics?
Can You make Full Tutorial ?
Okay I will with detailed steps. But by next weekend.
Guide Updated–
Detailed Guide: Creating a Grafana Dashboard for CrowdSec Metrics in Pangolin Stack- Part 1
ok i got it with grafana cloud but your json dashboard isnt working Not valid JSON
i have 3 docker instances:
Grafana Private Datasources
Node-Exporter
Prometheus with basic AUTH for security
Once I get to my desk will check. I will be available after Wednesday.