Intro

Cloud Development Kit for Terraform (CDKTF) is an offering from Hashicorp, that allows you to define infrastructure with a number of programming languages instead of the HCL.

In this post, I will show you how to setup CDKTF for use with the Typescript programming language to deploy Azure resources.

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

Pre-Flight Check

First up, you will need to get a few things installed before you can enjoy the power of CDKTF.

FNM

FNM is a node version manager written in Rust. Use this to install and manage different Node versions. Check out the docs for installation instructions.

Node and NPM

We are using Typescript to define our infrastructure, so we need to install Node. Additionally, CDKTF is installed via NPM so we need that too. Follow these instructions to install Node and NPM with FNM

AzureCLI

Terraform CLI for Azure uses the Azure CLI under the covers, so install that too. The install docs can be found here

Terraform CLI

Terraform CLI does all the of the grunt work to manage the infrastructure. Follow the official docs to get that bad girl/boy installed.

CDK for Terraform

Finally, CDKTF will generate JSON Terraform config from our Typescript files. Install CDKTF via NPM, by follow the docs here.

Azure CLI Login

Login to Azure via the CLI. There are multiple methods to authenicate, use the one suitable for your situation.

Follow the docs for instructions to setup your account and then login with az login command.

Setup

Let's create a project directory and set the Node version.

cmd
mkdir stuff-and-things && cd stuff-and-things
node --version > .node-version

Install the Azure Provider for CDKTF.

cmd
npm install @cdktf/provider-azurerm

Initialize a typescript based project using a local state file.

cmd
cdktf init --template=typescript --local

Define Config

Create a main.ts file with the following contents that will create a resource group and virtual network.

main.ts
import { Construct } from "constructs";
import { App, TerraformStack, TerraformVariable } from "cdktf";
import { AzurermProvider } from "@cdktf/provider-azurerm/lib/provider";
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 AzurermProvider(this, "AzureRm", {
      features: [{}],
      subscriptionId: armSubscriptionId.value,
    });

    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();
Note
This config uses the TF_VAR_ARM_SUBSCRIPTION_ID environement variable. Be sure that it is set in your environment.

The great thing about using a fully fledged programming language is you can use the language features. A simple example in the above code snippet is using variables for the resource_group and location parameters.

Plan/Apply/Destroy

Now that the config is defined you can use a familiar command structure to manage your environment

  • cdktf plan - Show planned infrastructure changes.
  • cdktf apply - Provision infrastructure.
  • cdktf destroy - Delete infrastructure.

Outro

In this post, I showed you how to get your environment setup to deploy Azure infrastructure using CDK for Terraform. I really like this workflow and will do some more experimentation in the near future.

Peace out nerds. Stay weird ✌️