Grafana Grafana

Provision Data Sources from YAML

Define data sources, credentials, and custom headers in files instead of the UI.

10 min Beginner

Data sources are the first thing every dashboard and alert rule depends on, so they are the first thing to put in files. Grafana reads YAML from the provisioning/datasources folder at startup, creates the data sources it finds, and updates the ones that already exist.

A basic file

provisioning/datasources/datasources.yaml:

apiVersion: 1

datasources:
  - name: Prometheus
    uid: prometheus
    type: prometheus
    access: proxy
    orgId: 1
    url: http://prometheus:9090
    isDefault: true
    editable: false
    jsonData:
      timeInterval: 15s

You can put one or many data sources in a file, and use several files. Grafana loads everything under the folder.

The fields that matter most:

  • name is the display name.
  • uid is the stable identifier that dashboards and alert rules reference. If you leave it out, Grafana generates one, which makes everything that references it fragile. Always set it.
  • type is the plugin ID, such as prometheus, loki, tempo, postgres, or elasticsearch.
  • access: proxy means Grafana’s server makes the requests. This is the normal choice and keeps credentials out of browsers.
  • isDefault marks the data source new panels start with. Only one should be the default per organization.
  • editable: false blocks changes in the UI, so the file stays authoritative.
  • jsonData holds non-secret settings, and the keys depend on the plugin.
  • secureJsonData holds secrets, which Grafana encrypts in its database.
  • version is compared on updates. With several Grafana instances sharing a database, an instance only updates a data source when the file’s version is the same or higher than the stored one, so bump it when you change a file.

Credentials without committing them

Provisioning files support environment variable interpolation in values (not in keys) with $VAR or ${VAR}. Write $$ for a literal dollar sign:

apiVersion: 1

datasources:
  - name: Postgres
    uid: postgres-main
    type: postgres
    url: $POSTGRES_HOST:5432
    user: $POSTGRES_USER
    editable: false
    jsonData:
      database: app
      sslmode: require
    secureJsonData:
      password: $POSTGRES_PASSWORD

Pass POSTGRES_PASSWORD into the container from your secret store (see the secrets guide). The password never appears in the repository, and Grafana stores it encrypted after loading.

Custom HTTP headers

Header names go in jsonData and their values in secureJsonData, numbered together:

datasources:
  - name: Mimir
    uid: mimir
    type: prometheus
    access: proxy
    url: https://mimir.example.com/prometheus
    jsonData:
      httpHeaderName1: X-Scope-OrgID
    secureJsonData:
      httpHeaderValue1: tenant-a

Basic auth and TLS

datasources:
  - name: Internal Prometheus
    uid: prom-internal
    type: prometheus
    access: proxy
    url: https://prometheus.internal:9090
    basicAuth: true
    basicAuthUser: grafana
    jsonData:
      tlsAuthWithCACert: true
    secureJsonData:
      basicAuthPassword: $PROM_PASSWORD
      tlsCACert: $PROM_CA_CERT

Correlate logs, metrics, and traces

Several plugins link data sources to each other by UID, which is another reason to set UIDs by hand. For example, Loki can turn a log field into a link to traces in Tempo:

datasources:
  - name: Loki
    uid: loki
    type: loki
    access: proxy
    url: http://loki:3100
    jsonData:
      derivedFields:
        - name: TraceID
          matcherRegex: 'trace_id=(\w+)'
          url: '$${__value.raw}'
          datasourceUid: tempo

Plugin-specific jsonData keys vary by version, so confirm them in the data source’s documentation. A quick way to discover them is to configure the data source once in a scratch instance and read the result from the API (GET /api/datasources/uid/<uid>).

Delete and prune

deleteDatasources removes data sources before datasources is processed. Use it when you retire one:

apiVersion: 1

deleteDatasources:
  - name: Old Graphite
    orgId: 1

To make the folder the full truth, add prune: true (Grafana 11.1 or newer). Provisioned data sources that are no longer in any file, or whose file is deleted, are then removed on the next start:

apiVersion: 1
prune: true

datasources:
  - name: Prometheus
    uid: prometheus
    type: prometheus
    url: http://prometheus:9090

Only provisioned data sources are pruned. Ones created by hand in the UI are left alone.

Apply and verify

Data sources are read at startup, so restart Grafana, or call the reload endpoint with admin basic auth:

curl -X POST -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/admin/provisioning/datasources/reload

curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/datasources | jq '.[] | {name, uid, type, readOnly}'

Provisioned data sources report readOnly: true. To confirm connectivity without the UI, use the data source health endpoint:

curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/datasources/uid/prometheus/health

If a data source didn’t load, check Grafana’s startup log for lines from the provisioning logger, which name the file and the error (usually YAML indentation, an unknown field, or a missing environment variable).

Popular Guides