<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Grafana Terraform provider on Grafana Labs</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/</link><description>Recent content in Grafana Terraform provider on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/index.xml" rel="self" type="application/rss+xml"/><item><title>Create and manage a Grafana Cloud stack using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-cloud-stack/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-cloud-stack/</guid><content><![CDATA[&lt;h1 id=&#34;create-and-manage-a-grafana-cloud-stack-using-terraform&#34;&gt;Create and manage a Grafana Cloud stack using Terraform&lt;/h1&gt;
&lt;p&gt;Learn how to add a data source, a dashboard, and a folder to a Grafana Cloud stack using Terraform.&lt;/p&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account, as shown in &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/downloads&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;All of the following Terraform configuration files should be saved in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;create-a-cloud-stack&#34;&gt;Create a Cloud stack&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a Terraform configuration file.&lt;/p&gt;
&lt;p&gt;This Terraform configuration will create a Grafana Cloud stack and a second token needed for your Grafana instance.&lt;/p&gt;
&lt;p&gt;Create a file named &lt;code&gt;cloud-stack.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
      version = &amp;#34;&amp;gt;= 2.9.0&amp;#34;
    }
  }
}
// Step 1: Create a stack
provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;cloud&amp;#34;
  cloud_access_policy_token = &amp;#34;&amp;lt;cloud-access-token&amp;gt;&amp;#34;
}


resource &amp;#34;grafana_cloud_stack&amp;#34; &amp;#34;my_stack&amp;#34; {
  provider = grafana.cloud

  name               = &amp;#34;&amp;lt;stack-name&amp;gt;&amp;#34;
  slug               = &amp;#34;&amp;lt;stack-name&amp;gt;&amp;#34;
  region_slug        = &amp;#34;&amp;lt;region&amp;gt;&amp;#34; # Example &amp;#34;us&amp;#34;,&amp;#34;eu&amp;#34; etc
  delete_protection  = true
}

// Step 2: Create a service account and key for the stack
resource &amp;#34;grafana_cloud_stack_service_account&amp;#34; &amp;#34;cloud_sa&amp;#34; {
  provider   = grafana.cloud
  stack_slug = grafana_cloud_stack.my_stack.slug

  name        = &amp;#34;&amp;lt;service-account-name&amp;gt;&amp;#34;
  role        = &amp;#34;Admin&amp;#34;
  is_disabled = false
}

resource &amp;#34;grafana_cloud_stack_service_account_token&amp;#34; &amp;#34;cloud_sa&amp;#34; {
  provider   = grafana.cloud
  stack_slug = grafana_cloud_stack.my_stack.slug

  name               = &amp;#34;terraform serviceaccount key&amp;#34;
  service_account_id = grafana_cloud_stack_service_account.cloud_sa.id
}

// Step 3: Create resources within the stack
provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;my_stack&amp;#34;

  url  = grafana_cloud_stack.my_stack.url
  auth = grafana_cloud_stack_service_account_token.cloud_sa.key
}
resource &amp;#34;grafana_folder&amp;#34; &amp;#34;my_folder&amp;#34; {
  provider = grafana.my_stack

  title = &amp;#34;Test Folder&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;cloud-access-token&amp;gt;&lt;/code&gt; with your Grafana Cloud Access Policy Token.
To create a new one, refer to &lt;a href=&#34;/docs/grafana-cloud/account-management/authentication-and-permissions/access-policies/&#34;&gt;Grafana Cloud Access Policies&lt;/a&gt;.
Add all stacks to the realms list.
The scopes needed for the example are:
&lt;ul&gt;
&lt;li&gt;dashboards:read&lt;/li&gt;
&lt;li&gt;orgs:read&lt;/li&gt;
&lt;li&gt;stack-dashboards:read&lt;/li&gt;
&lt;li&gt;stacks:read&lt;/li&gt;
&lt;li&gt;dashboards:write&lt;/li&gt;
&lt;li&gt;orgs:write&lt;/li&gt;
&lt;li&gt;stack-dashboards:write&lt;/li&gt;
&lt;li&gt;stacks:write&lt;/li&gt;
&lt;li&gt;stack-service-accounts:write&lt;/li&gt;
&lt;li&gt;dashboards:delete&lt;/li&gt;
&lt;li&gt;stack-dashboards:delete&lt;/li&gt;
&lt;li&gt;stacks:delete&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;stack-name&amp;gt;&lt;/code&gt; with the name of your stack.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;region&amp;gt;&lt;/code&gt; with the region in which you want to create the stack. For example &lt;code&gt;us&lt;/code&gt;, &lt;code&gt;eu&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;service-account-name&amp;gt;&lt;/code&gt; with a name for the serviceaccount that will be created to use for operations within the stack/instance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first provider block, &lt;code&gt;grafana.cloud&lt;/code&gt;, uses the Cloud Access Policy Token from the Cloud Portal and is referenced as a parameter when creating the Cloud stack and the token in the Grafana instance to provide the necessary authentication.&lt;/p&gt;
&lt;p&gt;The second provider block, &lt;code&gt;grafana.my_stack&lt;/code&gt;, is referenced as a parameter when creating resources inside the Grafana instance.&lt;/p&gt;
&lt;h2 id=&#34;add-a-data-source&#34;&gt;Add a data source&lt;/h2&gt;
&lt;p&gt;This guide uses the InfluxDB data source. The required arguments for &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/data_source&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;grafana_data_source (Resource)&lt;/a&gt; vary depending on the type of data source you select.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;datasource.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_data_source&amp;#34; &amp;#34;&amp;lt;data-source-name&amp;gt;&amp;#34; {
  provider = grafana.my_stack

  type          = &amp;#34;influxdb&amp;#34;
  name          = &amp;#34;&amp;lt;data-source-name&amp;gt;&amp;#34;
  url           = &amp;#34;&amp;lt;data-source-url&amp;gt;&amp;#34;
  username      = &amp;#34;&amp;lt;username&amp;gt;&amp;#34;
  password      = &amp;#34;&amp;lt;password&amp;gt;&amp;#34;
  database_name = &amp;#34;&amp;lt;db-name&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;data-source-name&amp;gt;&lt;/code&gt; with the name of the data source to be added in Grafana.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;data-source-url&amp;gt;&lt;/code&gt; with URL of your data source.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; with the username for authenticating with your data source.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;password&amp;gt;&lt;/code&gt; with password for authenticating with your data source.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;db-name&amp;gt;&lt;/code&gt; with name of your database.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;add-a-folder&#34;&gt;Add a folder&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates a folder in your Grafana instance using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/folder&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;grafana_folder (Resource)&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;folder.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_folder&amp;#34; &amp;#34;&amp;lt;folder-name&amp;gt;&amp;#34; {
  provider = grafana.my_stack

  title = &amp;#34;&amp;lt;folder-name&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field value:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;folder-name&amp;gt;&lt;/code&gt; with a name for the folder.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;add-a-dashboard-to-the-folder&#34;&gt;Add a dashboard to the folder&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates a dashboard inside the folder created above in your Grafana instance using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/dashboard&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;grafana_dashboard (Resource)&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;dashboard.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Using a JSON file
resource &amp;#34;grafana_dashboard&amp;#34; &amp;#34;dashboard&amp;#34; {
  provider = grafana.my_stack

  config_json = file(&amp;#34;&amp;lt;file-name&amp;gt;.json&amp;#34;)
  folder = grafana_folder.&amp;lt;folder-name&amp;gt;.id
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field value:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;file-name&amp;gt;&lt;/code&gt; with the name of the JSON file that has the source code for the dashboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The dashboard is represented by its JSON source code and referenced in the &lt;code&gt;config_json&lt;/code&gt; parameter.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;apply-the-terraform-configuration&#34;&gt;Apply the Terraform configuration&lt;/h2&gt;
&lt;p&gt;In a terminal, run the following commands from the directory where all of the configuration files are located.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Initialize a working directory containing Terraform configuration files.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform init&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Preview the changes that Terraform will make.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform plan&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply the configuration files.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform apply&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;Once you apply the changes in the Terraform configurations, you should be able to verify the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The new Grafana stack is created and visible in the Cloud Portal&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/static/img/docs/grafana-cloud/terraform/cloud_portal_tf.png&#34;
  alt=&#34;Cloud Portal&#34; width=&#34;1376&#34;
     height=&#34;816&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A service account key token is added in your Grafana instance. In the following image, the service account key token named &amp;ldquo;terraform serviceaccount key&amp;rdquo; was added by the &lt;a href=&#34;#create-a-cloud-stack&#34;&gt;grafana_cloud_stack_service_account_token (Resource)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/screenshot-api_key_tf.png&#34;
  alt=&#34;API Key&#34; width=&#34;2444&#34;
     height=&#34;916&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A new data source (InfluxDB in this example) is visible in the grafana instance.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/screenshot-influxdb_datasource_tf.png&#34;
  alt=&#34;InfluxDB data source&#34; width=&#34;1440&#34;
     height=&#34;764&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A new folder in Grafana. In the following image, a folder named &amp;ldquo;Demos&amp;rdquo; was added by the &lt;a href=&#34;./#add-a-folder&#34;&gt;grafana_folder (Resource)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/screenshot-folder_tf.png&#34;
  alt=&#34;Folder&#34; width=&#34;2436&#34;
     height=&#34;694&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A new dashboard in the Grafana instance. In the following image a dashboard named &amp;ldquo;InfluxDB Cloud Demos&amp;rdquo; was created inside the &amp;ldquo;Demos&amp;rdquo; folder.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/static/img/docs/grafana-cloud/terraform/influxdb_dashboard_tf.png&#34;
  alt=&#34;InfluxDB dashboard&#34; width=&#34;1855&#34;
     height=&#34;895&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you created a Grafana Cloud stack along with a data source, folder, and dashboard imported from a JSON file using Terraform.&lt;/p&gt;
&lt;p&gt;To learn more about managing Grafana Cloud using Terraform, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="create-and-manage-a-grafana-cloud-stack-using-terraform">Create and manage a Grafana Cloud stack using Terraform&lt;/h1>
&lt;p>Learn how to add a data source, a dashboard, and a folder to a Grafana Cloud stack using Terraform.&lt;/p></description></item><item><title>Create and manage dashboards using Terraform and GitHub Actions</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/dashboards-github-action/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/dashboards-github-action/</guid><content><![CDATA[&lt;h1 id=&#34;create-and-manage-dashboards-using-terraform-and-github-actions&#34;&gt;Create and manage dashboards using Terraform and GitHub Actions&lt;/h1&gt;
&lt;p&gt;Learn how to create and manage multiple dashboards represented as JSON source code for Grafana using Terraform and GitHub Actions.&lt;/p&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account, as shown in &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A &lt;a href=&#34;https://github.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;GitHub&lt;/a&gt; repository&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;add-dashboards-to-a-github-repository&#34;&gt;Add dashboards to a GitHub repository&lt;/h2&gt;
&lt;p&gt;This guide shows you how to add dashboards for ElasticSearch, InfluxDB, and AWS EC2. You can use different dashboards according to your configured data sources.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In your GitHub repository, create a folder named &lt;code&gt;dashboards&lt;/code&gt; in the root directory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;code&gt;dashboards&lt;/code&gt; folder create three sub-folders. For this guide, we will create three sub-folders named &lt;code&gt;elasticsearch&lt;/code&gt;, &lt;code&gt;influxdb&lt;/code&gt;, and &lt;code&gt;aws&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add dashboard JSON source code to each of the three sub-folders.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;terraform-configuration-for-grafana-provider&#34;&gt;Terraform configuration for Grafana provider&lt;/h2&gt;
&lt;p&gt;This Terraform configuration configures the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; to provide necessary authentication when creating folders and dashboards in the Grafana instance.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a service account and token in the Grafana instance by following these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/account-management/authentication-and-permissions/service-accounts/#create-a-service-account-in-grafana&#34;&gt;Create a service account in Grafana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/account-management/authentication-and-permissions/service-accounts/#add-a-token-to-a-service-account-in-grafana&#34;&gt;Add a token to a service account&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;main.tf&lt;/code&gt; in the Git root directory and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
   required_providers {
      grafana = {
         source  = &amp;#34;grafana/grafana&amp;#34;
         version = &amp;#34;&amp;gt;= 2.9.0&amp;#34;
      }
   }
}

provider &amp;#34;grafana&amp;#34; {
   alias = &amp;#34;cloud&amp;#34;

   url   = &amp;#34;&amp;lt;Grafana-instance-url&amp;gt;&amp;#34;
   auth  = &amp;#34;&amp;lt;Grafana-Service-Account-token&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Grafana-instance-url&amp;gt;&lt;/code&gt; with the URL of your Grafana instance, for example &lt;code&gt;&amp;quot;https://my-stack.grafana.net/&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Grafana-Service-Account-token&amp;gt;&lt;/code&gt; with a Service Account token from the Grafana instance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;terraform-configuration-for-folders&#34;&gt;Terraform configuration for folders&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates three folders named &lt;code&gt;ElasticSearch&lt;/code&gt;, &lt;code&gt;InfluxDB&lt;/code&gt; and &lt;code&gt;AWS&lt;/code&gt; in the Grafana instance using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/folder&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;grafana_folder (Resource)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Create a file named &lt;code&gt;folders.tf&lt;/code&gt; in the Git root directory and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_folder&amp;#34; &amp;#34;ElasticSearch&amp;#34; {
  provider = grafana.cloud

  title = &amp;#34;ElasticSearch&amp;#34;
}

resource &amp;#34;grafana_folder&amp;#34; &amp;#34;InfluxDB&amp;#34; {
  provider = grafana.cloud

  title = &amp;#34;InfluxDB&amp;#34;
}

resource &amp;#34;grafana_folder&amp;#34; &amp;#34;AWS&amp;#34; {
  provider = grafana.cloud

  title = &amp;#34;AWS&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;terraform-configuration-for-dashboards&#34;&gt;Terraform configuration for dashboards&lt;/h2&gt;
&lt;p&gt;This Terraform configuration iterates through the JSON files in the three folders (&lt;code&gt;elasticsearch&lt;/code&gt;, &lt;code&gt;influxdb&lt;/code&gt; and &lt;code&gt;aws&lt;/code&gt;) you created in the GitHub repository and adds them to the respective folders in the Grafana instance using a Grafana dashboard resource. Available resources include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/dashboard&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_dashboard&lt;/code&gt; (Resource)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For Kubernetes-style dashboards in Grafana v13 or later, use the appropriate resource depending on your dashboard&amp;rsquo;s Kubernetes version. Refer to &lt;a href=&#34;https://github.com/grafana/terraform-provider-grafana/blob/main/docs/resources&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana resources&lt;/a&gt; for details on the available resources, such as &lt;code&gt;grafana_apps_dashboard_dashboard_v1beta1&lt;/code&gt;, &lt;code&gt;grafana_apps_dashboard_dashboard_v1&lt;/code&gt;, or &lt;code&gt;grafana_apps_dashboard_dashboard_v2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, the dashboard represented as JSON source code in the &lt;code&gt;elasticsearch&lt;/code&gt; folder in the GitHub repository will be created in the &lt;code&gt;ElasticSearch&lt;/code&gt; folder in the Grafana instance.&lt;/p&gt;
&lt;p&gt;Create a file named &lt;code&gt;dashboards.tf&lt;/code&gt; in the Git root directory and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_dashboard&amp;#34; &amp;#34;elasticsearch&amp;#34; {
  provider = grafana.cloud

  for_each    = fileset(&amp;#34;${path.module}/dashboards/elasticsearch&amp;#34;, &amp;#34;*.json&amp;#34;)
  config_json = file(&amp;#34;${path.module}/dashboards/elasticsearch/${each.key}&amp;#34;)
  folder      = grafana_folder.ElasticSearch.id
}

resource &amp;#34;grafana_dashboard&amp;#34; &amp;#34;influxdb&amp;#34; {
  provider = grafana.cloud

  for_each    = fileset(&amp;#34;${path.module}/dashboards/influxdb&amp;#34;, &amp;#34;*.json&amp;#34;)
  config_json = file(&amp;#34;${path.module}/dashboards/influxdb/${each.key}&amp;#34;)
  folder      = grafana_folder.InfluxDB.id
}

resource &amp;#34;grafana_dashboard&amp;#34; &amp;#34;aws&amp;#34; {
  provider = grafana.cloud

  for_each    = fileset(&amp;#34;${path.module}/dashboards/aws&amp;#34;, &amp;#34;*.json&amp;#34;)
  config_json = file(&amp;#34;${path.module}/dashboards/aws/${each.key}&amp;#34;)
  folder      = grafana_folder.AWS.id
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;github-workflow-for-managing-dashboards-using-terraform&#34;&gt;GitHub workflow for managing dashboards using Terraform&lt;/h2&gt;
&lt;p&gt;This GitHub workflow consists of the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using the &lt;a href=&#34;https://github.com/actions/checkout&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;actions/checkout@v3&lt;/a&gt; action, The GitHub repository is checked out so that the GitHub workflow can access it.&lt;/li&gt;
&lt;li&gt;The Terraform CLI is installed on the GitHub runner using the &lt;a href=&#34;https://github.com/hashicorp/setup-terraform&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;hashicorp/setup-terraform@v1&lt;/a&gt; action.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform init&lt;/code&gt; is run as a bash command in the GitHub runner to initialize a working directory containing Terraform configuration files.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform fmt -check&lt;/code&gt; is run as a bash command in the GitHub runner to check if the Terraform configuration files are properly formatted. If the Terraform configuration files are not properly formatted, the workflow will fail at this step.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform plan&lt;/code&gt; is run as a bash command in the GitHub runner to preview the changes that Terraform will make.&lt;/li&gt;
&lt;li&gt;Using &lt;a href=&#34;https://github.com/mshick/add-pr-comment&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;mshick/add-pr-comment@v1&lt;/a&gt; action, the preview from Terraform plan is posted as a comment on the pull request. This helps in reviewing the changes that Terraform will make before the pull request is merged.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform apply -auto-approve&lt;/code&gt; is run as a bash command in the GitHub runner to apply the Terraform configuration files. &lt;code&gt;-auto-approve&lt;/code&gt; flag is added to the command to skip interactive approval of plan before applying and make the workflow automated.
This step is run only when changes are committed to &lt;code&gt;main&lt;/code&gt; branch. When a pull request is merged, the merge action creates a commit to the &lt;code&gt;main&lt;/code&gt; branch which triggers the &lt;code&gt;terraform apply -auto-approve&lt;/code&gt; step to execute.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In your GitHub repository, create a folder named &lt;code&gt;.github&lt;/code&gt; in the root directory .&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;code&gt;.github&lt;/code&gt; folder create a sub-folder named &lt;code&gt;workflows&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To add the GitHub workflow to your GitHub repository, create a file named &lt;code&gt;terraform.yml&lt;/code&gt; in the &lt;code&gt;workflows&lt;/code&gt; directory and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Terraform

on:
  push:
    branches:
      - &amp;#39;main&amp;#39;
  pull_request:

jobs:
  terraform:
    runs-on: ubuntu-latest

    steps:
      # Checkout the repository to the GitHub Actions runner
      - name: Checkout
        uses: actions/checkout@v3

      # Install the latest version of Terraform CLI
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v1

      # Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
      - name: Terraform Init
        run: terraform init

      # Checks that all Terraform configuration files adhere to a canonical format
      - name: Terraform Format
        run: terraform fmt -check

      # Previews the changes that Terraform will make
      - name: Plan Terraform
        id: plan
        continue-on-error: true
        run: terraform plan -input=false -no-color

      # Post the preview (terraform plan) from the previous step as a GitHub pull request comment
      - name: Post Plan to GitHub PR
        if: github.ref != &amp;#39;refs/heads/main&amp;#39;
        uses: mshick/add-pr-comment@v1
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          repo-token-user-login: &amp;#39;github-actions[bot]&amp;#39;
          message: |
            Applying:

            ```
            ${{ steps.plan.outputs.stdout }}
            ```

      # Applies the terraform configuration files when the branch is `main`
      - name: Apply Terraform
        if: github.ref == &amp;#39;refs/heads/main&amp;#39;
        id: apply
        continue-on-error: true
        run: |
          terraform apply -auto-approve&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Commit the changes made to the &lt;code&gt;terraform.yml&lt;/code&gt; in the previous step to the &lt;code&gt;main&lt;/code&gt; branch in your GitHub repository. Once the changes are committed, The GitHub workflow you created should start to run automatically as the workflow we defined in the previous step runs when a pull request is created or when changes are committed to &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;managing-the-terraform-state&#34;&gt;Managing the Terraform state&lt;/h2&gt;
&lt;p&gt;If you are not using a &lt;a href=&#34;https://www.terraform.io/language/settings/backends/configuration&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform backend&lt;/a&gt; to store the &lt;code&gt;.tfstate&lt;/code&gt; file, add the following code block to the end of the GitHub workflow file to make sure the Terraform state file is stored in Git.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;- name: commit the terraform state
  if: github.ref == &amp;#39;refs/heads/main&amp;#39;
  uses: stefanzweifel/git-auto-commit-action@v4
  with:
    commit_message: Updating Terraform state
    file_pattern: terraform.tfstate&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When you run &lt;code&gt;terraform apply&lt;/code&gt;, Terraform automatically manages and updates the &lt;code&gt;terraform.tfstate&lt;/code&gt; file to store state about your infrastructure and configuration.
This step uses the &lt;a href=&#34;https://github.com/stefanzweifel/git-auto-commit-action&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;stefanzweifel/git-auto-commit-action@v4&lt;/a&gt; action to auto-commit the &lt;code&gt;terraform.tfstate&lt;/code&gt; file for changes made by running the &lt;code&gt;terraform apply&lt;/code&gt; step.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The Terraform state file (terraform.tfstate) shouldn&amp;rsquo;t be stored in Git to avoid leakage of sensitive data. Instead, store Terraform state files using a remote backend like AWS S3 with proper RBAC. For more information, refer to &lt;a href=&#34;https://www.terraform.io/language/state&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform state&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;Once the GitHub workflow run is successful, you should be able to verify the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ElasticSearch&lt;/code&gt;, &lt;code&gt;InfluxDB&lt;/code&gt; and &lt;code&gt;AWS&lt;/code&gt; folders are created in the Grafana instance.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/screenshot-folders-github-action-tf.png&#34;
  alt=&#34;Folders in Dashboards&#34; width=&#34;2390&#34;
     height=&#34;734&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dashboard represented as JSON source code from &lt;code&gt;elasticsearch&lt;/code&gt; folder in GitHub are added under the &lt;code&gt;ElasticSearch&lt;/code&gt; folder in the Grafana instance.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/screenshot-elastic-folder-github-action-tf.png&#34;
  alt=&#34;ElasticSearch Folder&#34; width=&#34;2432&#34;
     height=&#34;708&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dashboard source code from the &lt;code&gt;influxdb&lt;/code&gt; folder in GitHub is added under the &lt;code&gt;InfluxDB&lt;/code&gt; folder in the Grafana instance.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/screenshot-influxdb-folder-github-action-tf.png&#34;
  alt=&#34;InfluxDB Folder&#34; width=&#34;2428&#34;
     height=&#34;708&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dashboards from &lt;code&gt;aws&lt;/code&gt; folder in GitHub are added under the &lt;code&gt;AWS&lt;/code&gt; folder in the Grafana instance.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/screenshots-aws-folder-github-action-tf.png&#34;
  alt=&#34;AWS EC2 Folder&#34; width=&#34;2434&#34;
     height=&#34;692&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you created a GitHub workflow using Terraform to manage dashboard source code. Using this workflow, the dashboards in the Grafana instance are synchronized with the JSON source code files for dashboards in GitHub.&lt;/p&gt;
&lt;p&gt;To learn more about managing Grafana Cloud using Terraform, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="create-and-manage-dashboards-using-terraform-and-github-actions">Create and manage dashboards using Terraform and GitHub Actions&lt;/h1>
&lt;p>Learn how to create and manage multiple dashboards represented as JSON source code for Grafana using Terraform and GitHub Actions.&lt;/p></description></item><item><title>Manage Grafana IRM in Grafana Cloud using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-oncall/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-oncall/</guid><content><![CDATA[&lt;h1 id=&#34;manage-grafana-irm-in-grafana-cloud-using-terraform&#34;&gt;Manage Grafana IRM in Grafana Cloud using Terraform&lt;/h1&gt;
&lt;p&gt;Learn how to use Terraform to manage &lt;a href=&#34;/docs/grafana-cloud/alerting-and-irm/irm/&#34;&gt;Grafana IRM&lt;/a&gt; resources.
This guide shows you how to connect an integration, configure escalation policies, and add on-call schedules using Terraform.&lt;/p&gt;
&lt;p&gt;To illustrate the use of IRM across multiple teams, this guide features examples with two teams: &lt;code&gt;Devs&lt;/code&gt; and &lt;code&gt;SREs&lt;/code&gt;.
Additionally, it includes the necessary steps to configure Slack for IRM.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Grafana IRM supports Terraform-based configuration for a limited set of resources, primarily those related to OnCall functionality.
These resources use the &lt;code&gt;grafana_oncall_&lt;/code&gt; naming convention in Terraform. Additional IRM components are not yet configurable via Terraform.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account, as shown in &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/downloads&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;li&gt;Administrator permissions in your Grafana instance&lt;/li&gt;
&lt;li&gt;(Optional) Administrator permissions in your Slack workspace, if you plan to integrate Slack with Grafana IRM&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;All of the following Terraform configuration files should be saved in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;connect-slack-to-grafana-irm&#34;&gt;Connect Slack to Grafana IRM&lt;/h2&gt;
&lt;p&gt;Before including Slack settings in your Terraform setup, you must first configure the Slack integration with Grafana IRM.&lt;/p&gt;
&lt;p&gt;To connect your Slack workspace to Grafana IRM, refer to the &lt;a href=&#34;/docs/grafana-cloud/alerting-and-irm/irm/configure/integrations/irm-slack/&#34;&gt;Slack integration for Grafana IRM&lt;/a&gt; documentation.&lt;/p&gt;
&lt;h2 id=&#34;configure-the-grafana-provider&#34;&gt;Configure the Grafana provider&lt;/h2&gt;
&lt;p&gt;This Terraform configuration sets up the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; to provide necessary authentication when managing resources for Grafana IRM.&lt;/p&gt;
&lt;p&gt;You can reuse a similar setup to the one described in &lt;a href=&#34;../terraform-cloud-stack/&#34;&gt;Creating and managing a Grafana Cloud stack using Terraform&lt;/a&gt; to set up a service account and a token.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a Service account and token in Grafana. To create a new one, refer to &lt;a href=&#34;/docs/grafana/latest/administration/service-accounts/#service-account-tokens&#34;&gt;Service account tokens&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;main.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
      version = &amp;#34;&amp;gt;= 3.15.3&amp;#34;
    }
  }
}

provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;oncall&amp;#34;

  url  = &amp;#34;&amp;lt;Stack-URL&amp;gt;&amp;#34;
  auth = &amp;#34;&amp;lt;Service-account-token&amp;gt;&amp;#34;
  oncall_url = &amp;#34;&amp;lt;OnCall-URL&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Stack-URL&amp;gt;&lt;/code&gt; with the URL of your Grafana stack&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Service-account-token&amp;gt;&lt;/code&gt; with the service account token that you created&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;OnCall-URL&amp;gt;&lt;/code&gt; with the API URL found on the &lt;strong&gt;Admin &amp;amp; API&lt;/strong&gt; tab of the IRM &lt;strong&gt;Settings&lt;/strong&gt; page&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;If the service account has the right permissions, this provider setup also allows you to manage other Grafana resources.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;authentication-via-oncall-api-tokens-deprecated&#34;&gt;Authentication via OnCall API tokens (deprecated)&lt;/h3&gt;
&lt;p&gt;OnCall API tokens are being deprecated.
While existing tokens will continue to work, we recommend using
&lt;a href=&#34;/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/service-accounts/&#34;&gt;Grafana Cloud service account tokens&lt;/a&gt; for all new API authentication.&lt;/p&gt;
&lt;div class=&#34;collapse&#34; x-data=&#34;app_collapse()&#34;&gt;
  &lt;button class=&#34;collapse-trigger&#34; @click=&#34;toggle()&#34;&gt;
    &lt;span class=&#34;body-large&#34;&gt;Authentication via OnCall API tokens&lt;/span&gt;
    &lt;span class=&#34;collapse-trigger__icon&#34; :class=&#34;{ &#39;collapse-trigger__icon-open&#39; : open }&#34;&gt;
      
  &lt;svg width=&#34;27&#34; height=&#34;26&#34; viewBox=&#34;0 0 27 26&#34; fill=&#34;none&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;
&lt;path opacity=&#34;0.2&#34; d=&#34;M1.73047 12.8359C1.73047 19.4634 7.10305 24.8359 13.7305 24.8359C20.3579 24.8359 25.7305 19.4634 25.7305 12.8359C25.7305 6.20852 20.3579 0.835937 13.7305 0.835937C7.10305 0.835937 1.73047 6.20852 1.73047 12.8359Z&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M18.2344 12.8359L9.23438 12.8359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M13.7344 8.33594L13.7344 17.3359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;/svg&gt;


    &lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&#34;collapse-content&#34; x-ref=&#34;content&#34; hidden=&#34;until-found&#34;&gt;
    &lt;div class=&#34;collapse-content__inner&#34; x-ref=&#34;content-inner&#34;&gt;&lt;p&gt;To use an existing OnCall API token:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Log into your Grafana Cloud instance&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select &lt;strong&gt;Alerts &amp;amp; IRM&lt;/strong&gt; &amp;gt; &lt;strong&gt;IRM&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Settings&lt;/strong&gt;, and then select &lt;strong&gt;Admin &amp;amp; API&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Locate the &lt;strong&gt;Grafana IRM API&lt;/strong&gt; section&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;View, copy or revoke existing &lt;strong&gt;OnCall API tokens&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;main.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
      version = &amp;#34;&amp;gt;= 2.9.0&amp;#34;
    }
  }
}

provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;oncall&amp;#34;

  oncall_access_token = &amp;#34;&amp;lt;OnCall-API-Token&amp;gt;&amp;#34;
  oncall_url = &amp;#34;&amp;lt;OnCall-URL&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;OnCall-API-Token&amp;gt;&lt;/code&gt; with your existing OnCall API Token&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;OnCall-URL&amp;gt;&lt;/code&gt; with the API URL found on the &lt;strong&gt;Admin &amp;amp; API&lt;/strong&gt; tab of the IRM &lt;strong&gt;Settings&lt;/strong&gt; page&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&#34;add-on-call-schedules&#34;&gt;Add on-call schedules&lt;/h2&gt;
&lt;p&gt;This Terraform configuration sets up two on-call schedules, &lt;code&gt;SREs&lt;/code&gt; and &lt;code&gt;Devs&lt;/code&gt;, using the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/oncall_schedule&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_oncall_schedule&lt;/code&gt; resource&lt;/a&gt; to define the schedules within Grafana IRM.
Additionally, this configuration includes Slack channels to receive notifications for the on-call schedules of each team.&lt;/p&gt;
&lt;p&gt;To learn more about managing on-call schedules, refer to the &lt;a href=&#34;/docs/grafana-cloud/alerting-and-irm/irm/manage/on-call-schedules/&#34;&gt;On-call schedules documentation&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create two new calendars in your calendar service, one for &lt;code&gt;Devs&lt;/code&gt; and one for &lt;code&gt;SREs&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Locate and save the secret iCal URLs.
For example, in a Google calendar, these URLs can be found in &lt;strong&gt;Settings &amp;gt; Settings for my calendars &amp;gt; Integrate calendar&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;schedule.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Name of the Slack channel to notify about on-call schedules for Devs
data &amp;#34;grafana_oncall_slack_channel&amp;#34; &amp;#34;Devs&amp;#34; {
  provider = grafana.oncall

  name = &amp;#34;&amp;lt;Devs-channel-name&amp;gt;&amp;#34;
}

# Name of the Slack channel to notify about on-call schedules for SREs
data &amp;#34;grafana_oncall_slack_channel&amp;#34; &amp;#34;SREs&amp;#34; {
  provider = grafana.oncall

  name = &amp;#34;&amp;lt;SREs-channel-name&amp;gt;&amp;#34;
}

resource &amp;#34;grafana_oncall_schedule&amp;#34; &amp;#34;schedule_Devs&amp;#34; {
  provider = grafana.oncall

  name             = &amp;#34;Devs&amp;#34;
  type             = &amp;#34;ical&amp;#34;
  ical_url_primary = &amp;#34;&amp;lt;secret-iCal-URL-for-devs-calendar&amp;gt;&amp;#34;
  slack {
    channel_id = data.grafana_oncall_slack_channel.Devs.slack_id
  }
}

resource &amp;#34;grafana_oncall_schedule&amp;#34; &amp;#34;schedule_SREs&amp;#34; {
  provider = grafana.oncall

  name             = &amp;#34;SREs&amp;#34;
  type             = &amp;#34;ical&amp;#34;
  ical_url_primary = &amp;#34;&amp;lt;secret-iCal-URL-for-SREs-calendar&amp;gt;&amp;#34;
  slack {
    channel_id = data.grafana_oncall_slack_channel.SREs.slack_id
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Devs-channel-name&amp;gt;&lt;/code&gt; with name of the Slack channel to notify about on-call schedules for &lt;code&gt;Devs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;SREs-channel-name&amp;gt;&lt;/code&gt; with name of the Slack channel to notify about on-call schedules for &lt;code&gt;SREs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;secret-iCal-URL-for-devs-calendar&amp;gt;&lt;/code&gt; with the secret iCal URL created in the first step for &lt;code&gt;Devs&lt;/code&gt; Calendar&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;secret-iCal-URL-for-SREs-calendar&amp;gt;&lt;/code&gt; with the secret iCal URL created in the first step for &lt;code&gt;SREs&lt;/code&gt; Calendar&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;add-escalation-chains&#34;&gt;Add escalation chains&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates two escalation chains named &lt;code&gt;SREs&lt;/code&gt; and &lt;code&gt;Devs&lt;/code&gt; in Grafana IRM using the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/oncall_escalation_chain&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_oncall_escalation_chain&lt;/code&gt; (Resource)&lt;/a&gt;.
The configuration also adds the following three steps to each escalation chain using the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/oncall_escalation&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_oncall_escalation&lt;/code&gt; (Resource)&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Notify users from on-call schedule&lt;/li&gt;
&lt;li&gt;Wait for 5 minutes&lt;/li&gt;
&lt;li&gt;Notify default Slack channel&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;escalation-devs.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_oncall_escalation_chain&amp;#34; &amp;#34;Devs&amp;#34; {
  provider = grafana.oncall

  name = &amp;#34;Devs&amp;#34;
}

// Notify users from on-call schedule
resource &amp;#34;grafana_oncall_escalation&amp;#34; &amp;#34;notify_schedule_step_Devs&amp;#34; {
  provider = grafana.oncall

  escalation_chain_id          = grafana_oncall_escalation_chain.Devs.id
  type                         = &amp;#34;notify_on_call_from_schedule&amp;#34;
  notify_on_call_from_schedule = grafana_oncall_schedule.schedule_Devs.id
  position                     = 0
}

// Wait step for 5 Minutes
resource &amp;#34;grafana_oncall_escalation&amp;#34; &amp;#34;wait_step_Devs&amp;#34; {
  provider = grafana.oncall

  escalation_chain_id = grafana_oncall_escalation_chain.Devs.id
  type                = &amp;#34;wait&amp;#34;
  duration            = 300
  position            = 1
}

// Notify default Slack channel step
resource &amp;#34;grafana_oncall_escalation&amp;#34; &amp;#34;notify_step_Devs&amp;#34; {
  provider = grafana.oncall

  escalation_chain_id = grafana_oncall_escalation_chain.Devs.id
  type                = &amp;#34;notify_whole_channel&amp;#34;
  important           = true
  position            = 2
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;escalation-sre.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_oncall_escalation_chain&amp;#34; &amp;#34;SREs&amp;#34; {
  provider = grafana.oncall

  name = &amp;#34;SREs&amp;#34;
}

// Notify users from on-call schedule
resource &amp;#34;grafana_oncall_escalation&amp;#34; &amp;#34;notify_schedule_step_SREs&amp;#34; {
  provider = grafana.oncall

  escalation_chain_id          = grafana_oncall_escalation_chain.SREs.id
  type                         = &amp;#34;notify_on_call_from_schedule&amp;#34;
  notify_on_call_from_schedule = grafana_oncall_schedule.schedule_SREs.id
  position                     = 0
}

// Wait step for 5 Minutes
resource &amp;#34;grafana_oncall_escalation&amp;#34; &amp;#34;wait_step_SREs&amp;#34; {
  provider = grafana.oncall

  escalation_chain_id = grafana_oncall_escalation_chain.SREs.id
  type                = &amp;#34;wait&amp;#34;
  duration            = 300
  position            = 1
}

// Notify default Slack channel step
resource &amp;#34;grafana_oncall_escalation&amp;#34; &amp;#34;notify_step_SREs&amp;#34; {
  provider = grafana.oncall

  escalation_chain_id = grafana_oncall_escalation_chain.SREs.id
  type                = &amp;#34;notify_whole_channel&amp;#34;
  important           = true
  position            = 2
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;connect-an-integration-to-grafana-irm&#34;&gt;Connect an integration to Grafana IRM&lt;/h2&gt;
&lt;p&gt;This Terraform configuration connects Alertmanager to Grafana IRM using the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/oncall_integration&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_oncall_integration&lt;/code&gt; (Resource)&lt;/a&gt;.
It also adds the &lt;code&gt;Devs&lt;/code&gt; escalation chain as the default route for alerts.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;integrations.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_oncall_integration&amp;#34; &amp;#34;AlertManager&amp;#34; {
  provider = grafana.oncall

  name = &amp;#34;AlertManager&amp;#34;
  type = &amp;#34;alertmanager&amp;#34;
  default_route {
    escalation_chain_id = grafana_oncall_escalation_chain.Devs.id
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To configure Alertmanager, refer to the &lt;a href=&#34;/docs/grafana-cloud/alerting-and-irm/oncall/integrations/alertmanager/&#34;&gt;Alertmanager integration for Grafana OnCall&lt;/a&gt; documentation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;set-up-a-route-to-configure-escalation-behavior-for-alert-group-notifications&#34;&gt;Set up a route to configure escalation behavior for alert group notifications&lt;/h2&gt;
&lt;p&gt;This Terraform configuration sets up a route to the Alertmanager integration using the &lt;code&gt;grafana_oncall_route&lt;/code&gt; (Resource).
This route ensures that notifications for alerts with &lt;code&gt;\&amp;quot;namespace\&amp;quot; *: *\&amp;quot;ops-.*\&amp;quot;&lt;/code&gt; in the payload are escalated to the &lt;code&gt;SREs&lt;/code&gt; escalation chain.&lt;/p&gt;
&lt;p&gt;Create a file named &lt;code&gt;routes.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_oncall_route&amp;#34; &amp;#34;route_SREs&amp;#34; {
  provider = grafana.oncall

  integration_id      = grafana_oncall_integration.AlertManager.id
  escalation_chain_id = grafana_oncall_escalation_chain.SREs.id
  routing_regex       = &amp;#34;\&amp;#34;namespace\&amp;#34; *: *\&amp;#34;ops-.*\&amp;#34;&amp;#34;
  position            = 0
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;apply-the-terraform-configuration&#34;&gt;Apply the Terraform configuration&lt;/h2&gt;
&lt;p&gt;In a terminal, run the following commands from the directory where all of the configuration files are located.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Initialize a working directory containing Terraform configuration files.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform init&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Preview the changes that Terraform will make.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform plan&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply the configuration files.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform apply&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After you apply the changes in the Terraform configurations, you can verify the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Two new Schedules named &lt;code&gt;Devs&lt;/code&gt; and &lt;code&gt;SREs&lt;/code&gt; are created in Grafana IRM:&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/alerting-and-irm/screenshot-oncall-schedules-tf.png&#34;
  alt=&#34;Devs and SREs OnCall schedules&#34; width=&#34;1320&#34;
     height=&#34;484&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;New Escalation chain named &lt;code&gt;SREs&lt;/code&gt; is created in Grafana IRM:&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/alerting-and-irm/screenshot-oncall-escalation-sre-tf.png&#34;
  alt=&#34;SREs escalation chain&#34; width=&#34;1320&#34;
     height=&#34;580&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;New Escalation chain named &lt;code&gt;Devs&lt;/code&gt; is created in Grafana IRM:&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/alerting-and-irm/screenshot-oncall-escalation-devs-tf.png&#34;
  alt=&#34;Devs escalation chain&#34; width=&#34;1320&#34;
     height=&#34;580&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Alertmanager integration is added and configured with escalation policies:&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/grafana-cloud/alerting-and-irm/screenshot-oncall-alertmanager-tf.png&#34;
  alt=&#34;Alertmanager integration for SREs escalation&#34; width=&#34;1320&#34;
     height=&#34;716&#34;/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you learned how to use Terraform to manage Grafana IRM by connecting an integration, configuring escalation policies, and setting up on-call schedules.&lt;/p&gt;
&lt;p&gt;To learn more about managing Grafana Cloud using Terraform, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="manage-grafana-irm-in-grafana-cloud-using-terraform">Manage Grafana IRM in Grafana Cloud using Terraform&lt;/h1>
&lt;p>Learn how to use Terraform to manage &lt;a href="/docs/grafana-cloud/alerting-and-irm/irm/">Grafana IRM&lt;/a> resources.
This guide shows you how to connect an integration, configure escalation policies, and add on-call schedules using Terraform.&lt;/p></description></item><item><title>Manage Knowledge Graph in Grafana Cloud using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/</guid><content><![CDATA[

  
    
      
    
  

  &lt;div&gt;
  &lt;div class=&#34;d-flex flex-direction-row flex-direction-column-small gap-2 justify-content-start align-items-center align-items-start-small flex-wrap &#34;&gt;&lt;div class=&#34;d-flex flex-direction-column&#34;&gt;
      &lt;div&gt;&lt;h1
  
  id=&#34;manage-knowledge-graph-using-terraform&#34;
  &gt;Manage Knowledge Graph using Terraform&lt;/h1&gt;&lt;/div&gt;
      
        &lt;div class=&#34;&#34;&gt;Use Terraform to manage Grafana Cloud Knowledge Graph resources as code. Configure the Knowledge Graph stack, notification alerts, suppressed assertions, custom model rules, log configurations, and threshold configurations using infrastructure as code best practices.&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;hr /&gt;
&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;Terraform enables you to manage &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Grafana Cloud Knowledge Graph&lt;/a&gt; resources using infrastructure as code. With Terraform, you can define, version control, and deploy Knowledge Graph configurations including stack onboarding, alert rules, suppression policies, entity models, log, trace, and profile correlations, and thresholds.&lt;/p&gt;
&lt;h2 id=&#34;explore&#34;&gt;Explore&lt;/h2&gt;

&lt;hr /&gt;
&lt;h2 id=&#34;related-resources&#34;&gt;Related resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana Terraform Provider Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/docs/cloud/guides/recommended-practices/index.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;div>
&lt;div class="d-flex flex-direction-row flex-direction-column-small gap-2 justify-content-start align-items-center align-items-start-small flex-wrap ">&lt;div class="d-flex flex-direction-column">
&lt;div>&lt;h1
id="manage-knowledge-graph-using-terraform"
>Manage Knowledge Graph using Terraform&lt;/h1>&lt;/div>
&lt;div class="">Use Terraform to manage Grafana Cloud Knowledge Graph resources as code. Configure the Knowledge Graph stack, notification alerts, suppressed assertions, custom model rules, log configurations, and threshold configurations using infrastructure as code best practices.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;hr />
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>Terraform enables you to manage &lt;a href="/docs/grafana-cloud/knowledge-graph/">Grafana Cloud Knowledge Graph&lt;/a> resources using infrastructure as code. With Terraform, you can define, version control, and deploy Knowledge Graph configurations including stack onboarding, alert rules, suppression policies, entity models, log, trace, and profile correlations, and thresholds.&lt;/p></description></item><item><title>Manage secrets in Grafana Cloud using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-secrets-management/</link><pubDate>Tue, 06 Oct 2026 19:16:37 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-secrets-management/</guid><content><![CDATA[&lt;h1 id=&#34;manage-secrets-in-grafana-cloud-using-terraform&#34;&gt;Manage secrets in Grafana Cloud using Terraform&lt;/h1&gt;
&lt;p&gt;Use the Terraform Grafana provider to create and manage secure values in &lt;a href=&#34;/docs/grafana-cloud/platform/security-and-account-management/security-and-access/manage-secrets/&#34;&gt;Grafana Secrets Management&lt;/a&gt; as code.
With Terraform, you keep secrets such as API keys, tokens, passwords, and certificates in version-controlled, declarative infrastructure alongside the rest of your Grafana stack.&lt;/p&gt;
&lt;p&gt;This guide covers &lt;em&gt;secure values&lt;/em&gt;, which you manage with the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_securevalue_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_apps_secret_securevalue_v1beta1&lt;/code&gt;&lt;/a&gt; resource.
By default, Grafana stores secure values in the built-in &lt;em&gt;system keeper&lt;/em&gt;, which requires no setup.
If you configure an additional keeper and set it as the active keeper for your namespace, Grafana stores new secure values there automatically.
For more information, refer to &lt;a href=&#34;#activate-and-use-the-keeper&#34;&gt;Activate and use the keeper&lt;/a&gt;.
To store secure values in an external secret manager instead, &lt;a href=&#34;#provision-a-keeper&#34;&gt;provision a keeper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To create and manage secure values with Terraform, you complete the following tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a service account token to authenticate the Terraform provider.&lt;/li&gt;
&lt;li&gt;Configure the Grafana provider.&lt;/li&gt;
&lt;li&gt;Define one or more secure values.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;terraform apply&lt;/code&gt; to provision your secure values.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;To provision secure values with Terraform, you need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud instance that you can reach from the machine that runs Terraform.&lt;/li&gt;
&lt;li&gt;Permission to create service account tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You also need the following tools at the minimum supported versions:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Tool&lt;/th&gt;
              &lt;th&gt;Minimum version&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;Terraform CLI&lt;/td&gt;
              &lt;td&gt;1.11, for &lt;a href=&#34;https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;write-only arguments&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafana/grafana&lt;/code&gt; Terraform provider&lt;/td&gt;
              &lt;td&gt;4.26.0&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;If you don&amp;rsquo;t have the Terraform CLI, refer to the &lt;a href=&#34;https://developer.hashicorp.com/terraform/install&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform install documentation&lt;/a&gt;.
The &lt;code&gt;grafana/grafana&lt;/code&gt; provider downloads automatically when you run &lt;code&gt;terraform init&lt;/code&gt; in &lt;a href=&#34;#provision-the-secure-value-with-terraform&#34;&gt;Provision the secure value with Terraform&lt;/a&gt;.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;All of the following Terraform configuration files should be saved in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;create-a-service-account-token&#34;&gt;Create a service account token&lt;/h2&gt;
&lt;p&gt;Terraform authenticates against Grafana with a service account token.&lt;/p&gt;
&lt;p&gt;To create a service account and token, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a service account and token in Grafana.
To create them, refer to &lt;a href=&#34;/docs/grafana/latest/administration/service-accounts/#service-account-tokens&#34;&gt;Service account tokens&lt;/a&gt;.
You can also refer to &lt;a href=&#34;../terraform-cloud-stack/&#34;&gt;Create and manage a Grafana Cloud stack using Terraform&lt;/a&gt; to set up a service account and token.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure the service account has the role-based access control (RBAC) actions needed to manage secure values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;secret.securevalues:create&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secret.securevalues:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secret.securevalues:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secret.securevalues:delete&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you also provision a keeper (refer to &lt;a href=&#34;#provision-a-keeper&#34;&gt;Provision a keeper&lt;/a&gt;), the service account also needs the keeper actions, which cover activating a keeper:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;secret.keepers:create&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secret.keepers:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secret.keepers:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secret.keepers:delete&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the token and store it securely, because you can&amp;rsquo;t view it again after you leave the page.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configure-the-grafana-provider&#34;&gt;Configure the Grafana provider&lt;/h2&gt;
&lt;p&gt;In your Terraform working directory, create a &lt;code&gt;main.tf&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_version = &amp;#34;&amp;gt;= 1.11.0&amp;#34;

  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
      version = &amp;#34;&amp;gt;= 4.26.0&amp;#34;
    }
  }
}

variable &amp;#34;grafana_auth&amp;#34; {
  type      = string
  sensitive = true
}

provider &amp;#34;grafana&amp;#34; {
  url  = &amp;#34;&amp;lt;GRAFANA_URL&amp;gt;&amp;#34;
  auth = var.grafana_auth

  # Required for app-platform resources, including secure values.
  stack_id = &amp;lt;STACK_ID&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace the placeholders as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;&amp;lt;GRAFANA_URL&amp;gt;&lt;/code&gt;&lt;/em&gt; is the URL of your Grafana instance, for example &lt;code&gt;https://my-org.grafana.net&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;&amp;lt;STACK_ID&amp;gt;&lt;/code&gt;&lt;/em&gt; is your numeric Grafana Cloud stack ID, for example &lt;code&gt;123456&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To find your stack ID, open the &lt;a href=&#34;/profile/org&#34;&gt;Grafana Cloud Portal&lt;/a&gt;, select your stack, and read the numeric &lt;strong&gt;Instance ID&lt;/strong&gt;. That value is your &lt;code&gt;stack_id&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also retrieve it with a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;https://grafana.com/api/orgs/&amp;lt;ORG_SLUG&amp;gt;/instances&lt;/code&gt;, where &lt;em&gt;&lt;code&gt;&amp;lt;ORG_SLUG&amp;gt;&lt;/code&gt;&lt;/em&gt; is your Grafana Cloud organization name.
The numeric &lt;code&gt;id&lt;/code&gt; field in the response is the stack ID.
This Cloud API endpoint authenticates with a &lt;a href=&#34;/docs/grafana-cloud/developer-resources/api-reference/cloud-api/&#34;&gt;Cloud Access Policy token&lt;/a&gt;, which is separate from the service account token that Terraform uses.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Provide each input variable through a matching environment variable that follows the Terraform &lt;code&gt;TF_VAR_&amp;lt;variable_name&amp;gt;&lt;/code&gt; naming convention.
The part after &lt;code&gt;TF_VAR_&lt;/code&gt; is the name of the variable in your configuration: Terraform maps &lt;code&gt;TF_VAR_grafana_auth&lt;/code&gt; to the &lt;code&gt;grafana_auth&lt;/code&gt; variable, &lt;code&gt;TF_VAR_external_api_key&lt;/code&gt; to &lt;code&gt;external_api_key&lt;/code&gt;, and so on.
You can also use a secrets manager or a &lt;code&gt;terraform.tfvars&lt;/code&gt; file.
Don&amp;rsquo;t set variables in a file that you commit.&lt;/p&gt;
&lt;p&gt;For other authentication options, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs#authentication&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.
For end-to-end stack management, refer to &lt;a href=&#34;../terraform-cloud-stack/&#34;&gt;Create and manage a Grafana Cloud stack using Terraform&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;define-a-secure-value&#34;&gt;Define a secure value&lt;/h2&gt;
&lt;p&gt;The following example stores an API key as a secure value and authorizes Synthetic Monitoring to decrypt it.
Add it to &lt;code&gt;main.tf&lt;/code&gt;, or to any other &lt;code&gt;.tf&lt;/code&gt; file in the same working directory.
Terraform loads all &lt;code&gt;.tf&lt;/code&gt; files in the directory together.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;variable &amp;#34;external_api_key&amp;#34; {
  type      = string
  sensitive = true
  ephemeral = true # Keeps the value out of state and plan files.
}

resource &amp;#34;grafana_apps_secret_securevalue_v1beta1&amp;#34; &amp;#34;external_api_key&amp;#34; {
  metadata {
    uid = &amp;#34;external-api-key&amp;#34; # The secure value&amp;#39;s name.
  }

  spec {
    description = &amp;#34;External API key&amp;#34;
    value       = var.external_api_key
    decrypters  = [&amp;#34;synthetic-monitoring&amp;#34;]
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Keep the following points in mind for this example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;metadata.uid&lt;/code&gt; is the secure value&amp;rsquo;s &lt;em&gt;name&lt;/em&gt; in Grafana.
The resource also exposes a separate, read-only &lt;code&gt;metadata.uuid&lt;/code&gt;, which is the Grafana-generated identifier rather than the name.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec.description&lt;/code&gt; is required and limited to 25 characters.
Longer values fail at plan with a Terraform length validation error.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec.value&lt;/code&gt; is a &lt;a href=&#34;https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;write-only argument&lt;/a&gt; that requires Terraform 1.11 or later.
Terraform sends the plaintext to Grafana on apply, but never writes it to state, plan output, or any other on-disk artifact.
Combine it with an &lt;code&gt;ephemeral&lt;/code&gt;, sensitive variable, as in the preceding example, so the value also stays out of &lt;code&gt;terraform plan&lt;/code&gt; output.&lt;/li&gt;
&lt;li&gt;You don&amp;rsquo;t pass a &lt;code&gt;namespace&lt;/code&gt;. The provider derives it from &lt;code&gt;stack_id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You don&amp;rsquo;t pass a keeper name. Grafana stores the value in whichever keeper is the active keeper for your namespace, which is the system keeper by default.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;schema-reference&#34;&gt;Schema reference&lt;/h3&gt;
&lt;p&gt;The full schema is on the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_securevalue_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform Registry&lt;/a&gt;.
The following tables describe the fields you use for secure values.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;metadata&lt;/code&gt; block contains the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;uid&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The secure value&amp;rsquo;s name. Up to 253 characters, DNS-compatible, and immutable.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;folder_uid&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Not used for secure values. Leave it unset.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;uuid&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;annotations&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Read-only. Grafana populates these fields.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;The &lt;code&gt;spec&lt;/code&gt; block contains the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes, enforced server-side&lt;/td&gt;
              &lt;td&gt;1 to 25 characters.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Conditional&lt;/td&gt;
              &lt;td&gt;Plaintext secret value, 1 to 24,576 bytes. Sensitive and &lt;a href=&#34;https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;write-only&lt;/a&gt; in Terraform 1.11 or later. Sent to Grafana on apply but never written to state or plan files. Set exactly one of &lt;code&gt;value&lt;/code&gt; or &lt;code&gt;ref&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;ref&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Conditional&lt;/td&gt;
              &lt;td&gt;Reference to a secret already stored in a third-party keeper, 1 to 1,024 characters. Valid only when the active keeper for the namespace isn&amp;rsquo;t the system keeper. Set exactly one of &lt;code&gt;value&lt;/code&gt; or &lt;code&gt;ref&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;decrypters&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of services permitted to decrypt this secure value. Up to 64 unique entries. Each entry must be a valid Kubernetes label value: letters, numbers, and the characters &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, and &lt;code&gt;_&lt;/code&gt;, with no slashes or spaces. For more information, refer to &lt;a href=&#34;#decrypters&#34;&gt;Decrypters&lt;/a&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;value_hash&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Computed&lt;/td&gt;
              &lt;td&gt;Read-only SHA-256 hash of the stored value. The provider uses it to detect rotation. Don&amp;rsquo;t set it yourself.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;The &lt;code&gt;options&lt;/code&gt; block is optional and contains the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;manager_identity&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Overrides the manager identity stamped on this resource. The default is &lt;code&gt;grafana-terraform-provider&lt;/code&gt;. Useful when multiple Terraform workspaces manage resources in the same Grafana instance.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;overwrite&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Set to &lt;code&gt;true&lt;/code&gt; to overwrite an existing resource with the same UID when applicable.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;At the top level, the resource exposes a read-only &lt;code&gt;id&lt;/code&gt; field, which Grafana derives from the secure value&amp;rsquo;s UUID.&lt;/p&gt;
&lt;h3 id=&#34;decrypters&#34;&gt;Decrypters&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;decrypters&lt;/code&gt; list controls which Grafana services can decrypt a secret. If a service isn&amp;rsquo;t in the list, it can&amp;rsquo;t read the plaintext value, even if it has access to the secure value&amp;rsquo;s metadata. An empty or unset list means no service can decrypt the value.&lt;/p&gt;
&lt;p&gt;Grafana supports the following decrypters:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Decrypter&lt;/th&gt;
              &lt;th&gt;Consumer&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;k6-cloud&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Grafana Cloud k6&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;synthetic-monitoring&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Synthetic Monitoring checks&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;Grant the minimum set of decrypters required for your use case.&lt;/p&gt;
&lt;h2 id=&#34;provision-the-secure-value-with-terraform&#34;&gt;Provision the secure value with Terraform&lt;/h2&gt;
&lt;p&gt;To apply the configuration, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Initialize the working directory.
This downloads the Grafana provider.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform init&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the environment variables, then preview and apply the changes:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;export TF_VAR_grafana_auth=&amp;#39;&amp;lt;TOKEN&amp;gt;&amp;#39;
export TF_VAR_external_api_key=&amp;#39;&amp;lt;SECRET&amp;gt;&amp;#39;
terraform plan
terraform apply&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace the placeholders as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&amp;lt;TOKEN&amp;gt;&lt;/code&gt;&lt;/em&gt; is the service account token you created in &lt;a href=&#34;#create-a-service-account-token&#34;&gt;Create a service account token&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&amp;lt;SECRET&amp;gt;&lt;/code&gt;&lt;/em&gt; is the plaintext secret value that Terraform stores as the secure value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This keeps secrets out of Terraform files.
If your shell writes history, prefer a secure secret-injection flow, such as CI/CD secrets, a secret manager, or a nested shell with history disabled.&lt;/p&gt;
&lt;p&gt;Terraform shows the execution plan and asks for confirmation:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;console&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-console&#34;&gt;Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only &amp;#39;yes&amp;#39; will be accepted to approve.

  Enter a value:&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After you confirm, Terraform creates the secure value:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;console&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-console&#34;&gt;Apply complete! Resources: 1 added, 0 changed, 0 destroyed.&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If a secure value with the same &lt;code&gt;metadata.uid&lt;/code&gt; already exists in the namespace, for example from a previous apply or one created outside Terraform, the apply fails with &lt;code&gt;HTTP 409 - AlreadyExists&lt;/code&gt;.
To bring the existing secure value under Terraform management instead of recreating it, &lt;a href=&#34;#import-an-existing-secure-value&#34;&gt;import it&lt;/a&gt;.
To replace it on apply, set &lt;code&gt;overwrite = true&lt;/code&gt; in the resource&amp;rsquo;s &lt;code&gt;options&lt;/code&gt; block.&lt;/p&gt;
&lt;h3 id=&#34;verify-that-the-plaintext-stays-out-of-state&#34;&gt;Verify that the plaintext stays out of state&lt;/h3&gt;
&lt;p&gt;Because &lt;code&gt;spec.value&lt;/code&gt; is write-only, Terraform never writes the plaintext to state.
It writes only the &lt;code&gt;value_hash&lt;/code&gt;.
To confirm this, search your local state file for the plaintext:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;grep -c &amp;#39;&amp;lt;SECRET_VALUE&amp;gt;&amp;#39; terraform.tfstate&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace &lt;em&gt;&lt;code&gt;&amp;lt;SECRET_VALUE&amp;gt;&lt;/code&gt;&lt;/em&gt; with the plaintext secret you provisioned.
The search returns no matches:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;console&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-console&#34;&gt;0&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The stored &lt;code&gt;spec&lt;/code&gt; shows &lt;code&gt;value&lt;/code&gt; as &lt;code&gt;null&lt;/code&gt; and retains only the hash:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JSON&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;&amp;#34;spec&amp;#34;: {
  &amp;#34;decrypters&amp;#34;: [&amp;#34;synthetic-monitoring&amp;#34;],
  &amp;#34;description&amp;#34;: &amp;#34;External API key&amp;#34;,
  &amp;#34;ref&amp;#34;: null,
  &amp;#34;value&amp;#34;: null,
  &amp;#34;value_hash&amp;#34;: &amp;#34;65f087ba121c13dec3fa0cb7697d4309ed5e624ba528a758bb9071bee220825a&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To verify the result, open &lt;strong&gt;Administration&lt;/strong&gt; &amp;gt; &lt;strong&gt;Secrets Management&lt;/strong&gt; in Grafana, or call the &lt;a href=&#34;/docs/grafana-cloud/developer-resources/api-reference/http-api/secrets_management/&#34;&gt;Secrets Management HTTP API&lt;/a&gt; directly.
The namespace is &lt;code&gt;stacks-&amp;lt;STACK_ID&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -H &amp;#34;Authorization: Bearer &amp;lt;TOKEN&amp;gt;&amp;#34; \
  &amp;#34;&amp;lt;GRAFANA_URL&amp;gt;/apis/secret.grafana.app/v1beta1/namespaces/stacks-&amp;lt;STACK_ID&amp;gt;/securevalues/external-api-key&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response includes the secure value&amp;rsquo;s metadata, its &lt;code&gt;spec&lt;/code&gt; with &lt;code&gt;description&lt;/code&gt; and &lt;code&gt;decrypters&lt;/code&gt;, and the keeper that stores it.
It never includes the plaintext &lt;code&gt;value&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JSON&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;#34;kind&amp;#34;: &amp;#34;SecureValue&amp;#34;,
  &amp;#34;apiVersion&amp;#34;: &amp;#34;secret.grafana.app/v1beta1&amp;#34;,
  &amp;#34;metadata&amp;#34;: {
    &amp;#34;name&amp;#34;: &amp;#34;external-api-key&amp;#34;,
    &amp;#34;namespace&amp;#34;: &amp;#34;stacks-&amp;lt;STACK_ID&amp;gt;&amp;#34;,
    &amp;#34;annotations&amp;#34;: {
      &amp;#34;grafana.app/managedBy&amp;#34;: &amp;#34;terraform&amp;#34;,
      &amp;#34;grafana.app/managerId&amp;#34;: &amp;#34;grafana-terraform-provider&amp;#34;
    }
  },
  &amp;#34;spec&amp;#34;: {
    &amp;#34;description&amp;#34;: &amp;#34;External API key&amp;#34;,
    &amp;#34;decrypters&amp;#34;: [&amp;#34;synthetic-monitoring&amp;#34;]
  },
  &amp;#34;status&amp;#34;: {
    &amp;#34;version&amp;#34;: 1,
    &amp;#34;keeper&amp;#34;: &amp;#34;system&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;There is no &lt;code&gt;value&lt;/code&gt; field in the response. The API doesn&amp;rsquo;t return decrypted secret contents.&lt;/p&gt;
&lt;h2 id=&#34;rotate-a-secure-value&#34;&gt;Rotate a secure value&lt;/h2&gt;
&lt;p&gt;To rotate a secret, change the value, or the variable that feeds it, and run &lt;code&gt;terraform apply&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;The provider computes a SHA-256 hash of your configured &lt;code&gt;spec.value&lt;/code&gt; at plan time and stores it in &lt;code&gt;value_hash&lt;/code&gt;. When the hash changes, Terraform plans an update. When the hash doesn&amp;rsquo;t change, Terraform plans no change. This lets you rotate secrets without storing plaintext in state.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_apps_secret_securevalue_v1beta1&amp;#34; &amp;#34;external_api_key&amp;#34; {
  metadata {
    uid = &amp;#34;external-api-key&amp;#34;
  }

  spec {
    description = &amp;#34;External API key&amp;#34;
    value       = var.external_api_key # Supply the new value here.
    decrypters  = [&amp;#34;synthetic-monitoring&amp;#34;]
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When the value changes, the recomputed &lt;code&gt;value_hash&lt;/code&gt; drives an in-place update:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;console&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-console&#34;&gt;  ~ spec {
      ~ value_hash = (sensitive value)
    }

Plan: 0 to add, 1 to change, 0 to destroy.&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you apply again without changing the value, the hash matches and Terraform plans no change:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;console&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-console&#34;&gt;No changes. Your infrastructure matches the configuration.&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;rotation-considerations&#34;&gt;Rotation considerations&lt;/h3&gt;
&lt;p&gt;Keep the following points in mind when you rotate secure values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;value&lt;/code&gt; is write-only.&lt;/strong&gt;
The Grafana API never returns the plaintext, and the provider never reads it back.
Only &lt;code&gt;value_hash&lt;/code&gt; is stored in state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Out-of-band value changes aren&amp;rsquo;t directly detectable.&lt;/strong&gt;
Because the plaintext is write-only, Terraform can&amp;rsquo;t read the current secret contents from Grafana.
Keep Terraform as your source of truth for rotations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You can&amp;rsquo;t switch a secure value between &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;ref&lt;/code&gt; after creation.&lt;/strong&gt;
The API rejects updates that try to change mode.
To change mode, destroy and recreate the resource.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;metadata.uid&lt;/code&gt; is immutable.&lt;/strong&gt;
Changing it forces Terraform to destroy and recreate the secure value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;decrypters&lt;/code&gt; ordering is significant in Terraform.&lt;/strong&gt;
Keep a stable order in your configuration to avoid noisy plans.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An update is a full replace with &lt;code&gt;PUT&lt;/code&gt;, not a patch.&lt;/strong&gt;
Always provide &lt;code&gt;description&lt;/code&gt; and &lt;code&gt;decrypters&lt;/code&gt; together with &lt;code&gt;value&lt;/code&gt; or &lt;code&gt;ref&lt;/code&gt; on update.
If you omit them, the new spec replaces the old one in full.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;handle-the-secret-value-safely&#34;&gt;Handle the secret value safely&lt;/h3&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;Never check plaintext secret values into Terraform configuration.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Instead, use one of the following approaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;sensitive&lt;/code&gt; or &lt;code&gt;ephemeral&lt;/code&gt; Terraform variable populated from a &lt;code&gt;TF_VAR_*&lt;/code&gt; environment variable.&lt;/li&gt;
&lt;li&gt;A CI/CD secret injected at apply time.&lt;/li&gt;
&lt;li&gt;A dedicated secret store, such as HashiCorp Vault or AWS Secrets Manager, referenced from Terraform with the appropriate provider data source.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;import-an-existing-secure-value&#34;&gt;Import an existing secure value&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;grafana_apps_secret_securevalue_v1beta1&lt;/code&gt; resource supports import.
The import ID is the secure value name, which is the value of &lt;code&gt;metadata.uid&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform import grafana_apps_secret_securevalue_v1beta1.external_api_key external-api-key&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After you import a secure value, keep the following points in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;spec.value&lt;/code&gt; is still write-only, and Terraform never imports it into state.&lt;/li&gt;
&lt;li&gt;For value-backed secure values, set &lt;code&gt;spec.value&lt;/code&gt; in configuration before you apply.
The first managed apply sets or rotates the value to whatever you configure.&lt;/li&gt;
&lt;li&gt;For reference-backed secure values, set &lt;code&gt;spec.ref&lt;/code&gt; in configuration to match the existing reference.&lt;/li&gt;
&lt;li&gt;Because you must set exactly one of &lt;code&gt;value&lt;/code&gt; or &lt;code&gt;ref&lt;/code&gt;, your configuration must include one of them after import.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;provision-a-keeper&#34;&gt;Provision a keeper&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;keeper&lt;/em&gt; defines where Grafana stores the encrypted material for your secure values. By default, Grafana uses the built-in system keeper, which encrypts values at rest in the Grafana database and requires no setup.&lt;/p&gt;
&lt;p&gt;To store secrets in an external secret manager instead, provision a keeper with the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_keeper_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_apps_secret_keeper_v1beta1&lt;/code&gt;&lt;/a&gt; resource.
Grafana currently supports AWS Secrets Manager as a keeper.&lt;/p&gt;
&lt;p&gt;Grafana connects to AWS Secrets Manager through cross-account role assumption with AWS Security Token Service, and never stores your AWS credentials.
You create an AWS Identity and Access Management (IAM) role in your AWS account that Grafana can assume, and the keeper references that role.&lt;/p&gt;
&lt;h3 id=&#34;keeper-requirements&#34;&gt;Keeper requirements&lt;/h3&gt;
&lt;p&gt;In addition to the &lt;a href=&#34;#before-you-begin&#34;&gt;requirements for secure values&lt;/a&gt;, you need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An AWS account with AWS Secrets Manager enabled in your target region.&lt;/li&gt;
&lt;li&gt;An IAM role named exactly &lt;code&gt;grafana-secrets-manager&lt;/code&gt; that Grafana can assume, along with its role ARN and external ID.
Grafana can assume only a role with that name.
For the IAM role and trust policy that the role requires, refer to &lt;a href=&#34;/docs/grafana-cloud/platform/security-and-account-management/security-and-access/configure-aws-secrets-manager-keeper/&#34;&gt;Configure an AWS Secrets Manager keeper&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;define-a-keeper&#34;&gt;Define a keeper&lt;/h3&gt;
&lt;p&gt;The following example provisions an AWS Secrets Manager keeper. Add it to &lt;code&gt;main.tf&lt;/code&gt;, or to any other &lt;code&gt;.tf&lt;/code&gt; file in the same working directory.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_apps_secret_keeper_v1beta1&amp;#34; &amp;#34;aws_secrets_manager&amp;#34; {
  metadata {
    uid = &amp;#34;aws-secrets-manager&amp;#34; # The keeper&amp;#39;s name.
  }

  spec {
    description = &amp;#34;AWS Secrets Manager keeper&amp;#34;

    aws {
      region = &amp;#34;&amp;lt;REGION&amp;gt;&amp;#34;

      assume_role {
        assume_role_arn = &amp;#34;arn:aws:iam::&amp;lt;ACCOUNT_ID&amp;gt;:role/grafana-secrets-manager&amp;#34;
        external_id     = &amp;#34;&amp;lt;EXTERNAL_ID&amp;gt;&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace the placeholders as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&amp;lt;REGION&amp;gt;&lt;/code&gt;&lt;/em&gt; is the AWS region that hosts your secrets, for example &lt;code&gt;us-east-1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&amp;lt;ACCOUNT_ID&amp;gt;&lt;/code&gt;&lt;/em&gt; is the ID of the AWS account that hosts your secrets.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&amp;lt;EXTERNAL_ID&amp;gt;&lt;/code&gt;&lt;/em&gt; is the external ID that your IAM role&amp;rsquo;s trust policy requires.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The role name in &lt;code&gt;assume_role_arn&lt;/code&gt; must be &lt;code&gt;grafana-secrets-manager&lt;/code&gt;. Grafana can&amp;rsquo;t assume a role with any other name.&lt;/p&gt;
&lt;p&gt;Apply the keeper with the same &lt;code&gt;terraform apply&lt;/code&gt; workflow you use for a secure value, described in &lt;a href=&#34;#provision-the-secure-value-with-terraform&#34;&gt;Provision the secure value with Terraform&lt;/a&gt;.
Unlike a secure value, a keeper has no secret value, so it needs no &lt;code&gt;ephemeral&lt;/code&gt; variable of its own: &lt;code&gt;TF_VAR_grafana_auth&lt;/code&gt; for the provider is the only variable you export.
Creating a keeper doesn&amp;rsquo;t make it active, so don&amp;rsquo;t create secure values in the same apply until you add the activation resource in &lt;a href=&#34;#activate-and-use-the-keeper&#34;&gt;Activate and use the keeper&lt;/a&gt; and make new secrets depend on it.&lt;/p&gt;
&lt;h3 id=&#34;keeper-schema-reference&#34;&gt;Keeper schema reference&lt;/h3&gt;
&lt;p&gt;The full schema is on the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_keeper_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform Registry&lt;/a&gt;. The following tables describe the fields you use for a keeper.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;metadata&lt;/code&gt; block contains the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;uid&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The keeper&amp;rsquo;s name. Up to 253 characters, DNS-compatible, and immutable.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;The &lt;code&gt;spec&lt;/code&gt; block contains the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Short description for the keeper, 1 to 253 characters.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;aws&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;AWS Secrets Manager configuration. Grafana currently supports only AWS, so this block is required. For the fields, refer to the following &lt;code&gt;aws&lt;/code&gt; table.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;The &lt;code&gt;aws&lt;/code&gt; block contains the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;region&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;AWS region that hosts your secrets, for example &lt;code&gt;us-east-1&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;assume_role&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Role that Grafana assumes to access AWS Secrets Manager. Required for AWS. &lt;code&gt;assume_role_arn&lt;/code&gt; and &lt;code&gt;external_id&lt;/code&gt; are both required.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;The &lt;code&gt;assume_role&lt;/code&gt; block contains the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;assume_role_arn&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;ARN of the IAM role that Grafana assumes.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;external_id&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;External ID that the IAM role&amp;rsquo;s trust policy requires.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;At the top level, the resource exposes a read-only &lt;code&gt;active&lt;/code&gt; status that&amp;rsquo;s &lt;code&gt;true&lt;/code&gt; when the keeper is the active keeper for the namespace.&lt;/p&gt;
&lt;h3 id=&#34;activate-and-use-the-keeper&#34;&gt;Activate and use the keeper&lt;/h3&gt;
&lt;p&gt;Creating a keeper with Terraform doesn&amp;rsquo;t make it active. Each namespace has at most one active keeper, which determines where Grafana stores new secure values.&lt;/p&gt;
&lt;p&gt;To set a keeper as active, use the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_keeper_activation_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_apps_secret_keeper_activation_v1beta1&lt;/code&gt;&lt;/a&gt; resource and reference the keeper&amp;rsquo;s &lt;code&gt;uid&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_apps_secret_keeper_activation_v1beta1&amp;#34; &amp;#34;aws_secrets_manager&amp;#34; {
  metadata {
    uid = grafana_apps_secret_keeper_v1beta1.aws_secrets_manager.metadata.uid
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The activation resource already depends on the keeper because it references the keeper&amp;rsquo;s &lt;code&gt;uid&lt;/code&gt;.
Any secure value that should use this keeper must depend on the activation, otherwise Terraform can create the secret while the system keeper is still active:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_apps_secret_securevalue_v1beta1&amp;#34; &amp;#34;external_api_key&amp;#34; {
  metadata {
    uid = &amp;#34;external-api-key&amp;#34;
  }

  spec {
    description = &amp;#34;External API key&amp;#34;
    value       = var.external_api_key
    decrypters  = [&amp;#34;synthetic-monitoring&amp;#34;]
  }

  depends_on = [grafana_apps_secret_keeper_activation_v1beta1.aws_secrets_manager]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Keep the following points in mind for this resource:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Because a namespace has only one active keeper, applying an activation for a different keeper switches which keeper is active.&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;terraform destroy&lt;/code&gt; on the activation resource reverts the namespace to the built-in system keeper.
Destroying the keeper resource doesn&amp;rsquo;t deactivate it first; destroy the activation resource as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also set the active keeper outside Terraform, in the Grafana UI under &lt;strong&gt;Administration&lt;/strong&gt; &amp;gt; &lt;strong&gt;Secrets Management&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;After the keeper is active, Grafana routes new secure values to it automatically.
A &lt;code&gt;value&lt;/code&gt;-backed secure value like the one in &lt;a href=&#34;#define-a-secure-value&#34;&gt;Define a secure value&lt;/a&gt; needs no field changes to use the active keeper, but it still needs &lt;code&gt;depends_on&lt;/code&gt; if you create it in the same configuration as the activation.
Destroying a &lt;code&gt;value&lt;/code&gt;-backed secure value that lives in AWS Secrets Manager deletes the AWS secret immediately, with no recovery window.&lt;/p&gt;
&lt;p&gt;To reference a secret that already exists in AWS Secrets Manager instead of sending a new value, use &lt;code&gt;ref&lt;/code&gt; in place of &lt;code&gt;value&lt;/code&gt;.
Set &lt;code&gt;ref&lt;/code&gt; to the AWS secret name or the full ARN, not a path inside Grafana:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_apps_secret_securevalue_v1beta1&amp;#34; &amp;#34;db_password&amp;#34; {
  metadata {
    uid = &amp;#34;db-password&amp;#34;
  }

  spec {
    description = &amp;#34;Production DB password&amp;#34;
    ref         = &amp;#34;grafana-secrets-manager/stacks-&amp;lt;STACK_ID&amp;gt;/db-password/1&amp;#34;
    decrypters  = [&amp;#34;synthetic-monitoring&amp;#34;]
  }

  depends_on = [grafana_apps_secret_keeper_activation_v1beta1.aws_secrets_manager]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace &lt;em&gt;&lt;code&gt;&amp;lt;STACK_ID&amp;gt;&lt;/code&gt;&lt;/em&gt; with the same numeric stack ID you set on the provider.
You can also set &lt;code&gt;ref&lt;/code&gt; to the full secret ARN, for example &lt;code&gt;arn:aws:secretsmanager:&amp;lt;REGION&amp;gt;:&amp;lt;ACCOUNT_ID&amp;gt;:secret:grafana-secrets-manager/stacks-&amp;lt;STACK_ID&amp;gt;/db-password/1-AbCdEf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you use &lt;code&gt;ref&lt;/code&gt; while the system keeper is active, the API returns the following error:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;console&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-console&#34;&gt;tried to create secure value using reference with system keeper, references can only be used with 3rd party keepers&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you created a service account token, configured the Grafana provider, and provisioned a secure value with Terraform.
You also learned how to rotate and import secure values, and how to provision and activate a keeper to store secrets in an external secret manager.&lt;/p&gt;
&lt;p&gt;To learn more about managing Grafana Cloud using Terraform, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;next-steps&#34;&gt;Next steps&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;For the full secure value schema and more examples, refer to &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_securevalue_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_apps_secret_securevalue_v1beta1&lt;/code&gt; on the Terraform Registry&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For the full keeper schema, refer to &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_keeper_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_apps_secret_keeper_v1beta1&lt;/code&gt; on the Terraform Registry&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For the keeper activation resource, refer to &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_secret_keeper_activation_v1beta1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_apps_secret_keeper_activation_v1beta1&lt;/code&gt; on the Terraform Registry&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For concepts, permissions, and limits, refer to &lt;a href=&#34;/docs/grafana-cloud/platform/security-and-account-management/security-and-access/manage-secrets/&#34;&gt;Manage secrets&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For the underlying HTTP API, refer to the &lt;a href=&#34;/docs/grafana-cloud/developer-resources/api-reference/http-api/secrets_management/&#34;&gt;Secrets Management API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For more about write-only arguments, refer to &lt;a href=&#34;https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Ephemeral values&lt;/a&gt; in the Terraform documentation.&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="manage-secrets-in-grafana-cloud-using-terraform">Manage secrets in Grafana Cloud using Terraform&lt;/h1>
&lt;p>Use the Terraform Grafana provider to create and manage secure values in &lt;a href="/docs/grafana-cloud/platform/security-and-account-management/security-and-access/manage-secrets/">Grafana Secrets Management&lt;/a> as code.
With Terraform, you keep secrets such as API keys, tokens, passwords, and certificates in version-controlled, declarative infrastructure alongside the rest of your Grafana stack.&lt;/p></description></item><item><title>Manage Fleet Management in Grafana Cloud using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-fleet-management/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-fleet-management/</guid><content><![CDATA[&lt;h1 id=&#34;manage-fleet-management-in-grafana-cloud-using-terraform&#34;&gt;Manage Fleet Management in Grafana Cloud using Terraform&lt;/h1&gt;
&lt;p&gt;Learn how to create &lt;a href=&#34;/docs/grafana-cloud/send-data/fleet-management/&#34;&gt;Grafana Fleet Management&lt;/a&gt; collectors and pipelines in Grafana Cloud using Terraform.
This guide shows you how to create an access policy and a token for Fleet Management and &lt;a href=&#34;/docs/alloy/latest/&#34;&gt;Grafana Alloy&lt;/a&gt;, a collector with remote attributes, and a pipeline for profiling Alloy.&lt;/p&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account, as shown in &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/downloads&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/alloy/latest/set-up/install/&#34;&gt;Alloy&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;li&gt;Administrator permissions in your Grafana instance&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;All of the following Terraform configuration files should be saved in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configure-a-provider-for-grafana-cloud&#34;&gt;Configure a provider for Grafana Cloud&lt;/h2&gt;
&lt;p&gt;This Terraform configuration configures the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; to provide necessary authentication when interacting with the Cloud API.
The &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/data-sources/cloud_stack&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_stack&lt;/code&gt; (Data Source)&lt;/a&gt; is used to retrieve the user ID and URL details of your instance.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a Grafana Cloud access policy and token.
To create a new one, refer to &lt;a href=&#34;/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-policies/&#34;&gt;Grafana Cloud Access Policies&lt;/a&gt;.
Add your stack to the realms list.
The scopes needed for the examples in this guide are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;accesspolicies:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;accesspolicies:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;accesspolicies:delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stacks:read&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;cloud-provider.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
      version = &amp;#34;&amp;gt;= 3.19.0&amp;#34;
    }
  }
}

provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;cloud&amp;#34;

  cloud_access_policy_token = &amp;#34;&amp;lt;CLOUD_ACCESS_POLICY_TOKEN&amp;gt;&amp;#34;
}

data &amp;#34;grafana_cloud_stack&amp;#34; &amp;#34;stack&amp;#34; {
  provider = grafana.cloud

  slug = &amp;#34;&amp;lt;STACK_SLUG&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;CLOUD_ACCESS_POLICY_TOKEN&amp;gt;&lt;/code&gt; with the access policy token you created in the first step&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;STACK_SLUG&amp;gt;&lt;/code&gt; with your stack slug, which is the subdomain where your Grafana Cloud instance is available: &lt;code&gt;https://&amp;lt;STACK_SLUG&amp;gt;.grafana.net&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;create-an-access-policy-and-token-for-fleet-management&#34;&gt;Create an access policy and token for Fleet Management&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An access policy named &lt;code&gt;fleet-management-policy&lt;/code&gt; with &lt;code&gt;fleet-management:read&lt;/code&gt; and &lt;code&gt;fleet-management:write&lt;/code&gt; scopes, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_access_policy&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_access_policy&lt;/code&gt; (Resource)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A token named &lt;code&gt;fleet-management-token&lt;/code&gt;, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_access_policy_token&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_access_policy_token&lt;/code&gt; (Resource)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;fm-access-policy.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_cloud_access_policy&amp;#34; &amp;#34;fm_policy&amp;#34; {
  provider = grafana.cloud

  name   = &amp;#34;fleet-management-policy&amp;#34;
  region = data.grafana_cloud_stack.stack.region_slug

  scopes = [
    &amp;#34;fleet-management:read&amp;#34;,
    &amp;#34;fleet-management:write&amp;#34;
  ]

  realm {
    type       = &amp;#34;stack&amp;#34;
    identifier = data.grafana_cloud_stack.stack.id
  }
}

resource &amp;#34;grafana_cloud_access_policy_token&amp;#34; &amp;#34;fm_token&amp;#34; {
  provider = grafana.cloud

  name             = &amp;#34;fleet-management-token&amp;#34;
  region           = grafana_cloud_access_policy.fm_policy.region
  access_policy_id = grafana_cloud_access_policy.fm_policy.policy_id
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configure-a-provider-for-fleet-management&#34;&gt;Configure a provider for Fleet Management&lt;/h2&gt;
&lt;p&gt;This Terraform configuration configures the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; to provide necessary authentication when interacting with the Fleet Management API.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;fm-provider.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;locals {
  fm_id    = data.grafana_cloud_stack.stack.fleet_management_user_id
  fm_token = grafana_cloud_access_policy_token.fm_token.token
  fm_url   = data.grafana_cloud_stack.stack.fleet_management_url
}

provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;fm&amp;#34;

  fleet_management_auth = &amp;#34;${local.fm_id}:${local.fm_token}&amp;#34;
  fleet_management_url  = local.fm_url
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;create-a-fleet-management-collector&#34;&gt;Create a Fleet Management collector&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates a collector with a remote attribute, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/fleet_management_collector&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_fleet_management_collector&lt;/code&gt; (Resource)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This configuration only preregisters the collector.
You must complete the &lt;a href=&#34;#run-alloy&#34;&gt;Run Alloy&lt;/a&gt; step for the collector to register with Fleet Management and be assigned remote attributes.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;fm-collector.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_fleet_management_collector&amp;#34; &amp;#34;fm_collector&amp;#34; {
  provider = grafana.fm

  id = &amp;#34;prod_collector&amp;#34;
  remote_attributes = {
    &amp;#34;env&amp;#34; = &amp;#34;PROD&amp;#34;
  }
  enabled = true
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;create-a-fleet-management-pipeline&#34;&gt;Create a Fleet Management pipeline&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates a pipeline for Alloy profiling with a matcher for the collector declared in the previous step, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/fleet_management_pipeline&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_fleet_management_pipeline&lt;/code&gt; (Resource)&lt;/a&gt;.
The pipeline writes the profiles to &lt;a href=&#34;/docs/grafana-cloud/monitor-applications/profiles/&#34;&gt;Grafana Cloud Profiles&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;profiling.alloy.tftpl&lt;/code&gt; and add the following content:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;// This pipeline scrapes pprof Go profiles from Alloy and sends them to Pyroscope.
//
// It requires the following environment variables to be set where Alloy is running:
//   Required:
//     * GCLOUD_RW_API_KEY: The Grafana Cloud API key with write access to Pyroscope.
//   Optional:
//     * ALLOY_ADDRESS: The address Alloy listens on. Defaults to 127.0.0.1:12345.
pyroscope.scrape &amp;#34;alloy&amp;#34; {
    targets = [
        {
            &amp;#34;__address__&amp;#34; = coalesce(
                sys.env(&amp;#34;ALLOY_ADDRESS&amp;#34;),
                &amp;#34;127.0.0.1:12345&amp;#34;,
            ),
            &amp;#34;service_name&amp;#34; = &amp;#34;alloy&amp;#34;,
        },
    ]
    forward_to = [pyroscope.write.grafana_cloud.receiver]

    profiling_config {
        profile.process_cpu {
            enabled = true
        }

        profile.memory {
            enabled = true
        }

        profile.mutex {
            enabled = true
        }

        profile.block {
            enabled = true
        }

        profile.goroutine {
            enabled = true
        }
    }
}

pyroscope.write &amp;#34;grafana_cloud&amp;#34; {
    endpoint {
        url = &amp;#34;${profiles_url}&amp;#34;

        basic_auth {
            username = &amp;#34;${profiles_id}&amp;#34;
            password = sys.env(&amp;#34;GCLOUD_RW_API_KEY&amp;#34;)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;fm-pipeline.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;locals {
  profiles_id  = data.grafana_cloud_stack.stack.profiles_user_id
  profiles_url = data.grafana_cloud_stack.stack.profiles_url
}

resource &amp;#34;grafana_fleet_management_pipeline&amp;#34; &amp;#34;pipeline&amp;#34; {
  provider = grafana.fm

  name = &amp;#34;profiling&amp;#34;
  contents = templatefile(
    &amp;#34;profiling.alloy.tftpl&amp;#34;,
    {
      profiles_id  = local.profiles_id,
      profiles_url = local.profiles_url,
    },
  )
  matchers = [
    &amp;#34;env=\&amp;#34;PROD\&amp;#34;&amp;#34;
  ]
  enabled = true
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;create-an-access-policy-and-token-for-alloy&#34;&gt;Create an access policy and token for Alloy&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An access policy named &lt;code&gt;alloy-policy&lt;/code&gt; with &lt;code&gt;set:alloy-data-write&lt;/code&gt; scope, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_access_policy&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_access_policy&lt;/code&gt; (Resource)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A token named &lt;code&gt;alloy-token&lt;/code&gt;, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_access_policy_token&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_access_policy_token&lt;/code&gt; (Resource)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;alloy-access-policy.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_cloud_access_policy&amp;#34; &amp;#34;alloy_policy&amp;#34; {
  provider = grafana.cloud

  name   = &amp;#34;alloy-policy&amp;#34;
  region = data.grafana_cloud_stack.stack.region_slug

  scopes = [
    &amp;#34;set:alloy-data-write&amp;#34;
  ]

  realm {
    type       = &amp;#34;stack&amp;#34;
    identifier = data.grafana_cloud_stack.stack.id
  }
}

resource &amp;#34;grafana_cloud_access_policy_token&amp;#34; &amp;#34;alloy_token&amp;#34; {
  provider = grafana.cloud

  name             = &amp;#34;alloy-token&amp;#34;
  region           = grafana_cloud_access_policy.alloy_policy.region
  access_policy_id = grafana_cloud_access_policy.alloy_policy.policy_id
}

output &amp;#34;alloy_token&amp;#34; {
  value     = grafana_cloud_access_policy_token.alloy_token.token
  sensitive = true
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;create-a-configuration-file-for-alloy&#34;&gt;Create a configuration file for Alloy&lt;/h2&gt;
&lt;p&gt;This Terraform configuration creates an Alloy configuration file with the &lt;a href=&#34;/docs/grafana-cloud/send-data/alloy/reference/config-blocks/remotecfg/&#34;&gt;&lt;code&gt;remotecfg&lt;/code&gt; block&lt;/a&gt; for Fleet Management, using &lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;local_file&lt;/code&gt; (Resource)&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;config.alloy.tftpl&lt;/code&gt; and add the following content:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;remotecfg {
    id             = &amp;#34;${collector_id}&amp;#34;
    url            = &amp;#34;${fm_url}&amp;#34;
    poll_frequency = &amp;#34;60s&amp;#34;

    basic_auth {
        username = &amp;#34;${fm_id}&amp;#34;
        password = sys.env(&amp;#34;GCLOUD_RW_API_KEY&amp;#34;)
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;alloy-config.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;local_file&amp;#34; &amp;#34;alloy_config&amp;#34; {
  filename = &amp;#34;&amp;lt;ALLOY_CONFIG_PATH&amp;gt;&amp;#34;
  content = templatefile(
    &amp;#34;config.alloy.tftpl&amp;#34;,
    {
      collector_id = &amp;#34;prod_collector&amp;#34;,
      fm_id        = local.fm_id,
      fm_url       = local.fm_url,
    },
  )
  directory_permission = &amp;#34;0644&amp;#34;
  file_permission      = &amp;#34;0644&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;ALLOY_CONFIG_PATH&amp;gt;&lt;/code&gt; with the path the Alloy configuration file should be written to, for example &lt;code&gt;config.alloy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;apply-the-terraform-configuration&#34;&gt;Apply the Terraform configuration&lt;/h2&gt;
&lt;p&gt;In a terminal, run the following commands from the directory where all of the configuration files are located.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Initialize a working directory containing Terraform configuration files:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform init&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Preview the Terraform changes:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform plan&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply the configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform apply&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;run-alloy&#34;&gt;Run Alloy&lt;/h2&gt;
&lt;p&gt;To learn how to start or restart Alloy, refer to &lt;a href=&#34;/docs/alloy/latest/set-up/run/&#34;&gt;Run Grafana Alloy&lt;/a&gt;.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The variable &lt;code&gt;GCLOUD_RW_API_KEY&lt;/code&gt; must be set in the environment where Alloy is running for the remote configuration in this example to work.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Run the following command to view the Alloy token:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform output -raw alloy_token&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the environment variable &lt;code&gt;GCLOUD_RW_API_KEY&lt;/code&gt; to the value from the first step.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run Alloy.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After you apply the changes in the Terraform configurations and run Alloy, you should be able to verify the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A collector is added to the Fleet Management &lt;strong&gt;Inventory tab&lt;/strong&gt;:&lt;/p&gt;
&lt;figure
      class=&#34;figure-wrapper figure-wrapper__lightbox w-100p &#34;
      style=&#34;max-width: 2222px;&#34;
      itemprop=&#34;associatedMedia&#34;
      itemscope=&#34;&#34;
      itemtype=&#34;http://schema.org/ImageObject&#34;
    &gt;&lt;a
          class=&#34;lightbox-link&#34;
          href=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png&#34;
          itemprop=&#34;contentUrl&#34;
        &gt;&lt;div class=&#34;img-wrapper w-100p h-auto&#34;&gt;&lt;img
            class=&#34;lazyload &#34;
            data-src=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png&#34;data-srcset=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png?w=320 320w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png?w=550 550w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png?w=750 750w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png?w=900 900w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png?w=1040 1040w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png?w=1240 1240w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png?w=1920 1920w&#34;data-sizes=&#34;auto&#34;alt=&#34;The Inventory screen in the Fleet Management interface in Grafana Cloud which shows that a new collector called `prod_collector` is registered with attribute `env=PROD`, has a healthy status, and was last modified a few seconds ago.&#34;width=&#34;2222&#34;height=&#34;978&#34;/&gt;
          &lt;noscript&gt;
            &lt;img
              src=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-collector.png&#34;
              alt=&#34;The Inventory screen in the Fleet Management interface in Grafana Cloud which shows that a new collector called `prod_collector` is registered with attribute `env=PROD`, has a healthy status, and was last modified a few seconds ago.&#34;width=&#34;2222&#34;height=&#34;978&#34;/&gt;
          &lt;/noscript&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A pipeline is added to the Fleet Management &lt;strong&gt;Remote configuration tab&lt;/strong&gt;:&lt;/p&gt;
&lt;figure
      class=&#34;figure-wrapper figure-wrapper__lightbox w-100p &#34;
      style=&#34;max-width: 2228px;&#34;
      itemprop=&#34;associatedMedia&#34;
      itemscope=&#34;&#34;
      itemtype=&#34;http://schema.org/ImageObject&#34;
    &gt;&lt;a
          class=&#34;lightbox-link&#34;
          href=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png&#34;
          itemprop=&#34;contentUrl&#34;
        &gt;&lt;div class=&#34;img-wrapper w-100p h-auto&#34;&gt;&lt;img
            class=&#34;lazyload &#34;
            data-src=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png&#34;data-srcset=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png?w=320 320w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png?w=550 550w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png?w=750 750w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png?w=900 900w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png?w=1040 1040w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png?w=1240 1240w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png?w=1920 1920w&#34;data-sizes=&#34;auto&#34;alt=&#34;The Remote configuration screen in the Fleet Management interface in Grafana Cloud which shows that a new configuration pipeline called `profiling` is active and was last modified a few seconds ago.&#34;width=&#34;2228&#34;height=&#34;904&#34;/&gt;
          &lt;noscript&gt;
            &lt;img
              src=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-pipeline.png&#34;
              alt=&#34;The Remote configuration screen in the Fleet Management interface in Grafana Cloud which shows that a new configuration pipeline called `profiling` is active and was last modified a few seconds ago.&#34;width=&#34;2228&#34;height=&#34;904&#34;/&gt;
          &lt;/noscript&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alloy profiles are being exported to Grafana Cloud Profiles:&lt;/p&gt;
&lt;figure
      class=&#34;figure-wrapper figure-wrapper__lightbox w-100p &#34;
      style=&#34;max-width: 2228px;&#34;
      itemprop=&#34;associatedMedia&#34;
      itemscope=&#34;&#34;
      itemtype=&#34;http://schema.org/ImageObject&#34;
    &gt;&lt;a
          class=&#34;lightbox-link&#34;
          href=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png&#34;
          itemprop=&#34;contentUrl&#34;
        &gt;&lt;div class=&#34;img-wrapper w-100p h-auto&#34;&gt;&lt;img
            class=&#34;lazyload &#34;
            data-src=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png&#34;data-srcset=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png?w=320 320w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png?w=550 550w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png?w=750 750w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png?w=900 900w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png?w=1040 1040w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png?w=1240 1240w, /media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png?w=1920 1920w&#34;data-sizes=&#34;auto&#34;alt=&#34;A dashboard in Grafana Cloud which shows Alloy profiling data, including graphs for CPU and memory.&#34;width=&#34;2228&#34;height=&#34;1406&#34;/&gt;
          &lt;noscript&gt;
            &lt;img
              src=&#34;/media/docs/fleet-management/screenshot-fleet-management-terraform-validate-profiles.png&#34;
              alt=&#34;A dashboard in Grafana Cloud which shows Alloy profiling data, including graphs for CPU and memory.&#34;width=&#34;2228&#34;height=&#34;1406&#34;/&gt;
          &lt;/noscript&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you created an access policy and a token for Fleet Management and Alloy, a collector with remote attributes, and a pipeline for profiling Alloy, all using Terraform.&lt;/p&gt;
&lt;p&gt;To learn more about managing Grafana Cloud using Terraform, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="manage-fleet-management-in-grafana-cloud-using-terraform">Manage Fleet Management in Grafana Cloud using Terraform&lt;/h1>
&lt;p>Learn how to create &lt;a href="/docs/grafana-cloud/send-data/fleet-management/">Grafana Fleet Management&lt;/a> collectors and pipelines in Grafana Cloud using Terraform.
This guide shows you how to create an access policy and a token for Fleet Management and &lt;a href="/docs/alloy/latest/">Grafana Alloy&lt;/a>, a collector with remote attributes, and a pipeline for profiling Alloy.&lt;/p></description></item><item><title>Manage Frontend Observability in Grafana Cloud with Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-frontend-observability/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-frontend-observability/</guid><content><![CDATA[&lt;h1 id=&#34;manage-frontend-observability-in-grafana-cloud-with-terraform&#34;&gt;Manage Frontend Observability in Grafana Cloud with Terraform&lt;/h1&gt;
&lt;p&gt;Learn how to use Terraform to manage &lt;a href=&#34;/docs/grafana-cloud/frontend-observability/&#34;&gt;Grafana Frontend Observability&lt;/a&gt; resources, such as your applications.
This guide shows you how to create an access policy and a token for Frontend Observability so that you can connect to the Frontend Observability API.&lt;/p&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account, as shown in &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/downloads&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;li&gt;Administrator permissions in your Grafana instance&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;All of the following Terraform configuration files should be saved in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configure-a-provider-for-grafana-cloud&#34;&gt;Configure a provider for Grafana Cloud&lt;/h2&gt;
&lt;p&gt;This Terraform configuration configures the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; to provide necessary authentication when interacting with the Cloud API.
The &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/data-sources/cloud_stack&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_stack&lt;/code&gt; (Data Source)&lt;/a&gt; is used to retrieve the details of your instance.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a Grafana Cloud access policy and token.
To create a new one, refer to &lt;a href=&#34;/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-policies/&#34;&gt;Grafana Cloud Access Policies&lt;/a&gt;.
Add your stack to the realms list.
The scopes needed for the examples in this guide are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;accesspolicies:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;accesspolicies:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;accesspolicies:delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dashboards:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dashboards:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dashboards:delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orgs:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orgs:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stacks:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stacks:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stacks:delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack-dashboards:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack-dashboards:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack-dashboards:delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack-service-accounts:write&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;cloud-provider.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
    }
  }
}

provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;cloud&amp;#34;

  cloud_access_policy_token = &amp;#34;&amp;lt;CLOUD_ACCESS_POLICY_TOKEN&amp;gt;&amp;#34;
}

data &amp;#34;grafana_cloud_stack&amp;#34; &amp;#34;stack&amp;#34; {
  provider = grafana.cloud

  slug = &amp;#34;&amp;lt;STACK_SLUG&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;CLOUD_ACCESS_POLICY_TOKEN&amp;gt;&lt;/code&gt; with the access policy token you created in the first step&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;STACK_SLUG&amp;gt;&lt;/code&gt; with your stack slug, which is the subdomain where your Grafana Cloud instance is available: &lt;code&gt;https://&amp;lt;STACK_SLUG&amp;gt;.grafana.net&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;create-an-access-policy-and-token-for-frontend-observability&#34;&gt;Create an access policy and token for Frontend Observability&lt;/h2&gt;
&lt;p&gt;You must create a Terraform configuration with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An access policy with &lt;code&gt;frontend-observability:read&lt;/code&gt;, &lt;code&gt;frontend-observability:write&lt;/code&gt;, and &lt;code&gt;frontend-observability:delete&lt;/code&gt; scopes, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_access_policy&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_access_policy&lt;/code&gt; (Resource)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A token named &lt;code&gt;frontend_o11y_api_access_token&lt;/code&gt;, using &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_access_policy_token&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_cloud_access_policy_token&lt;/code&gt; (Resource)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;configure-the-provider-to-use-the-frontend-observability-api&#34;&gt;Configure the provider to use the Frontend Observability API&lt;/h2&gt;
&lt;p&gt;After you have created the token, you can configure the provider as follows:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;provider &amp;#34;grafana&amp;#34; {
  frontend_o11y_api_access_token = &amp;#34;&amp;lt;access token from previous step&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you created an access policy and a token for Frontend Observability using Terraform.&lt;/p&gt;
&lt;p&gt;To learn more about managing Grafana Cloud using Terraform, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="manage-frontend-observability-in-grafana-cloud-with-terraform">Manage Frontend Observability in Grafana Cloud with Terraform&lt;/h1>
&lt;p>Learn how to use Terraform to manage &lt;a href="/docs/grafana-cloud/frontend-observability/">Grafana Frontend Observability&lt;/a> resources, such as your applications.
This guide shows you how to create an access policy and a token for Frontend Observability so that you can connect to the Frontend Observability API.&lt;/p></description></item><item><title>Manage Cloud Provider Observability in Grafana Cloud using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-cloud-provider-o11y/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-cloud-provider-o11y/</guid><content><![CDATA[&lt;h1 id=&#34;manage-cloud-provider-observability-in-grafana-cloud-using-terraform&#34;&gt;Manage Cloud Provider Observability in Grafana Cloud using Terraform&lt;/h1&gt;
&lt;p&gt;Manage Cloud Provider Observability, including Amazon CloudWatch and Microsoft Azure resources, in Grafana Cloud using Terraform.
For more information on Cloud Provider Observability, refer to the &lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/&#34;&gt;Cloud Provider Observability&lt;/a&gt; documentation.&lt;/p&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account
&lt;ul&gt;
&lt;li&gt;For more information on setting up a Grafana Cloud account, refer to &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Terraform installed on your machine
&lt;ul&gt;
&lt;li&gt;For more information on how to install Terraform, refer to the &lt;a href=&#34;https://developer.hashicorp.com/terraform/install&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform install documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Administrator permissions in your Grafana instance
&lt;ul&gt;
&lt;li&gt;For more information on assigning Grafana RBAC roles, refer to &lt;a href=&#34;/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-control/assign-rbac-roles/&#34;&gt;Assign RBAC roles&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Save all of the following Terraform configuration files in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configure-authentication-for-the-grafana-provider&#34;&gt;Configure authentication for the Grafana Provider&lt;/h2&gt;
&lt;p&gt;The Grafana Provider is a logical abstraction of an upstream API that you can use to interact with Grafana Cloud resources.
You must configure it with the following information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud access policy token that includes the permissions the provider needs to access the Grafana Cloud Provider API.&lt;/li&gt;
&lt;li&gt;A regional cloud provider API endpoint to establish which Grafana Cloud stack you are accessing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To configure authentication for the Grafana Provider:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a Grafana Cloud access policy and token.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To create an access policy for your organization, refer to the &lt;a href=&#34;/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-policies/create-access-policies/#create-an-access-policy-for-a-stack&#34;&gt;Create an access policy for a stack steps&lt;/a&gt; and use the following scopes listed for the supported Amazon CloudWatch or Microsoft Azure resources:
&lt;ul&gt;
&lt;li&gt;Amazon CloudWatch
&lt;ul&gt;
&lt;li&gt;Metrics scrape or resource metadata scrape
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;integration-management:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration-management:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stacks:read&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Metric streams
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;metrics:write&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ALB access logs, logs with Lambda, or logs with Amazon Data Firehose
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;logs:write&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Microsoft Azure
&lt;ul&gt;
&lt;li&gt;Serverless metrics
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;integration-management:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration-management:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stacks:read&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Logs with Azure functions
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;logs:write&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Obtain the regional Cloud Provider API endpoint.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To obtain the regional Cloud provider API endpoint, use your access policy token and the following command to return a list of all of the Grafana stacks you own, along with their respective Cloud Provider API hostnames:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -sH &amp;#34;Authorization: Bearer @@@GRAFANA_CLOUD_ACCESS_POLICY_TOKEN@@@&amp;#34; &amp;#34;https://grafana.com/api/instances&amp;#34; | \
jq &amp;#39;[.items[]|{stackName: .slug, clusterName:.clusterSlug, cloudProviderAPIURL: &amp;#34;https://cloud-provider-api-\(.clusterSlug).grafana.net&amp;#34;}]&amp;#39;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;If this endpoint does not work, your Grafana Cloud Provider API endpoint may be using the new URL format.
For more information on Grafana Cloud URLs, refer to &lt;a href=&#34;/docs/grafana-cloud/security-and-account-management/region-url-formats/&#34;&gt;Determine Grafana Cloud URLs based on region&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;cloud-provider.tf&lt;/code&gt; and add the following code block:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;tf&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-tf&#34;&gt;terraform {
    required_providers {
    grafana = {
        source  = &amp;#34;grafana/grafana&amp;#34;
    }
  }
}

provider &amp;#34;grafana&amp;#34; {
    cloud_api_url      = &amp;#34;&amp;lt;@@@CLOUD_PROVIDER_API_URL@@@&amp;#34;
    cloud_access_policy_token     = &amp;#34;@@@CLOUD_ACCESS_POLICY_TOKEN@@@&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;variables.tf&lt;/code&gt; file and paste the &lt;code&gt;CLOUD_ACCESS_POLICY_TOKEN&lt;/code&gt; and &lt;code&gt;CLOUD_PROVIDER_API_URL&lt;/code&gt; variables with your values.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the following Terraform command:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;tf&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-tf&#34;&gt;terraform apply -var-file=&amp;#34;variables.tf&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configure-your-resources&#34;&gt;Configure your resources&lt;/h2&gt;
&lt;p&gt;To find instructions for configuring specific Amazon CloudWatch and Microsoft Azure resources in Cloud Provider Observability using Terraform, refer to the following documents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Amazon CloudWatch
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/aws/cloudwatch-metrics/config-cw-metric-scrape/&#34;&gt;Metrics scrape&lt;/a&gt;: Pull CloudWatch metrics from multiple regions for your AWS account, without needing to install Grafana Alloy.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/aws/cloudwatch-metrics/config-cw-metric-streams/#configure-metric-streams-with-terraform&#34;&gt;Metric streams&lt;/a&gt;: Push metrics with CloudWatch metric streams using Amazon Data Firehose, providing real-time insights and scalability while simplifying configuration and reducing cost and manual effort.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/aws/logs/cloudwatch-logs/config-alb-access-logs-lambda/#configure-with-terraform&#34;&gt;ALB access logs&lt;/a&gt;: Send application load balancer access logs from AWS to Grafana Cloud using a Lambda function.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/aws/logs/cloudwatch-logs/config-cw-logs-lambda/#configure-with-terraform&#34;&gt;Logs with Lambda&lt;/a&gt;: Send logs to Grafana Cloud from multiple AWS services using a lambda-promtail function.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/aws/logs/firehose-logs/config-firehose-logs/#configure-with-terraform&#34;&gt;Logs with Amazon Data Firehose&lt;/a&gt;: Send logs from AWS to Grafana Cloud with Amazon Data Firehose and minimal infrastructure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Microsoft Azure
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/azure/collect-azure-serverless/config-azure-metrics-serverless/&#34;&gt;Serverless metrics&lt;/a&gt;: Monitor your Azure resources without the need to configure or deploy a collector by using Cloud Provider Observability.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/azure/config-azure-logs-azure-function/&#34;&gt;Logs with Azure functions&lt;/a&gt;: Send Azure event logs to a Loki endpoint using an Azure function that subscribes to an Azure event hub.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;grafana-cloud-provider-resources&#34;&gt;Grafana cloud provider resources&lt;/h2&gt;
&lt;p&gt;You can define the following Cloud Provider Observability resources and data sources using Terraform:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Resource name&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafana_cloud_provider_aws_account&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Represents an AWS IAM role that authorizes Grafana Cloud to pull Amazon CloudWatch metrics for a set of regions. Usually, there&amp;rsquo;s one of these resources per configured AWS account. For a full reference of this resource, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_provider_aws_account&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform Grafana Provider reference documentation&lt;/a&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafana_cloud_provider_aws_cloudwatch_scrape_job&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Represents a Grafana AWS scrape job. This configures Grafana to fetch a list of metrics and statistics for one or many AWS services, and for a given &lt;code&gt;grafana_cloud_provider_aws_account&lt;/code&gt;. For a full reference of this resource, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_provider_aws_cloudwatch_scrape_job&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform Grafana Provider reference documentation&lt;/a&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafana_cloud_provider_aws_resource_metadata_scrape_job&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Represents a Grafana AWS Resource Metadata scrape job. This resource configures Grafana to fetch resource metadata for one or multiple AWS services, for a given &lt;code&gt;grafana_cloud_provider_aws_account&lt;/code&gt;. For a full reference of this resource, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_provider_aws_resource_metadata_scrape_job&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform Grafana Provider reference documentation&lt;/a&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafana_cloud_provider_azure_credential&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;A resource representing an Azure Service Principal credential used by Grafana Cloud to pull Azure Monitor metrics from one or more subscriptions. For a full reference of this resource, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_provider_azure_credential&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform Grafana Provider resource documentation&lt;/a&gt;.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;]]></content><description>&lt;h1 id="manage-cloud-provider-observability-in-grafana-cloud-using-terraform">Manage Cloud Provider Observability in Grafana Cloud using Terraform&lt;/h1>
&lt;p>Manage Cloud Provider Observability, including Amazon CloudWatch and Microsoft Azure resources, in Grafana Cloud using Terraform.
For more information on Cloud Provider Observability, refer to the &lt;a href="/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/">Cloud Provider Observability&lt;/a> documentation.&lt;/p></description></item><item><title>Install plugins in Grafana Cloud using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-plugins/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/terraform-plugins/</guid><content><![CDATA[&lt;h1 id=&#34;install-plugins-in-grafana-cloud-using-terraform&#34;&gt;Install plugins in Grafana Cloud using Terraform&lt;/h1&gt;
&lt;p&gt;This guide shows you how to install plugins in Grafana Cloud using Terraform. For more information about Grafana plugins, refer to the &lt;a href=&#34;/docs/grafana-cloud/introduction/find-and-use-plugins/&#34;&gt;Find and use Grafana plugins&lt;/a&gt; documentation.&lt;/p&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account; for more information on setting up a Grafana Cloud account, refer to &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Terraform installed on your machine; for more information on how to install Terraform, refer to the &lt;a href=&#34;https://developer.hashicorp.com/terraform/install&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform install documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Administrator permissions in your Grafana instance; for more information on assigning Grafana RBAC roles, refer to &lt;a href=&#34;/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-control/assign-rbac-roles/&#34;&gt;Assign RBAC roles&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Save all of the following Terraform configuration files in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configure-the-grafana-provider&#34;&gt;Configure the Grafana provider&lt;/h2&gt;
&lt;p&gt;Use this Terraform configuration to set up the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; to provide the authentication required to manage plugin resources.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a service account and token in Grafana. For more information on creating a service account and token, refer to &lt;a href=&#34;/docs/grafana/latest/administration/service-accounts/#service-account-tokens&#34;&gt;Service account tokens&lt;/a&gt;. You can also refer to &lt;a href=&#34;../terraform-cloud-stack/&#34;&gt;Creating and managing a Grafana Cloud stack using Terraform&lt;/a&gt; to set up a service account and a token.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure that the token has the following permissions:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;stack-plugins:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack-plugins:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack-plugins:delete&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next, create a file named &lt;code&gt;main.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;   terraform {
     required_providers {
       grafana = {
         source  = &amp;#34;grafana/grafana&amp;#34;
         version = &amp;#34;&amp;gt;= 4.5.3&amp;#34;
       }
     }
   }

   provider &amp;#34;grafana&amp;#34; {
     cloud_api_url      = &amp;#34;&amp;lt;Stack-URL&amp;gt;&amp;#34;
     cloud_access_policy_token     = &amp;#34;&amp;lt;Service-account-token&amp;gt;&amp;#34;
   }&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Stack-URL&lt;/code&gt; with the URL of your Grafana stack, for example &lt;code&gt;https://my-stack.grafana.net/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Service-account-token&lt;/code&gt; with the service account token that you created&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;create-new-plugin-resource&#34;&gt;Create new plugin resource&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;plugins.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_cloud_plugin_installation&amp;#34; &amp;#34;grafana-clock-panel&amp;#34; {
  stack_slug   = &amp;#34;&amp;lt;Your-Stack-Slug&amp;gt;&amp;#34;
  slug         = &amp;#34;grafana-clock-panel&amp;#34;
  version      = &amp;#34;latest&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you learned how to install a plugin in Grafana Cloud using Terraform.&lt;/p&gt;
&lt;p&gt;To learn more about plugin installation, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_plugin_installation&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider documentation&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="install-plugins-in-grafana-cloud-using-terraform">Install plugins in Grafana Cloud using Terraform&lt;/h1>
&lt;p>This guide shows you how to install plugins in Grafana Cloud using Terraform. For more information about Grafana plugins, refer to the &lt;a href="/docs/grafana-cloud/introduction/find-and-use-plugins/">Find and use Grafana plugins&lt;/a> documentation.&lt;/p></description></item><item><title>Manage saved queries using Terraform</title><link>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/manage-saved-queries/</link><pubDate>Tue, 18 Aug 2026 10:15:08 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/infrastructure-as-code/terraform/manage-saved-queries/</guid><content><![CDATA[&lt;h1 id=&#34;manage-saved-queries-using-terraform&#34;&gt;Manage saved queries using Terraform&lt;/h1&gt;
&lt;p&gt;This guide shows you how to manage 
    &lt;a href=&#34;/docs/grafana/v13.2/visualizations/panels-visualizations/query-transform-data/#saved-queries&#34;&gt;saved queries&lt;/a&gt;, also known as the query library, using the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana Terraform provider&lt;/a&gt;. Managing saved queries as code lets you version-control your query library and keep it consistent across Grafana instances.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Saved queries are only available on Grafana Enterprise and Grafana Cloud.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Enterprise or Grafana Cloud instance. For more information on setting up a Grafana Cloud account, refer to &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Terraform installed on your machine. For more information on how to install Terraform, refer to the &lt;a href=&#34;https://developer.hashicorp.com/terraform/install&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform install documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A service account token with the &lt;strong&gt;Writer&lt;/strong&gt; role for saved queries. For more information, refer to 
    &lt;a href=&#34;/docs/grafana/v13.2/visualizations/panels-visualizations/query-transform-data/#roles-permissions-and-rbac&#34;&gt;Roles, permissions, and RBAC&lt;/a&gt; and 
    &lt;a href=&#34;/docs/grafana/v13.2/administration/service-accounts/#service-account-tokens&#34;&gt;Service account tokens&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;configure-the-grafana-provider&#34;&gt;Configure the Grafana provider&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;main.tf&lt;/code&gt; and add the following to set up the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; with the authentication required to manage saved queries:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
      version = &amp;#34;&amp;gt;= 4.44.0&amp;#34;
    }
  }
}

provider &amp;#34;grafana&amp;#34; {
  url  = &amp;#34;&amp;lt;Grafana-URL&amp;gt;&amp;#34;
  auth = &amp;#34;&amp;lt;Service-account-token&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Grafana-URL&lt;/code&gt; with the URL of your Grafana instance, for example &lt;code&gt;https://my-stack.grafana.net/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Service-account-token&lt;/code&gt; with the service account token that you created&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;create-a-saved-query-resource&#34;&gt;Create a saved query resource&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;saved-queries.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_apps_queries_query_v1&amp;#34; &amp;#34;example&amp;#34; {
  metadata {
    uid = &amp;#34;example-saved-query&amp;#34;
  }

  spec {
    title       = &amp;#34;Requests per second&amp;#34;
    description = &amp;#34;Prometheus rate of HTTP requests&amp;#34;
    is_visible  = true
    tags        = [&amp;#34;http&amp;#34;, &amp;#34;prometheus&amp;#34;]

    targets {
      properties_json = jsonencode({
        refId = &amp;#34;A&amp;#34;
        expr  = &amp;#34;rate(http_requests_total[$__rate_interval])&amp;#34;
        datasource = {
          type = &amp;#34;prometheus&amp;#34;
          uid  = &amp;#34;my-prometheus-uid&amp;#34;
        }
      })
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Because the shape of a data source query depends on the data source, the query stored in each target (&lt;code&gt;properties_json&lt;/code&gt;), a target&amp;rsquo;s variable replacements (&lt;code&gt;variables_json&lt;/code&gt;), and a variable&amp;rsquo;s value list (&lt;code&gt;value_list_definition_json&lt;/code&gt;) are passed as raw JSON strings. Use &lt;code&gt;jsonencode()&lt;/code&gt; to construct them.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;spec&lt;/code&gt; block supports the following fields:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Field&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The display name of the saved query. Required.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;A longer description of the saved query.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;is_visible&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Whether the saved query is visible in the query library.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;is_locked&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Whether the saved query is locked and can&amp;rsquo;t be edited in the UI. This is for UI display only, not for security.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The tags used to filter the saved query.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;targets&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The query targets that make up the saved query. At least one target is required.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;vars&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The template variables that can be interpolated into the query targets.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;For the complete schema, refer to the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/apps_queries_query_v1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;grafana_apps_queries_query_v1&lt;/code&gt; resource documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;import-an-existing-saved-query&#34;&gt;Import an existing saved query&lt;/h2&gt;
&lt;p&gt;To bring an existing saved query under Terraform management, import it using its UID:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform import grafana_apps_queries_query_v1.example example-saved-query&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this guide, you learned how to create and import saved queries using Terraform.&lt;/p&gt;
&lt;p&gt;To learn more about saved queries, refer to 
    &lt;a href=&#34;/docs/grafana/v13.2/visualizations/panels-visualizations/query-transform-data/#saved-queries&#34;&gt;Saved queries&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="manage-saved-queries-using-terraform">Manage saved queries using Terraform&lt;/h1>
&lt;p>This guide shows you how to manage
&lt;a href="/docs/grafana/v13.2/visualizations/panels-visualizations/query-transform-data/#saved-queries">saved queries&lt;/a>, also known as the query library, using the &lt;a href="https://registry.terraform.io/providers/grafana/grafana/latest/docs" target="_blank" rel="noopener noreferrer">Grafana Terraform provider&lt;/a>. Managing saved queries as code lets you version-control your query library and keep it consistent across Grafana instances.&lt;/p></description></item></channel></rss>