Skip to content
DevOps AI ToolKit
All guides
AI for Automation By James Joyner IV · · 9 min read

Grafana Provisioning for DevOps: Documentation First GitOps and CI

Documentation first guide to Grafana provisioning for DevOps engineers. Adopt GitOps and CI validation, design repo layouts, and stop configuration drift.

Grafana Provisioning for DevOps: Documentation First GitOps and CI

Grafana provisioning lets you declare data sources, dashboards, and plugins as YAML files so every change ships through version control instead of a UI click. The moment a resource is under provisioning, it becomes the single source of truth, and Grafana blocks UI edits or deletes on it. Your first move: drop manifests into the provisioning/ directory tree and run them through a CI lint step before they ever touch a running Grafana instance.


TL;DR:

  • Properly set the paths.provisioning in Grafana’s config to ensure the correct directory is scanned for YAML manifests, especially in container or Kubernetes deployments.
  • Always include prune: true in data source manifests cautiously, as it deletes sources missing from the YAML, risking accidental removal.
  • Use consistent UIDs for dashboards and keep version numbers up-to-date to prevent overwriting during restarts in high-availability environments.
  • Separate development and production provisioning paths, and validate manifests with CI linting to prevent configuration errors before deployment.
  • Automate repository management with GitOps practices, staging, and environment-specific paths to maintain reproducibility and avoid drift in large-scale deployments.

Table of Contents

What Is Grafana Provisioning and Where Do the Files Live?

Grafana reads its provisioning configuration from a path set in grafana.ini (or custom.ini), under the paths.provisioning key. Out of the box, that points to conf/provisioning/ on most installs, but you can repoint it anywhere your deployment pipeline expects it, which matters if you’re baking configs into a container image or mounting a ConfigMap in Kubernetes.

Inside that directory, Grafana expects a fixed structure:

  • provisioning/datasources/ for data source YAML manifests
  • provisioning/dashboards/ for dashboard provider definitions (and optionally the dashboard JSON itself)
  • provisioning/plugins/ for app plugin configuration

Each subfolder can hold multiple YAML files, and Grafana scans all of them at startup and on an interval afterward. If you’re running in a locked-down environment, check permitted_provisioning_paths — it restricts which filesystem locations Grafana is allowed to read from, which trips people up when a mounted volume sits outside the allowed path. For credentials, Grafana supports environment variable expansion inside these files using $VAR or ${VAR} syntax, so you never need to hardcode a token directly into a manifest that lives in Git.

How Do You Provision Data Sources With YAML Manifests?

A data source manifest follows a simple skeleton: an apiVersion, then a datasources: list where each entry defines name, type, url, and access. Anything beyond the basics, custom headers, query timeouts, TLS settings, goes into jsonData. Anything sensitive, API keys, passwords, client certificates, goes into secureJsonData, and the values there should reference environment variables rather than sit in plaintext.

apiVersion: 1
datasources:
  - name: Prometheus-Prod
    type: prometheus
    access: proxy
    url: http://prometheus.prod.svc:9090
    isDefault: true
    jsonData:
      timeInterval: "15s"
    secureJsonData:
      httpHeaderValue1: "$PROM_AUTH_TOKEN"
    version: 2

Two fields deserve extra attention. Setting prune: true at the top of the file tells Grafana to delete any provisioned data source that no longer appears in the manifest, which is powerful but unforgiving if someone removes an entry by accident. And the version number on each data source matters more than most teams realize: in a multi-instance or high-availability setup, Grafana uses version numbers to decide which config wins on restart, so an older instance restarting later won’t silently clobber a newer configuration.

Pro Tip: Never commit secureJsonData values directly, even as placeholders. Reference an environment variable every time, and let your secrets manager or CI pipeline inject the real value at deploy time.

How Do Dashboard Providers and Folder Mapping Work?

Dashboard provisioning runs through a separate providers list, and each provider needs a name, a target folder, type: file, and an options.path pointing at the JSON files it should load. From there, three settings shape how dashboards behave once they’re live.

  1. foldersFromFilesStructure tells Grafana to mirror your filesystem’s subfolder layout inside the Grafana UI instead of dumping everything into one flat folder.
  2. updateIntervalSeconds controls how often Grafana rescans the path for changes. The default is 10 seconds, which means most dashboard edits show up without a restart.
  3. allowUiUpdates decides whether someone can tweak a provisioned dashboard in the UI and have that change persist, or whether Grafana overwrites it back to the file version on the next scan.

A few practical notes worth keeping in mind:

  • foldersFromFilesStructure is convenient for onboarding new teams fast, but a messy or unplanned filesystem tree turns into a messy Grafana sidebar. Design the hierarchy before you flip the switch.
  • Every dashboard JSON file should carry a stable UID, not just an auto-generated id. UIDs survive repository migrations and environment promotions, while numeric IDs do not.
  • Leave allowUiUpdates: false in production once a dashboard is stable. It’s the difference between “the file is the truth” and “someone’s Tuesday-afternoon edit is the truth until the next scan.”

Can You Provision Plugins and Apps the Same Way?

Yes, though it’s a smaller surface area. Drop YAML files into provisioning/plugins/ using an apps: list, where each entry references a plugin by its type identifier and carries its own jsonData block for plugin-specific settings like API endpoints or default org assignments.

  • Plugin provisioning enables or configures an already-installed plugin. It doesn’t install the plugin binary itself.
  • Use jsonData for non-sensitive plugin settings and the same secureJsonData pattern for anything that needs to stay out of source control.
  • File-based plugin provisioning can’t replicate every action available in the UI. Some plugin-specific configuration screens still require a manual step the first time, so treat this as a starting point rather than full parity.

File-Based Provisioning vs. Classic Provisioning: What’s the Difference?

Grafana introduced on-prem file provisioning in version 12, and it’s easy to confuse with the classic YAML approach described above. On-prem file provisioning covers dashboards only and connects to a repository or local directory that Grafana syncs continuously. It does not touch data sources, and it isn’t available on Grafana Cloud, so it complements classic provisioning rather than replacing it.

  • Set permitted_provisioning_paths to define exactly which directories or repository connections Grafana can sync from.
  • You can migrate an existing unmanaged dashboard into the provisioned folder as part of adopting this workflow, rather than rebuilding it from scratch.
  • Expect a short synchronization lag between a commit landing and Grafana reflecting it. It’s not instant, so build that into any rollout timing.

What GitOps Practices Keep Provisioning Manageable at Scale?

Treat provisioning changes exactly like application code changes: no direct edits to a running instance, everything through a pull request, everything validated before merge, as explained in What Is User Provisioning? A Guide for IT Teams.

  • Design your repository’s directory tree deliberately before turning on foldersFromFilesStructure — retrofitting folder structure after fifty dashboards exist is painful.
  • Run a YAML/JSON linter and a schema validation step in CI on every pull request, and fail the merge if a manifest is malformed. A tool like Grafonnet can generate valid dashboard JSON programmatically, which cuts down on hand-edited syntax errors.
  • Separate dev and prod provisioning paths, or bake them into separate images, so a bad manifest in staging never has a path to production.
  • Assign UIDs deliberately, keep version numbers current on data sources, and stage rollouts through a lower environment before promoting.

Pro Tip: Wire your provisioning repo into the same pipeline you already use for infrastructure changes. A pattern like Argo CD or Flux applying config on merge turns provisioning into the same reviewable, revertible process as everything else in your stack.

What Do Minimal Manifests and a CI Checklist Look Like?

A minimal working setup needs almost nothing beyond the two file types below, plus a validation gate in your pipeline.

apiVersion: 1
datasources:
  - name: Loki
    type: loki
    url: http://loki:3100
    access: proxy
apiVersion: 1
providers:
  - name: default
    folder: Production
    type: file
    options:
      path: /etc/grafana/provisioning/dashboards/prod
    updateIntervalSeconds: 30
  • Lint every YAML and JSON file with a schema validator before merge.
  • Deploy to a staging Grafana instance first and confirm the dashboards render with the correct UID before promoting.
  • Keep the official provisioning tutorial open as a working reference while you build out your first repository structure.

Provisioning in Real Operations: What Actually Changes

Provisioning’s real payoff shows up months in, not on day one: environments stop drifting apart, and rebuilding a Grafana instance from scratch becomes a repository checkout instead of a memory exercise. The upfront cost is real. You have to design a repo structure and CI validation before you get any of that benefit, and skipping that step just moves the pain to your first production incident instead of removing it.

Teams that treat provisioning like application code, staged rollouts, gated merges, versioned data sources, get the reproducibility without the surprise deletions. Teams that treat it as a one-time YAML dump usually rediscover prune: true the hard way.

— James

Accelerate Your Provisioning Workflow With Ready-Made Assets

Writing every YAML manifest and CI validation step from scratch works, but it’s slow the first time through. Devopsaitoolkit builds downloadable playbooks, validator scripts, and CI examples specifically for engineers automating Grafana, Prometheus, and Kubernetes infrastructure, so you’re adapting a tested pattern instead of debugging your first schema validator at 2 a.m.

Devopsaitoolkit

The toolkit’s provisioning-focused resources cover repository layout templates, staged rollout checklists, and lint configurations you can drop straight into an existing pipeline, alongside prompt packs for troubleshooting the config errors that show up once you’re running this at scale. If your team is also managing Linux hosts, check the Linux Admins AI Prompts library for copy-paste diagnostic prompts that pair well with provisioning debugging work. Browse the full catalog on the AI Workflows for Real Cloud Engineers landing page and see which playbook matches your current provisioning setup.

Newsletter

Free: the DevOps AI Incident-Triage Cheat Sheet

Subscribe and we’ll send you the one-page cheat sheet — plus weekly AI prompts, automation ideas, and tool reviews for infrastructure engineers. One email a week. No spam, unsubscribe anytime.

  • AI Incident-Triage Cheat Sheet (PDF)
  • Access to 2,778 DevOps AI prompts
  • One practical workflow email per week
Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.