Dashboard Provisioning
Introduction
Dashboard provisioning in Grafana allows you to automatically create and update dashboards from configuration files or external sources. Instead of manually creating dashboards through the UI, you can define them as code, enabling version control, automation, and consistent deployment across multiple Grafana instances.
This approach follows the "Infrastructure as Code" philosophy, where configurations are managed in text files rather than through graphical interfaces. Dashboard provisioning is particularly valuable for:
- Maintaining consistent dashboards across multiple environments (development, staging, production)
- Implementing version control for dashboards
- Automating dashboard deployment as part of CI/CD pipelines
- Scaling Grafana deployments across large organizations
How Dashboard Provisioning Works
Dashboard provisioning in Grafana works through configuration files and folder structures that tell Grafana where and how to find dashboard definitions.
The process typically involves:
- Creating dashboard JSON definitions
- Setting up provisioning configuration files
- Configuring Grafana to read from these sources
- Restarting or reloading Grafana to apply changes
Setting Up Dashboard Provisioning
Step 1: Prepare Your Directory Structure
First, you need to create directories to store your provisioning configurations and dashboard definitions:
# Example directory structure for Grafana provisioning
grafana/
├── provisioning/
│ ├── dashboards/
│ │ ├── default.yaml
│ │ └── team-dashboards.yaml
│ └── datasources/
│ └── datasources.yaml
└── dashboards/
├── system/
│ ├── cpu-metrics.json
│ └── memory-usage.json
└── application/
└── service-monitoring.json
Step 2: Configure Dashboard Providers
Create a YAML configuration file in the provisioning/dashboards/
directory to tell Grafana where to find your dashboard JSON files:
# provisioning/dashboards/default.yaml
apiVersion: 1
providers:
- name: 'Default Dashboards'
orgId: 1
folder: 'System Monitoring'
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: false
options:
path: /etc/grafana/dashboards/system
foldersFromFilesStructure: true
Let's break down this configuration:
name
: A human-readable name for this providerorgId
: The organization ID in Grafana (default is 1)folder
: The folder where these dashboards will appear in the Grafana UItype
: The provider type (usually 'file' for file-based provisioning)disableDeletion
: If true, dashboards removed from files won't be deleted from GrafanaupdateIntervalSeconds
: How often Grafana should check for updatesallowUiUpdates
: If false, provisioned dashboards can't be saved from the UIoptions.path
: The path to dashboard JSON filesfoldersFromFilesStructure
: If true, uses the file system structure to create folders
Step 3: Create Dashboard JSON Files
Save your dashboard definitions as JSON files in the configured path. You can export existing dashboards from the Grafana UI or create them from scratch:
{
"annotations": {
"list": []
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"expr": "100 - (avg by(instance) (irate(node_cpu_seconds_total{mode=\"idle\"}[1m])) * 100)",
"refId": "A"
}
],
"title": "CPU Usage",
"type": "gauge"
}
],
"refresh": "5s",
"schemaVersion": 37,
"style": "dark",
"tags": ["system", "cpu"],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "browser",
"title": "CPU Metrics",
"uid": "cpu-metrics",
"version": 1
}
When exporting dashboards from the Grafana UI, remember to:
- Remove the
id
field or set it tonull
- Update any hardcoded datasource UIDs to use variables like
${DS_PROMETHEUS}
- Set appropriate
uid
values for your dashboard
Step 4: Configure Grafana to Use Provisioning
Make sure your Grafana configuration points to the provisioning directory. In grafana.ini
:
[paths]
provisioning = /etc/grafana/provisioning/
Step 5: Restart or Reload Grafana
After setting up provisioning, restart Grafana or trigger a provisioning reload:
# Option 1: Restart Grafana service
sudo systemctl restart grafana-server
# Option 2: Use Grafana API to reload provisioning (if enabled)
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" http://localhost:3000/api/admin/provisioning/dashboards/reload
Advanced Provisioning Techniques
Using Variables for Environment-Specific Settings
You can use Grafana's templating variables in your dashboard JSON to make them adaptable to different environments:
{
"templating": {
"list": [
{
"current": {
"selected": true,
"text": "Production",
"value": "production"
},
"name": "environment",
"options": [
{
"selected": true,
"text": "Production",
"value": "production"
},
{
"selected": false,
"text": "Staging",
"value": "staging"
},
{
"selected": false,
"text": "Development",
"value": "development"
}
],
"query": "production,staging,development",
"type": "custom"
}
]
}
}
Provisioning from Multiple Sources
You can define multiple providers to load dashboards from different locations:
# provisioning/dashboards/multiple-sources.yaml
apiVersion: 1
providers:
- name: 'System Dashboards'
orgId: 1
folder: 'System'
type: file
disableDeletion: false
updateIntervalSeconds: 30
options:
path: /etc/grafana/dashboards/system
- name: 'Application Dashboards'
orgId: 1
folder: 'Applications'
type: file
disableDeletion: false
updateIntervalSeconds: 30
options:
path: /etc/grafana/dashboards/application
Provisioning from Git
For more advanced scenarios, you can set up a pipeline that pulls dashboard definitions from Git and updates your Grafana provisioning:
#!/bin/bash
# Example script to update dashboards from Git
# Pull the latest changes
cd /opt/grafana-dashboards
git pull
# Copy to Grafana provisioning location
cp -R dashboards/* /etc/grafana/dashboards/
# Reload provisioning (if API is enabled)
curl -X POST -H "Authorization: Bearer ${GRAFANA_API_KEY}" \
http://localhost:3000/api/admin/provisioning/dashboards/reload
Practical Example: Monitoring a Web Application
Let's create a complete example of provisioning a dashboard to monitor a web application:
- First, define the dashboard provider:
# provisioning/dashboards/web-app.yaml
apiVersion: 1
providers:
- name: 'Web Application Monitoring'
orgId: 1
folder: 'Web Apps'
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: true
options:
path: /etc/grafana/dashboards/web-app
- Create the dashboard JSON file:
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_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": "linear",
"lineWidth": 1,
"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
},
{
"color": "red",
"value": 80
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"expr": "sum(rate(http_requests_total{job=\"web-app\"}[5m])) by (status)",
"refId": "A"
}
],
"title": "HTTP Request Rate",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"fieldConfig": {
"defaults": {
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "yellow",
"value": 200
},
{
"color": "red",
"value": 500
}
]
},
"unit": "ms"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 2,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "9.3.6",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"expr": "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{job=\"web-app\"}[5m])) by (le)) * 1000",
"refId": "A"
}
],
"title": "95th Percentile Response Time",
"type": "gauge"
}
],
"refresh": "10s",
"schemaVersion": 37,
"style": "dark",
"tags": [
"web",
"prometheus"
],
"templating": {
"list": []
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Web Application Dashboard",
"uid": "web-app-dashboard",
"version": 1,
"weekStart": ""
}
- Deploy these files to their respective locations and reload Grafana
Best Practices for Dashboard Provisioning
Version Control
Store your dashboard JSON files and provisioning configurations in a version control system like Git:
# Example git workflow
git init
git add provisioning/ dashboards/
git commit -m "Add initial Grafana dashboards"
git push origin main
Validation
Validate your dashboard JSON files before deploying them:
# Using jq to validate JSON
cat dashboards/system/cpu-metrics.json | jq '.' > /dev/null && echo "Valid JSON" || echo "Invalid JSON"
Documentation
Document your dashboards with README files:
# System Monitoring Dashboards
This directory contains dashboards for system monitoring:
- `cpu-metrics.json`: Shows CPU usage across all instances
- `memory-usage.json`: Displays memory consumption and available memory
## Variables
These dashboards use the following variables:
- `$DS_PROMETHEUS`: Prometheus data source name
- `$instance`: Server instance selector
Consistent Naming
Adopt a consistent naming convention for your dashboard UIDs and titles:
[team]-[application]-[metrics-type]
For example:
infra-system-cpu
web-frontend-performance
db-postgres-queries
Troubleshooting Dashboard Provisioning
Common Issues and Solutions
Dashboards Not Appearing
If your dashboards aren't showing up after provisioning:
- Check the Grafana logs:
grep "provisioning" /var/log/grafana/grafana.log
- Verify file permissions:
ls -la /etc/grafana/dashboards/
ls -la /etc/grafana/provisioning/dashboards/
- Validate your YAML configuration:
yamllint provisioning/dashboards/default.yaml
Dashboard JSON Errors
If your dashboard JSON has errors:
- Export a working dashboard from the UI to use as a template
- Compare your JSON structure with the exported version
- Use a JSON validator to check for syntax errors
Changes Not Reflecting
If changes to your JSON files aren't reflected in Grafana:
- Check if
updateIntervalSeconds
is set appropriately - Verify that
allowUiUpdates
is configured correctly - Check if you need to manually reload provisioning
Summary
Dashboard provisioning is a powerful feature in Grafana that allows you to manage dashboards as code. By using provisioning, you can:
- Automate dashboard creation and updates
- Version control your dashboards
- Deploy consistent dashboards across multiple environments
- Integrate dashboard management into your CI/CD pipelines
Key components of dashboard provisioning include:
- Dashboard JSON files that define the dashboard content
- Provider configuration files that tell Grafana where to find dashboards
- Directory structures for organizing dashboards by team or function
By following the steps and best practices outlined in this guide, you can implement an efficient dashboard provisioning workflow that scales with your organization's monitoring needs.
Additional Resources
- Official Grafana Provisioning Documentation
- Grafana Dashboard JSON Model
- Grafana as Code with Terraform
Exercises
- Create a basic dashboard provider configuration file for system monitoring dashboards.
- Export an existing dashboard from your Grafana instance and modify it for provisioning.
- Set up a Git repository to store your dashboard definitions and create a script to deploy changes to Grafana.
- Create a dashboard that uses variables to dynamically change data source based on environment.
- Implement a multi-team dashboard provisioning structure with separate folders for each team.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)