Grafana Provisioning
Provisioning lets you configure Grafana entirely through files instead of clicking through the UI. Data sources, dashboards, alert rules, and notification policies are defined in YAML or JSON files on disk. When Grafana starts, it reads these files and applies the configuration automatically. This is the foundation of infrastructure-as-code for your monitoring setup.
The Restaurant Franchise Analogy
A franchise restaurant chain does not rely on each branch manager to memorise the recipes and setup procedures. A central manual documents everything: how the kitchen is arranged, what equipment goes where, and exactly how each dish is prepared. Every new branch opens identically because staff follow the same manual. Grafana provisioning works the same way — your files are the manual, and every new Grafana instance reads them to configure itself identically.
Without provisioning: With provisioning: Install Grafana Install Grafana Log in to UI Copy provisioning files Click: Add data source Restart Grafana Click: Configure Prometheus ↓ Click: Save Everything configured automatically Click: Import dashboard ↓ Click: Configure alerts 100 identical Grafana instances (repeat for every instance) deployed in minutes
Provisioning Directory Structure
The default provisioning directory is /etc/grafana/provisioning/. Each subdirectory handles one type of configuration.
/etc/grafana/provisioning/
├── datasources/
│ └── prometheus.yaml
├── dashboards/
│ └── dashboard-provider.yaml
├── alerting/
│ ├── rules.yaml
│ └── notifications.yaml
└── plugins/
└── plugins.yaml
You can change the base path in /etc/grafana/grafana.ini:
[paths] provisioning = /etc/grafana/provisioning
Provisioning Data Sources
Create a YAML file in the datasources/ directory. Grafana reads all YAML files in this directory on startup (and on live reload).
# /etc/grafana/provisioning/datasources/prometheus.yaml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
access: proxy
isDefault: true
editable: false
jsonData:
scrapeInterval: 15s
httpMethod: POST
- name: Loki
type: loki
url: http://loki:3100
access: proxy
editable: false
jsonData:
derivedFields:
- name: TraceID
matcherRegex: "traceID=(\\w+)"
url: "$${__value.raw}"
datasourceUid: tempo
editable: false
Setting editable: false prevents users from modifying or deleting the provisioned data source through the UI. This is important in production — you want data sources managed through version-controlled files, not by users clicking around in the settings.
deleteDatasources
Add a deleteDatasources block to remove data sources that no longer appear in the provisioning files:
deleteDatasources:
- name: Old MySQL
orgId: 1
Provisioning Dashboards
Dashboard provisioning has two steps: configure a dashboard provider (which tells Grafana where to find dashboard JSON files), and place the dashboard JSON files in that location.
Step 1 – Dashboard Provider Configuration
# /etc/grafana/provisioning/dashboards/dashboard-provider.yaml
apiVersion: 1
providers:
- name: Default
type: file
updateIntervalSeconds: 30
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true
The updateIntervalSeconds: 30 setting tells Grafana to check the directory every 30 seconds for new or changed JSON files. Any dashboard JSON file added to the directory appears in Grafana automatically within 30 seconds — no manual import needed.
The foldersFromFilesStructure: true setting maps subdirectory names to Grafana folder names:
/var/lib/grafana/dashboards/
├── infrastructure/
│ ├── server-health.json → Grafana folder: "infrastructure"
│ └── network.json
└── business/
└── sales-metrics.json → Grafana folder: "business"
Step 2 – Place Dashboard JSON Files
Export your dashboards from the Grafana UI (Share → Export → Download JSON) and place the JSON files in the directory you configured. Grafana loads them automatically.
Provisioned Dashboards Are Read-Only in the UI
Users can view provisioned dashboards but cannot save changes to them through the UI. To modify a provisioned dashboard, edit the JSON file on disk — Grafana detects the change within the updateIntervalSeconds interval and applies it. This enforces the GitOps workflow where all changes go through version control.
Provisioning Alert Rules
Define alert rules in YAML files in the alerting/ directory.
# /etc/grafana/provisioning/alerting/rules.yaml
apiVersion: 1
groups:
- orgId: 1
name: Infrastructure Alerts
folder: Alerts
interval: 1m
rules:
- uid: cpu-high-alert
title: High CPU Usage
condition: C
data:
- refId: A
datasourceUid: prometheus
model:
expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m]))*100)
intervalMs: 1000
maxDataPoints: 43200
- refId: C
datasourceUid: "-100"
model:
type: threshold
conditions:
- evaluator:
params: [90]
type: gt
reducer:
type: last
noDataState: NoData
execErrState: Error
for: 5m
annotations:
summary: CPU usage above 90% on {{ $labels.instance }}
labels:
severity: critical
Provisioning Contact Points and Notification Policies
# /etc/grafana/provisioning/alerting/notifications.yaml
apiVersion: 1
contactPoints:
- orgId: 1
name: Ops Slack
receivers:
- uid: ops-slack-receiver
type: slack
settings:
url: https://hooks.slack.com/services/T.../B.../...
channel: "#alerts"
policies:
- orgId: 1
receiver: Ops Slack
group_by: [alertname, instance]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- receiver: Ops Slack
matchers:
- severity = critical
Grafana Provisioning with Docker Compose
Docker Compose is the most common way to deploy a fully provisioned Grafana stack. Mount the provisioning directory and dashboard files as volumes.
# docker-compose.yml
services:
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- ./provisioning:/etc/grafana/provisioning
- ./dashboards:/var/lib/grafana/dashboards
environment:
- GF_SECURITY_ADMIN_PASSWORD=secret
- GF_AUTH_ANONYMOUS_ENABLED=false
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
Run docker compose up -d and the entire monitoring stack — Grafana pre-loaded with data sources, dashboards, and alerts — starts in one command. New team members get a fully working setup in minutes by cloning the Git repository and running the same command.
Live Reload
Grafana watches provisioning files for changes. Data source changes apply immediately on file save. Dashboard JSON files apply within the configured interval. Alert rules and notification policies apply after a short delay. You do not need to restart Grafana for most provisioning changes to take effect.
