Grafana Grafana

Dashboards as Code: Foundation SDK, Git Sync, and the gcx CLI

Generate dashboards from typed code and sync them with a Git repository from Grafana itself.

15 min Advanced

Writing dashboard JSON by hand doesn’t scale, and exporting it from the UI leaves the UI as the real source. Grafana’s observability-as-code tools address both: the Foundation SDK generates dashboards from typed code, Git Sync has Grafana read and write dashboards in a Git repository, and the gcx CLI pushes and pulls resources from the terminal. Several of these features are recent, and some APIs are marked alpha, so check the documentation for your version.

Generate dashboards with the Foundation SDK

The Foundation SDK provides builders for dashboards, panels, and queries in Go, TypeScript, Python, PHP, and Java. You describe a dashboard in a typed language, and calling build() produces the dashboard JSON. Because it is code, you get compile-time checks, reuse (a function that builds a standard service panel row), and normal code review.

Install it for your language, for example:

# Go
go get github.com/grafana/grafana-foundation-sdk/go@latest

# TypeScript
npm install @grafana/grafana-foundation-sdk

Python, PHP, and Java packages are listed in the SDK documentation. It targets Grafana 10 and newer.

A typical workflow:

  1. Write a small program that defines the dashboards and writes each one’s JSON to dashboards/<name>.json.
  2. Run it in CI.
  3. Commit the generated JSON, or publish it as a build artifact.
  4. Deliver the JSON with whichever mechanism you already use: a provider folder, a ConfigMap, a GrafanaDashboard resource, Terraform, or Git Sync.
# CI job sketch
steps:
  - run: npm ci
  - run: npx tsx dashboards/generate.ts --out dashboards/generated
  - run: git diff --exit-code dashboards/generated   # fail if generated files are stale

The git diff --exit-code check makes sure nobody edits generated JSON by hand and that the code and output stay in step.

Git Sync

Git Sync lets Grafana store dashboards as JSON in a Git repository. Changes flow both ways: an edit in the Grafana UI becomes a commit or a pull request, and a merged change in the repository appears in Grafana. Grafana polls the repository every 60 seconds by default, and a webhook makes updates arrive almost immediately. Git Sync is generally available in Grafana 13 across editions. It supports GitHub (with App authentication), GitHub Enterprise, GitLab, Bitbucket, and plain Git through a “Pure Git” repository type.

You can configure it entirely as code with a Repository resource. Create repository.yaml:

apiVersion: provisioning.grafana.app/v0alpha1
kind: Repository
metadata:
  name: my-repo
spec:
  title: My Repository
  type: github
  github:
    url: https://github.com/<org>/<repo>
    branch: main
    path: grafana/
  sync:
    enabled: true
    intervalSeconds: 60
    target: folder
  workflows:
    - write
    - branch
secure:
  token:
    create: '<git-personal-access-token>'

Field notes:

  • type is one of github, githubEnterprise, gitlab, bitbucket, or git, and each has its own block. Bitbucket and plain Git also need a tokenUser.
  • path is the folder in the repository that Grafana owns.
  • workflows controls what UI saves do: write commits directly to the branch, and branch opens a pull request.
  • sync.target is folder (the default) or folderless.
  • secure.token carries the credential, so it is stored as a secret and not in the spec. Instead of a token you can use a GitHub App or OAuth app connection with spec.connection.name; those need a separate connection.yaml.
  • The API version is v0alpha1, so field names can change between releases.

Apply it with gcx (next section), or through the Grafana UI if you prefer.

What Git Sync is best at: letting UI authors and Git-first engineers share one source of truth, with pull request review on every change. Read the usage limitations page before adopting it for a large instance, since provisioning large numbers of dashboards has performance considerations.

The gcx CLI

gcx is Grafana’s command line for working with resources and, on Grafana Cloud, other products. It works against Grafana Cloud and open source or Enterprise Grafana 12 and later, and it replaces the earlier grafanactl tool (migrating is mostly renaming the command, and grafanactl resources serve becomes gcx dev serve). Install it from the project’s repository and configure a context with your Grafana URL and token, as described in its documentation.

Common commands:

# push local resource files to Grafana
gcx resources push --path ./resources

# list what exists, or inspect one resource
gcx resources get repositories
gcx resources get repository/my-repo -o yaml

# edit or delete
gcx resources edit repository/my-repo
gcx resources delete repository/my-repo

# live-preview dashboards while developing
gcx dev serve

Use it in CI to push resource definitions from the repository, or locally while building dashboards from the SDK.

Choosing between the approaches

SituationReach for
Many similar dashboards, or reusable building blocksFoundation SDK, delivered by any mechanism
Authors work in the UI but you want Git as the recordGit Sync
Kubernetes GitOps, one object per dashboardGrafana Operator
Whole-platform automation including teams and permissionsTerraform
One Grafana, static JSON filesPlain provider folder

They combine well: generate JSON with the SDK, commit it to a repository, and let Git Sync or a provider folder deliver it.

Verify

gcx resources get repositories
curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  "http://localhost:3000/api/search?type=dash-db" | jq '.[] | {title, folderTitle}'

For repository sync issues, check the repository’s status in Grafana (under Administration, then Provisioning) and the Grafana server log. Typical problems are an expired token, a wrong branch or path, and a webhook that can’t reach Grafana.

Popular Guides