Terraform CDK Azure Blob Storage Backend
Published: 2025-03-07
Intro
In a previous post I setup CDK for Terraform using a local state backend.
In this post, I will show you how to utilize an Azure Blob storage container as a backend for CDKTF. The post, follows on from the previous post, so check that out for details on setting up the environment.
Software
The following software was used in this post.
- Ubuntu - 24.04
- NodeJS - v22.14.0
- NPM - v10.9.2
- fnm - v1.38.1
- Typescript - v5.8.2
- TerraformCLI - v1.10.5
- TerraformCDK - v0.20.11
- Azure CLI - v2.68.0
Setup
Azure
You will need to create a storage account to store your TF State in Azure. There are a few ways to do this, you can click through the web UI or use the Azure CLI.
Once it is created, browse to [storage-account-name] > Security + Networking > Access Keys to get an authentication key.
Set the key as an environment variable named ARM_ACCESS_KEY. This key is used to authenticate Terraform to the Storage Account.
Project Directory
If you followed along on the last post, you will have a cdktf.out/ directory. Delete that before continuing.
rm -rf cdktf.out/
Define Config
Create a main.ts file with the following contents that will utilise Azure Blob storage as a backend and create a resource group and virtual network.
import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import { App, TerraformStack, AzurermBackend, TerraformVariable } from "cdktf";
import { VirtualNetwork } from "@cdktf/provider-azurerm/lib/virtual-network"
import { ResourceGroup } from "@cdktf/provider-azurerm/lib/resource-group";
const resource_group = "rg-stuff-and-things";
const location = "australiaeast";
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
// Environment variabled prefixed with TF_VAR_ eg: TF_VAR_ARM_SUBSCRIPTION_ID
const armSubscriptionId = new TerraformVariable(this, "ARM_SUBSCRIPTION_ID", {
type: "string",
description: "Subscription UUID",
sensitive: true,
});
new AzurermBackend(this, {
resourceGroupName: "rg-tfstate",
storageAccountName: "sa-tfstate-42069",
containerName: "tfstate",
key: "stuff-and-things.terraform.tfstate",
});
new AzurermProvider(this, "AzureRm", {
features: [{}],
subscriptionId: process.env.ARM_SUBSCRIPTION_ID,
});
const resourceGroup = new ResourceGroup(this, "RgStuffAndThing", {
name: resource_group,
location: location,
});
new VirtualNetwork(this, "StuffAndThingVnet", {
name: "vnet-stuff-and-things",
location: resourceGroup.location,
resourceGroupName: resourceGroup.name,
addressSpace: ["10.0.0.0/24"],
});
}
}
const app = new App();
new MyStack(app, "azurecdk-tf");
app.synth();
Testing
Now with that in place, you can run a cdktf plan to confirm that access to the blog storage is working and deploy your infrastructure using an Azure Blob Storage backend.
Outro
In this post, we setup an Azure Blob Storage backend for use with CDKTF. A shared state backend allow multiple team members / platforms to work with a common centralised state file.
Peace out nerds. Stay weird ✌️
Links
https://github.com/cdktf/cdktf-provider-azurerm
https://developer.hashicorp.com/terraform/cdktf/concepts/remote-backends