---
title: "How to Build Your First Pulumi Infrastructure as Code Project in Azure"
description: "Learn how to get started with Pulumi and how to build your first project with this great infrastructure as code product."
canonical: "https://adamtheautomator.com/pulumi/"
---

# How to Build Your First Pulumi Infrastructure as Code Project in Azure

> Learn how to get started with Pulumi and how to build your first project with this great infrastructure as code product.

Source: https://adamtheautomator.com/pulumi/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![How to Build Your First Pulumi Infrastructure in Azure](https://adamtheautomator.com/wp-content/uploads/2021/09/How-to-Build-Your-First-Pulumi-Infrastructure-as-Code-Project-in-Azure.jpg)

# How to Build Your First Pulumi Infrastructure in Azure

[![](https://secure.gravatar.com/avatar/bbb3aa33d8c35820d2892462d21634beb25120c1b1e62e96974f69814715f6bd?s=192&d=mm&r=g)Victor Silva](https://adamtheautomator.com/author/victorsilva/)10 September 20216 min. read

Categories: [DevOps](/category/devops/)

Tags:[Pulumi](/tag/pulumi/)

Table of Contents

*   [What is Pulumi?](#what-is-pulumi)
*   [Building a Pulumi Project from Scratch](#building-a-pulumi-project-from-scratch)
*   [Prerequisites](#prerequisites)
*   [Installing Pulumi](#installing-pulumi)
*   [Setting up Pulumi Access to Azure](#setting-up-pulumi-access-to-azure)
*   [Creating a Pulumi Project](#creating-a-pulumi-project)
*   [Deploying Azure Resources with Pulumi](#deploying-azure-resources-with-pulumi)
*   [Cleaning Up](#cleaning-up)
*   [Conclusion](#conclusion)

If you’ve heard about Pulumi and the whole Infrastructure as Code (IaC) way of provisioning resources but aren’t necessarily sure where to start, this tutorial is for you.

This tutorial will introduce you to Pulumi and how it can help provision infrastructure quickly. The tutorial will also build an actual project in Azure to help you see just how much time you can save than building resources by hand.

Let’s get it on!

## What is Pulumi?

In the DevOps world, engineers need to automate as many tasks as possible to build efficient pipelines. Engineers must standardize and codify as many tasks as possible. One of those tasks is provisioning the infrastructure to support software.

Pulumi is a development platform that allows users to craft [IaC](https://adamtheautomator.com/infrastructure-as-code-iac/) solutions with code to then call upon to deploy resources across on-prem and in nearly every cloud environment.

Related:[Infrastructure as Code: Where Continuous Delivery All Begins](https://adamtheautomator.com/infrastructure-as-code-iac/)

Pulumi allows developers to write instructions for provisioning resources in multiple languages, define the state of your infrastructure, and Pulumi figures out how to make it happen.

## Building a Pulumi Project from Scratch

To understand the power of Pulumi, let’s build an actual project. This project will build a few different resources in Azure written in Python but you can build just about any resources in another language with Pulumi. The project will:

1.  Create an Azure resource group.
2.  Create an Azure storage account.
3.  Create an Azure key vault.
4.  Clean up all resources created.

By the time you’re done with this project, you should have a good introductory understanding of what Pulumi can do and how to build a project with it.

## Prerequisites

To ensure you can follow along with the tutorial, be sure you have the following:

*   A Windows 10 or later PC – Pulumi will work with other operating systems, but some tutorial parts will depend on Windows.
    
*   A [Pulumi account](https://app.pulumi.com/signup)
    
*   An Azure account to creates the resources.
    
*   The Chocolatey package manager installed locally.
    

Related:[How to Install Chocolatey and Get Started in No Time](https://adamtheautomator.com/install-chocolatey/)

*   Python v3.6+ – This tutorial will use Python v3.8.2.
    
*   Azure CLI
    

Related:[How to install the Azure CLI](https://adamtheautomator.com/install-azure-cli/)

Open your terminal of choice (PowerShell in this case), and let’s get started!

## Installing Pulumi

To get started, you’ll first need to install Pulumi. One of the quickest ways to install Pulumi is to use the Chocolatey package manager. Once you have Chocolatey installed, run the following command to install the Chocolatey Pulumi package.

```python
choco install pulumi -y
```

![Installing Pulumi with Chocolatey](https://adamtheautomator.com/wp-content/uploads/2021/09/image-38.png)

Installing Pulumi with Chocolatey

## Setting up Pulumi Access to Azure

Once you’ve installed Pulumi, it’s time to set up access to Pulumi itself and give Pulumi access to Azure to create the resources.

To access Azure on the command-line, Pulumi uses credentials stored via the Azure CLI. Pulumi can use an Azure user account or service principal to authenticate to Azure, but this tutorial will use a user account.

Related:[How to create an Azure Service Principal](https://adamtheautomator.com/azure-service-principal/)

To provide credentials to Pulumi, you must first provide credentials to the Azure CLI.

1\. Run the below command, and the Azure CLI will provide you with a URL to visit, where you will provide your username and password.

```python
az login
```

Once complete, Pulumi will know where to find your Azure credentials and will use that to authenticate to Azure.

2\. Now, open your browser, navigate to the [app](https://app.pulumi.com/) and log in with your Pulumi account.

3\. Click on the **Settings** tab and then on **Access Tokens**. In the **Access Tokens** tab, you’ll see all of the tokens you’ve previously created to authenticate with the Pulumi command-line client.

![Navigating to the Pulumi access tokens](https://adamtheautomator.com/wp-content/uploads/2021/09/image-39.png)

Navigating to the Pulumi access tokens

4\. Click on **Create token** and provide a friendly name. This tutorial is calling the token **_demo_**. Once created, click on the paper icon to the right of the token to copy it to your clipboard.

![Creating a Pulumi access token](https://adamtheautomator.com/wp-content/uploads/2021/09/image-40.png)

Creating a Pulumi access token

## Creating a Pulumi Project

Now that you’re all set up and ready to go, let’s create a Pulumi stack and project! Pulumi refers to a project as a folder containing all the files and data it needs to function properly. A stack is an isolated and independently configurable instance of a Pulumi program.

1\. To keep this tutorial’s files straight, create a new folder to store all of the project’s files and change to the directory.

```powershell
mkdir ~/demo
cd ~/demo
```

2\. Next, invoke the Pulumi command-line client to create a new project with the `azure-python` template (based on the cloud and language specified).

```python
pulumi new azure-python
```

> _Whenever you create a new Pulumi project for Azure, Pulumi creates an Azure resource group, storage account. exports the storage account’s primary key._

Since this is the first time you’re invoking the command-line client, Pulumi will prompt you for the access token from the previous section. Paste that access token into the terminal.

![Providing a Pulumi access token to the command line client](https://adamtheautomator.com/wp-content/uploads/2021/09/image-41.png)

Providing a Pulumi access token to the command line client

3\. Now, provide answers to each prompt Pulumi gives you. This tutorial will be using all defaults.

*   Project name
*   Project description
*   Stack name
*   Azure Location – You’ll learn how to change this attribute in the next section.

![Creating a Pulumi project ](https://adamtheautomator.com/wp-content/uploads/2021/09/image-42.png)

Creating a Pulumi project

> _Don’t worry if you receive an error message about the failed action to run the wheel-building process. Pulumi should still finish the project build. The error is mentioned on the GitHub page [here](https://github.com/pypa/pip/issues/8368) and is still open._

When the process finishes, you will see a like below.

![Successful Pulumi project creation](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/a0672756-c511-4893-8179-798befdabea0/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210910%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210910T063310Z&X-Amz-Expires=86400&X-Amz-Signature=b36e5eae222b736f1af78bf889262b6d1a684ff67a3a386862d45706730ff994&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22)

Successful Pulumi project creation

4\. Next, set the Azure region you’d like to create all future resources with the `pulumi config set` command. `pulumi config set azure-native:location eastus`

```powershell
pulumi config set azure-native:location eastus
```

> _Once you’ve created the project and need to change anything about it, you can use the [`pulumi config set` command](https://www.pulumi.com/docs/reference/cli/pulumi_config_set/) to change any necessary attributes._

5\. Now, review the project by listing all of the files in the current directory with `ls`. You should see three different files in this project directory.

*   _Pulumi.yaml_ – A YAML file that defines the Pulumi project such as the name, description, and runtime like `nodejs`, `python`, `dotnet`, or `go`.
*   _Pulumi.dev.yaml_ – A YAML file specific to the environment you’re deploying resources to; in this case, the _dev_ environment. This file contains various configuration values, such as a different number of servers for a specific role, specific sizes for VMs, etc., for the initialized stack. At this time, _Pulumi.dev.yaml_ should only have the Azure location defined with the last command executed.

![Pulumi.dev.yaml configuration](https://adamtheautomator.com/wp-content/uploads/2021/09/image-43.png)

Pulumi.dev.yaml configuration

*   _**main**.py_ – The Python script that will define all of the Azure resources Pulumi will build.

![Pulumi main.py Azure resource script](https://adamtheautomator.com/wp-content/uploads/2021/09/image-44.png)

Pulumi main.py Azure resource script

6\. Next, find your Azure AD tenant ID and user object ID for the user account you provided earlier. You’ll need these values to add to the Python script, defining where to query and create resources. To do that, run the following commands.

```python
## Find the Azure tenant ID
az account list --query "[?isDefault]" | findstr "tenantId"
## Find the Azure user ID
az ad signed-in-user show --query "[objectId]"
```

7\. Open a code editor and edit the _**main**.py_ script to add the `tenantId` and `objectId` variables, replacing the `0`s with your specific IDs found in step six.

Also, add the Azure `keyvault` resource. The tutorial is creating this resource as an example. You’re free to create any kind of Azure resource you’d like. You’ll see the key vault uses an access policy assigned to the logged user (`object_id=objectId`).

```python
import pulumi
from pulumi_azure_native import storage
from pulumi_azure_native import resources
from pulumi_azure_native import keyvault

# Define two variables needed to run this program (get the info from Azure)
tenantId = "00000000-0000-0000-0000-000000000000"
objectId = "00000000-0000-0000-0000-000000000000"

# Create an Azure Resource Group
resource_group = resources.ResourceGroup('resource_group')

# Create an Azure resource (Storage Account)
account = storage.StorageAccount('sa',
    resource_group_name=resource_group.name,
    sku=storage.SkuArgs(
        name=storage.SkuName.STANDARD_LRS,
    ),
    kind=storage.Kind.STORAGE_V2)

# Create a second Azure resource (Key Vault)
vault = keyvault.Vault("vault",
    properties=keyvault.VaultPropertiesArgs(
        access_policies=[keyvault.AccessPolicyEntryArgs(
            object_id=objectId,
            permissions=keyvault.PermissionsArgs(
                certificates=[
                    "get",
                    "list",
                    "delete",
                    "create",
                    "import",
                    "update",
                    "managecontacts",
                    "getissuers",
                    "listissuers",
                    "setissuers",
                    "deleteissuers",
                    "manageissuers",
                    "recover",
                    "purge",
                ],
                keys=[
                    "encrypt",
                    "decrypt",
                    "wrapKey",
                    "unwrapKey",
                    "sign",
                    "verify",
                    "get",
                    "list",
                    "create",
                    "update",
                    "import",
                    "delete",
                    "backup",
                    "restore",
                    "recover",
                    "purge",
                ],
                secrets=[
                    "get",
                    "list",
                    "set",
                    "delete",
                    "backup",
                    "restore",
                    "recover",
                    "purge",
                ],
            ),
            tenant_id=tenantId,
        )],
        enabled_for_deployment=True,
        enabled_for_disk_encryption=True,
        enabled_for_template_deployment=True,
        sku=keyvault.SkuArgs(
            family="A",
            name="standard",
        ),
    tenant_id=tenantId,
    ),
    resource_group_name=resource_group.name,
    vault_name="demopulumikeyvault")

# Export (print in the output) the primary key of the Storage Account
primary_key = pulumi.Output.all(resource_group.name, account.name) \
    .apply(lambda args: storage.list_storage_account_keys(
        resource_group_name=args[0],
        account_name=args[1]
    )).apply(lambda accountKeys: accountKeys.keys[0].value)

pulumi.export("primary_storage_key", primary_key)
```

## Deploying Azure Resources with Pulumi

Now that you’ve created the project, you should be ready to deploy it! To do so, run `pulumi up` to start the deployment to Azure and select **Yes** to continue deployment, as shown below.

![Invoking a Pulumi project](https://adamtheautomator.com/wp-content/uploads/2021/09/image-45.png)

Invoking a Pulumi project

If all goes well, you should see a great status under the **Outputs** section and the number of **Resources** created in green.

![Successful Pulumi project deployment](https://adamtheautomator.com/wp-content/uploads/2021/09/image-46.png)

Successful Pulumi project deployment

## Cleaning Up

Once you’re done learning with the resources you just provisioned with Pulumi, go ahead and clean things up with `pulumi destroy`, providing the stack directory that contains the Pulumi project.

```python
pulumi destroy -s ~/demo/dev
```

## Conclusion

Pulumi is an excellent tool to manage cloud resources and start to work in a modern cloud engineering way taking advantage of development skills. This tutorial only covered creating Azure resources with Python but you can build many different resources in different clouds, even with different languages with Pulumi.

What do you plan to create with Pulumi?

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fpulumi%2F&text=How%20to%20Build%20Your%20First%20Pulumi%20Infrastructure%20in%20Azure)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fpulumi%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fpulumi%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/08/featured_image-6.webp)

### [Automate Terraform with Azure DevOps](/automate-terraform-azure-devops/)

Automate Terraform with Azure DevOps Pipelines: structure a multi-environment repo, store remote state in Azure Storage with locking, and deploy through

![](https://adamtheautomator.com/wp-content/uploads/2026/08/featured_image-5.webp)

### [Azure DevOps Boards: Trace Every Commit to Deployment](/azure-devops-boards-traceability/)

Configure Azure DevOps Boards process templates, backlogs, and Kanban WIP limits, then trace every work item from commit to deployment.

![](https://adamtheautomator.com/wp-content/uploads/2026/07/featured_image-3.png)

### [Build Your First Internal Developer Platform](/build-first-internal-developer-platform/)

Build your first Internal Developer Platform with Backstage, a software catalog, software templates, CI/CD handoffs, and Kubernetes deployment manifests.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
