---
title: "Creating Resources on Azure"
description: "In Pulumi, resources represent the fundamental units that make up your infrastructure, such as virtual machines, networks, storage, and databases. A resource is used to define and manage an infrastructure object in your Pulumi configuration.

In this tutorial, you will create a simple static website hosted on an Azure Blob Storage account. You will then refer to documentation in the Pulumi Registry to configure the storage account as a website."
url: "https://www.pulumi.com/dev/tutorials/creating-resources-azure/"
image: "https://www.pulumi.com/assets/og/dev/tutorials/creating-resources-azure.png"
---

# Creating Resources on Azure

In Pulumi, resources represent the fundamental units that make up your infrastructure, such as virtual machines, networks, storage, and databases. A resource is used to define and manage an infrastructure object in your Pulumi configuration.

In this tutorial, you will create a simple static website hosted on an Azure Blob Storage account. You will then refer to documentation in the Pulumi Registry to configure the storage account as a website.

## What you'll learn

- How to create a new resource
- How to reference resource definitions in the Pulumi documentation

## Prerequisites

- The [Pulumi CLI](https://www.pulumi.com/docs/install/)
- A [Pulumi Cloud account](https://app.pulumi.com/signup) and an [access token](https://www.pulumi.com/docs/administration/access-identity/access-tokens/)
- An [Azure account](https://azure.microsoft.com/en-us/pricing/purchase-options/azure-account)
- The [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli)
- Familiarity with one of [Pulumi's supported languages](https://www.pulumi.com/docs/iac/languages-sdks/)

## Create a new project

To start, [login to the Pulumi CLI](https://www.pulumi.com/dev/tutorials/cli-authentication/) and [ensure it is configured to use your Azure account](https://www.pulumi.com/docs/iac/get-started/azure/begin/#configure-pulumi-to-access-your-microsoft-azure-account). Next, [create a new project and stack](https://www.pulumi.com/docs/iac/get-started/azure/create-project/).

```bash
# Example using Python
$ mkdir pulumi-tutorial-azure
$ cd pulumi-tutorial-azure
$ pulumi new azure-python
```

Then use the following code snippet to scaffold your project with the required imports and overall program structure that you will fill in as you go along:

```javascript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

// Steps:
// [1] Create a resource group.
// [2] Create a blob storage account.
// [3] Configure the storage account as a website.
```

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

// Steps:
// [1] Create a resource group.
// [2] Create a blob storage account.
// [3] Configure the storage account as a website.
```

```python
import pulumi
import pulumi_azure_native as azure_native
import pulumi_synced_folder as synced_folder

path = "./wwwroot"
index_document = "index.html"
error_document = "error.html"

#### Steps:
# [1] Create a resource group.
# [2] Create a blob storage account.
# [3] Configure the storage account as a website.
```

```go
package main

import (
	"github.com/pulumi/pulumi-azure-native-sdk/resources/v2"
	"github.com/pulumi/pulumi-azure-native-sdk/storage/v2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		path := "./wwwroot";
		indexDocument := "index.html";
		errorDocument := "error.html";
	
		// Steps:
		// [1] Create a resource group.
		// [2] Create a blob storage account.
		// [3] Configure the storage account as a website.
	})
}
```

```csharp
﻿using Pulumi;
using Resources = Pulumi.AzureNative.Resources;
using Storage = Pulumi.AzureNative.Storage;
using System.Collections.Generic;

return await Pulumi.Deployment.RunAsync(() =>
{
    var path = "./wwwroot";
    var indexDocument = "index.html";
    var errorDocument = "error.html";

    // Steps:
    // [1] Create a resource group.
    // [2] Create a blob storage account.
    // [3] Configure the storage account as a website.
});
```

```yaml
name: azure-native-static-website-yaml
runtime: yaml
description: An example that deploys all of the resources for a static website on Azure.

#### Steps:
# [1] Create a resource group.
# [2] Create a blob storage account.
# [3] Configure the storage account as a website.
```

> **Note**
>
> If you are deploying your resources using Pulumi Python, this tutorial will make use of the [Pulumi Synced Folder](https://www.pulumi.com/registry/packages/synced-folder/) package, so you will also need to make sure to [install this dependency into your project](https://github.com/pulumi/pulumi-synced-folder?tab=readme-ov-file#installing).

## Create a resource group

The first resource you will create will be an [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal). Azure Resource Groups provide a logical container to organize and manage resources in your Azure account. In Azure, resources like virtual machines, storage accounts, and databases are grouped together within a resource group.

The [Pulumi Registry](https://www.pulumi.com/registry/) provides the documentation for all of the Pulumi providers and their associated resources. Open the [azure-native.resources.ResourceGroup documentation page](https://www.pulumi.com/registry/packages/azure-native/api-docs/resources/resourcegroup/) to view a description of this resource, example usage, the resource definition, and supported properties. You will now define your resource group resource as shown below:

```javascript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});
```

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

// [1] Create a resource group.
const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});
```

```python
import pulumi
import pulumi_azure_native as azure_native
import pulumi_synced_folder as synced_folder

path = "./wwwroot"
index_document = "index.html"
error_document = "error.html"

# [1] Create a resource group.
resource_group = azure_native.resources.ResourceGroup( "website-resource-group",
    location="eastus"
)
```

```go
package main

import (
	"github.com/pulumi/pulumi-azure-native-sdk/resources/v2"
	"github.com/pulumi/pulumi-azure-native-sdk/storage/v2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		path := "./wwwroot";
		indexDocument := "index.html";
		errorDocument := "error.html";

		// [1] Create a resource group.
		resourceGroup, err := resources.NewResourceGroup(ctx, "website-resource-group", &resources.ResourceGroupArgs{
			Location:          pulumi.String("eastus"),
		})
		if err != nil {
			return err
		}

	})
}
```

```csharp
﻿using Pulumi;
using Resources = Pulumi.AzureNative.Resources;
using Storage = Pulumi.AzureNative.Storage;
using System.Collections.Generic;

return await Pulumi.Deployment.RunAsync(() =>
{
    var path = "./wwwroot";
    var indexDocument = "index.html";
    var errorDocument = "error.html";

    // [1] Create a resource group.
    var resourceGroup = new Resources.ResourceGroup("website-resource-group", new()
    {
        Location = "eastus",
    });

});
```

```yaml
name: azure-native-static-website-yaml
runtime: yaml
description: An example that deploys all of the resources for a static website on Azure.

resources:
  # [1] Create a resource group.
  resourceGroup:
    type: azure-native:resources:ResourceGroup
    properties:
      location: eastus
```

All resources have a required [`name`](https://www.pulumi.com/docs/concepts/resources/names/) argument. Each resource has both a [logical name](https://www.pulumi.com/docs/concepts/resources/names/#logicalname) and a [physical name](https://www.pulumi.com/docs/concepts/resources/names/#autonaming). The **logical name** is how the resource is known inside Pulumi. This is the value provided to the required `name` argument. The **physical name** is the name used for the resource in the cloud provider that a Pulumi program is deploying to. It is a combination of the logical name plus a random suffix which helps to prevent resource naming collisions.

In the above example, the logical name for our `ResourceGroup` resource is **"website-resource-group"**, and the physical name might typically look something like **"website-resource-group-d7c2fa0"**.

## Create a storage account

The next step will be to create an [Azure Blob Storage account](https://azure.microsoft.com/en-us/products/storage/blobs) that will be used to host the website. Once again, you can refer to the Pulumi registry, specifically the [`azure-native.storage.StorageAccount` resource page](https://www.pulumi.com/registry/packages/azure-native/api-docs/storage/storageaccount/), to define your storage account as shown below:

```javascript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});

// [2] Create a blob storage account.
const storageAccount = new storage.StorageAccount("websiteblob", {
    resourceGroupName: resourceGroup.name,
    kind: "StorageV2",
    sku: {
        name: "Standard_LRS",
    },
});
```

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

// [1] Create a resource group.
const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});

// [2] Create a blob storage account.
const storageAccount = new storage.StorageAccount("websiteblob", {
    resourceGroupName: resourceGroup.name,
    kind: "StorageV2",
    sku: {
        name: "Standard_LRS",
    },
});
```

```python
import pulumi
import pulumi_azure_native as azure_native
import pulumi_synced_folder as synced_folder

path = "./wwwroot"
index_document = "index.html"
error_document = "error.html"

# [1] Create a resource group.
resource_group = azure_native.resources.ResourceGroup( "website-resource-group",
    location="eastus"
)

# [2] Create a blob storage account.
storage_account = azure_native.storage.StorageAccount(
    "websiteblob",
    resource_group_name=resource_group.name,
    kind="StorageV2",
    sku={
        "name": "Standard_LRS",
    }
)
```

```go
package main

import (
	"github.com/pulumi/pulumi-azure-native-sdk/resources/v2"
	"github.com/pulumi/pulumi-azure-native-sdk/storage/v2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		path := "./wwwroot";
		indexDocument := "index.html";
		errorDocument := "error.html";

		// [1] Create a resource group.
		resourceGroup, err := resources.NewResourceGroup(ctx, "website-resource-group", &resources.ResourceGroupArgs{
			Location:          pulumi.String("eastus"),
		})
		if err != nil {
			return err
		}

		// [2] Create a blob storage account.
		storageAccount, err := storage.NewStorageAccount(ctx, "websiteblob", &storage.StorageAccountArgs{
			ResourceGroupName: resourceGroup.Name,
			Sku: &storage.SkuArgs{
				Name: pulumi.String("Standard_LRS"),
			},
			Kind: pulumi.String("StorageV2"),
		})
		if err != nil {
			return err
		}

	})
}
```

```csharp
﻿using Pulumi;
using Resources = Pulumi.AzureNative.Resources;
using Storage = Pulumi.AzureNative.Storage;
using System.Collections.Generic;

return await Pulumi.Deployment.RunAsync(() =>
{
    var path = "./wwwroot";
    var indexDocument = "index.html";
    var errorDocument = "error.html";

    // [1] Create a resource group.
    var resourceGroup = new Resources.ResourceGroup("website-resource-group", new()
    {
        Location = "eastus",
    });

    // [2] Create a blob storage account.
    var storageAccount = new Storage.StorageAccount("websiteblob", new()
    {
        ResourceGroupName = resourceGroup.Name,
        Sku = new Storage.Inputs.SkuArgs
        {
            Name = Storage.SkuName.Standard_LRS
        },
        Kind = Storage.Kind.StorageV2
    });

});
```

```yaml
name: azure-native-static-website-yaml
runtime: yaml
description: An example that deploys all of the resources for a static website on Azure.

resources:
  # [1] Create a resource group.
  resourceGroup:
    type: azure-native:resources:ResourceGroup
    properties:
      location: eastus

  # [2] Create a blob storage account.
  storageAccount:
    type: azure-native:storage:StorageAccount
    properties:
      accountName: websiteblob
      resourceGroupName: ${resourceGroup.name}
      kind: "StorageV2"
```

In addition to names, resources have properties and options. **Properties** are used to specify what type of resource to create. Properties are often resource-specific, and they can be required or optional depending on the specifications of the provider.

The properties inside your `StorageAccount` resource are:

| Property | Description |
| --- | --- |
| **resource group name** | tells the Azure Native what resource group to associate this resource with |
| **kind** | tells the provider the type of storage account to create, e.g. `StorageV2` |
| **sku** | tells the provider the SKU to use when creating the resource, e.g. `Standard_LRS` |

**Options** let you control certain aspects of a resource (such as showing explicit dependencies or importing existing infrastructure). We do not have any options defined for this resource, but you can learn more about options in the [Pulumi documentation](https://www.pulumi.com/docs/concepts/options).

## Deploy your storage account

Now run the `pulumi up` command to preview and deploy the resources you've just defined in your project.

```bash
$ pulumi up -y
Previewing update (static-website)

     Type                                     Name                    Plan
 +   pulumi:pulumi:Stack                      azure-static-website    create
 +   ├─ azure-native:resources:ResourceGroup  website-resource-group  create
 +   └─ azure-native:storage:StorageAccount   websiteblob             create

Resources:
    + 3 to create

Updating (static-website)

     Type                                     Name                    Status
 +   pulumi:pulumi:Stack                      azure-static-website    created (39s)
 +   ├─ azure-native:resources:ResourceGroup  website-resource-group  created (4s)
 +   └─ azure-native:storage:StorageAccount   websiteblob             created (30s)

Resources:
    + 3 created

Duration: 41s
```

## Configure the static website

In this section, you will use the Pulumi documentation to configure the storage account as a static website on your own. To prepare for the configuration of the storage account, you will need to create a folder labeled `www` in your project. Inside this project, you will need to create an `index.html` file and an `error.html` file with the content as shown below.

Contents of the `index.html` file:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Hello, world!</title>
</head>
<body>
    <h1>Hello, world! 👋</h1>
    <p>Deployed with 💜 by <a href="https://pulumi.com/">Pulumi</a>.</p>
</body>
</html>
```

Content of the `error.html` file:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Page not found</title>
</head>
<body>
    Oops! That page wasn't found. Try our <a href="/">home page</a> instead.
</body>
</html>
```

An updated version of the project code has been provided below as a starting point:

```javascript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});

// [2] Create a blob storage account.
const storageAccount = new storage.StorageAccount("websiteblob", {
    resourceGroupName: resourceGroup.name,
    kind: "StorageV2",
    sku: {
        name: "Standard_LRS",
    },
});

// [3] Configure the storage account as a website.
const website = new storage.StorageAccountStaticWebsite("website", {
// TO-DO

[indexDocument, errorDocument].map(
    name =>
        new storage.Blob(name, {
            resourceGroupName: resourceGroup.name,
            accountName: storageAccount.name,
            containerName: website.containerName,
            source: new pulumi.asset.FileAsset(`./${path}/${name}`),
            contentType: "text/html",
        }),
);

// Export the URL of the website.
export const staticEndpoint = storageAccount.primaryEndpoints.web;
```

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

// [1] Create a resource group.
const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});

// [2] Create a blob storage account.
const storageAccount = new storage.StorageAccount("websiteblob", {
    resourceGroupName: resourceGroup.name,
    kind: "StorageV2",
    sku: {
        name: "Standard_LRS",
    },
});

// [3] Configure the storage account as a website.
// TO-DO

// Upload the website files
[indexDocument, errorDocument].map(
    name =>
        new storage.Blob(name, {
            resourceGroupName: resourceGroup.name,
            accountName: storageAccount.name,
            containerName: website.containerName,
            source: new pulumi.asset.FileAsset(`./${path}/${name}`),
            contentType: "text/html",
        }),
);

// Export the URL of the website.
export const staticEndpoint = storageAccount.primaryEndpoints.web;
```

```python
import pulumi
import pulumi_azure_native as azure_native
import pulumi_synced_folder as synced_folder

path = "./wwwroot"
index_document = "index.html"
error_document = "error.html"

# [1] Create a resource group.
resource_group = azure_native.resources.ResourceGroup( "website-resource-group",
    location="eastus"
)

# [2] Create a blob storage account.
storage_account = azure_native.storage.StorageAccount(
    "websiteblob",
    resource_group_name=resource_group.name,
    kind="StorageV2",
    sku={
        "name": "Standard_LRS",
    }
)

# [3] Configure the storage account as a website.
# TO-DO

# Upload the website files.
synced_folder = synced_folder.AzureBlobFolder(
    "synced-folder",
    path=path,
    resource_group_name=resource_group.name,
    storage_account_name=storage_account.name,
    container_name=website.container_name,
)

# Export the URL of the website.
pulumi.export("staticEndpoint", storage_account.primary_endpoints.web)
```

```go
package main

import (
	"github.com/pulumi/pulumi-azure-native-sdk/resources/v2"
	"github.com/pulumi/pulumi-azure-native-sdk/storage/v2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		path := "./wwwroot";
		indexDocument := "index.html";
		errorDocument := "error.html";

		// [1] Create a resource group.
		resourceGroup, err := resources.NewResourceGroup(ctx, "website-resource-group", &resources.ResourceGroupArgs{
			Location:          pulumi.String("eastus"),
		})
		if err != nil {
			return err
		}

		// [2] Create a blob storage account.
		storageAccount, err := storage.NewStorageAccount(ctx, "websiteblob", &storage.StorageAccountArgs{
			ResourceGroupName: resourceGroup.Name,
			Sku: &storage.SkuArgs{
				Name: pulumi.String("Standard_LRS"),
			},
			Kind: pulumi.String("StorageV2"),
		})
		if err != nil {
			return err
		}

		//[3] Configure the storage account as a website.
        // TO-DO

		_, err = storage.NewBlob(ctx, "index.html", &storage.BlobArgs{
			ResourceGroupName: resourceGroup.Name,
			AccountName:       storageAccount.Name,
			ContainerName:     website.ContainerName,
			Source:            pulumi.NewFileAsset("./" + path + "/" + indexDocument),
			ContentType:       pulumi.String("text/html"),
		})
		if err != nil {
			return err
		}
		_, err = storage.NewBlob(ctx, "404.html", &storage.BlobArgs{
			ResourceGroupName: resourceGroup.Name,
			AccountName:       storageAccount.Name,
			ContainerName:     website.ContainerName,
			Source:            pulumi.NewFileAsset("./" + path + "/" + errorDocument),
			ContentType:       pulumi.String("text/html"),
		})
		if err != nil {
			return err
		}

		// Export the URL of the website.
		ctx.Export("staticEndpoint", storageAccount.PrimaryEndpoints.Web())
		return nil
	})
}
```

```csharp
﻿using Pulumi;
using Resources = Pulumi.AzureNative.Resources;
using Storage = Pulumi.AzureNative.Storage;
using System.Collections.Generic;

return await Pulumi.Deployment.RunAsync(() =>
{
    var path = "./wwwroot";
    var indexDocument = "index.html";
    var errorDocument = "error.html";

    // [1] Create a resource group.
    var resourceGroup = new Resources.ResourceGroup("website-resource-group", new()
    {
        Location = "eastus",
    });

    // [2] Create a blob storage account.
    var storageAccount = new Storage.StorageAccount("websiteblob", new()
    {
        ResourceGroupName = resourceGroup.Name,
        Sku = new Storage.Inputs.SkuArgs
        {
            Name = Storage.SkuName.Standard_LRS
        },
        Kind = Storage.Kind.StorageV2
    });

    // [3] Configure the storage account as a website.
    // TO-DO

    // Upload the website files
    var index_html = new Storage.Blob("index.html", new Storage.BlobArgs
    {
        ResourceGroupName = resourceGroup.Name,
        AccountName = storageAccount.Name,
        ContainerName = website.ContainerName,
        Source = new FileAsset($"./{path}/{indexDocument}"),
        ContentType = "text/html",
    });

    var notfound_html = new Storage.Blob("404.html", new Storage.BlobArgs
    {
        ResourceGroupName = resourceGroup.Name,
        AccountName = storageAccount.Name,
        ContainerName = website.ContainerName,
        Source = new FileAsset($"./{path}/{errorDocument}"),
        ContentType = "text/html",
    });

    var staticEndpoint = storageAccount.PrimaryEndpoints.Apply(primaryEndpoints => primaryEndpoints.Web);

    // Export the URL of the website.
    return new Dictionary<string, object?>
    {
        ["staticEndpoint"] = staticEndpoint
    };
});
```

```yaml
name: azure-native-static-website-yaml
runtime: yaml
description: An example that deploys all of the resources for a static website on Azure.

resources:
  # [1] Create a resource group.
  resourceGroup:
    type: azure-native:resources:ResourceGroup
    properties:
      location: eastus

  # [2] Create a blob storage account.
  storageAccount:
    type: azure-native:storage:StorageAccount
    properties:
      accountName: websiteblob
      resourceGroupName: ${resourceGroup.name}
      kind: "StorageV2"
      sku: { name: "Standard_LRS" }

  # TO-DO

  # Upload the website files
  index.html:
    type: azure-native:storage:Blob
    properties:
      resourceGroupName: ${resourceGroup.name}
      accountName: ${storageAccount.name}
      containerName: ${staticWebsite.containerName}
      contentType: text/html
      type: "Block"
      source:
        fn::fileAsset: ./wwwroot/index.html
  error.html:
    type: azure-native:storage:Blob
    properties:
      resourceGroupName: ${resourceGroup.name}
      accountName: ${storageAccount.name}
      containerName: ${staticWebsite.containerName}
      contentType: text/html
      type: "Block"
      source:
        fn::fileAsset: ./wwwroot/error.html

# Export the URL of the website.
outputs:
```

Use the following steps as a guide for adding the storage :

- Navigate to the [Azure Native Registry](https://www.pulumi.com/registry/packages/azure-native/)
- Search for the `StorageAccountStaticWebsite` resource
- Define the `StorageAccountStaticWebsite` resource in your project code
- Preview and deploy your updated project code

The website URL has been provided for you as an output, and you can use this to access your static website once the deployment has completed. You should be greeted with a "Hello, world!" homepage message that indicates your static website has been successfully created.

### View complete solution

You can view the complete project code below:

```javascript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});

// [2] Create a blob storage account.
const storageAccount = new storage.StorageAccount("websiteblob", {
    resourceGroupName: resourceGroup.name,
    kind: "StorageV2",
    sku: {
        name: "Standard_LRS",
    },
});

// [3] Configure the storage account as a website.
const website = new storage.StorageAccountStaticWebsite("website", {
    accountName: storageAccount.name,
    resourceGroupName: resourceGroup.name,
    indexDocument: indexDocument,
    error404Document: errorDocument,
});

// Upload the website files
[indexDocument, errorDocument].map(
    name =>
        new storage.Blob(name, {
            resourceGroupName: resourceGroup.name,
            accountName: storageAccount.name,
            containerName: website.containerName,
            source: new pulumi.asset.FileAsset(`./${path}/${name}`),
            contentType: "text/html",
        }),
);

// Export the URL of the website.
export const staticEndpoint = storageAccount.primaryEndpoints.web;
```

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

const path = "./wwwroot";
const indexDocument = "index.html";
const errorDocument = "error.html";

// [1] Create a resource group.
const resourceGroup = new resources.ResourceGroup("website-resource-group", {
    location: "eastus",
});

// [2] Create a blob storage account.
const storageAccount = new storage.StorageAccount("websiteblob", {
    resourceGroupName: resourceGroup.name,
    kind: "StorageV2",
    sku: {
        name: "Standard_LRS",
    },
});

// [3] Configure the storage account as a website.
const website = new storage.StorageAccountStaticWebsite("website", {
    accountName: storageAccount.name,
    resourceGroupName: resourceGroup.name,
    indexDocument: indexDocument,
    error404Document: errorDocument,
});

// Upload the website files
[indexDocument, errorDocument].map(
    name =>
        new storage.Blob(name, {
            resourceGroupName: resourceGroup.name,
            accountName: storageAccount.name,
            containerName: website.containerName,
            source: new pulumi.asset.FileAsset(`./${path}/${name}`),
            contentType: "text/html",
        }),
);

// Export the URL of the website.
export const staticEndpoint = storageAccount.primaryEndpoints.web;
```

```python
import pulumi
import pulumi_azure_native as azure_native
import pulumi_synced_folder as synced_folder

path = "./wwwroot"
index_document = "index.html"
error_document = "error.html"

# [1] Create a resource group.
resource_group = azure_native.resources.ResourceGroup( "website-resource-group",
    location="eastus"
)

# [2] Create a blob storage account.
storage_account = azure_native.storage.StorageAccount(
    "websiteblob",
    resource_group_name=resource_group.name,
    kind="StorageV2",
    sku={
        "name": "Standard_LRS",
    }
)

# [3] Configure the storage account as a website.
website = azure_native.storage.StorageAccountStaticWebsite(
    "website",
    account_name=storage_account.name,
    resource_group_name=resource_group.name,
    index_document=index_document,
    error404_document=error_document,
)

# Upload the website files.
synced_folder = synced_folder.AzureBlobFolder(
    "synced-folder",
    path=path,
    resource_group_name=resource_group.name,
    storage_account_name=storage_account.name,
    container_name=website.container_name,
)

# Export the URL of the website.
pulumi.export("staticEndpoint", storage_account.primary_endpoints.web)
```

```go
package main

import (
	"github.com/pulumi/pulumi-azure-native-sdk/resources/v2"
	"github.com/pulumi/pulumi-azure-native-sdk/storage/v2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		path := "./wwwroot";
		indexDocument := "index.html";
		errorDocument := "error.html";

		// [1] Create a resource group.
		resourceGroup, err := resources.NewResourceGroup(ctx, "website-resource-group", &resources.ResourceGroupArgs{
			Location:          pulumi.String("eastus"),
		})
		if err != nil {
			return err
		}

		// [2] Create a blob storage account.
		storageAccount, err := storage.NewStorageAccount(ctx, "websiteblob", &storage.StorageAccountArgs{
			ResourceGroupName: resourceGroup.Name,
			Sku: &storage.SkuArgs{
				Name: pulumi.String("Standard_LRS"),
			},
			Kind: pulumi.String("StorageV2"),
		})
		if err != nil {
			return err
		}

		//[3] Configure the storage account as a website.
		website, err := storage.NewStorageAccountStaticWebsite(ctx, "staticWebsite", &storage.StorageAccountStaticWebsiteArgs{
			AccountName:       storageAccount.Name,
			ResourceGroupName: resourceGroup.Name,
			IndexDocument:     pulumi.String("index.html"),
			Error404Document:  pulumi.String("404.html"),
		})
		if err != nil {
			return err
		}

		_, err = storage.NewBlob(ctx, "index.html", &storage.BlobArgs{
			ResourceGroupName: resourceGroup.Name,
			AccountName:       storageAccount.Name,
			ContainerName:     website.ContainerName,
			Source:            pulumi.NewFileAsset("./" + path + "/" + indexDocument),
			ContentType:       pulumi.String("text/html"),
		})
		if err != nil {
			return err
		}
		_, err = storage.NewBlob(ctx, "404.html", &storage.BlobArgs{
			ResourceGroupName: resourceGroup.Name,
			AccountName:       storageAccount.Name,
			ContainerName:     website.ContainerName,
			Source:            pulumi.NewFileAsset("./" + path + "/" + errorDocument),
			ContentType:       pulumi.String("text/html"),
		})
		if err != nil {
			return err
		}

		// Export the URL of the website.
		ctx.Export("staticEndpoint", storageAccount.PrimaryEndpoints.Web())
		return nil
	})
}
```

```csharp
﻿using Pulumi;
using Resources = Pulumi.AzureNative.Resources;
using Storage = Pulumi.AzureNative.Storage;
using System.Collections.Generic;

return await Pulumi.Deployment.RunAsync(() =>
{
    var path = "./wwwroot";
    var indexDocument = "index.html";
    var errorDocument = "error.html";

    // [1] Create a resource group.
    var resourceGroup = new Resources.ResourceGroup("website-resource-group", new()
    {
        Location = "eastus",
    });

    // [2] Create a blob storage account.
    var storageAccount = new Storage.StorageAccount("websiteblob", new()
    {
        ResourceGroupName = resourceGroup.Name,
        Sku = new Storage.Inputs.SkuArgs
        {
            Name = Storage.SkuName.Standard_LRS
        },
        Kind = Storage.Kind.StorageV2
    });

    // [3] Configure the storage account as a website.
    var website = new Storage.StorageAccountStaticWebsite("website", new Storage.StorageAccountStaticWebsiteArgs
    {
        AccountName = storageAccount.Name,
        ResourceGroupName = resourceGroup.Name,
        IndexDocument = indexDocument,
        Error404Document = errorDocument,
    });

    // Upload the website files
    var index_html = new Storage.Blob("index.html", new Storage.BlobArgs
    {
        ResourceGroupName = resourceGroup.Name,
        AccountName = storageAccount.Name,
        ContainerName = website.ContainerName,
        Source = new FileAsset($"./{path}/{indexDocument}"),
        ContentType = "text/html",
    });

    var notfound_html = new Storage.Blob("404.html", new Storage.BlobArgs
    {
        ResourceGroupName = resourceGroup.Name,
        AccountName = storageAccount.Name,
        ContainerName = website.ContainerName,
        Source = new FileAsset($"./{path}/{errorDocument}"),
        ContentType = "text/html",
    });

    var staticEndpoint = storageAccount.PrimaryEndpoints.Apply(primaryEndpoints => primaryEndpoints.Web);

    // Export the URL of the website.
    return new Dictionary<string, object?>
    {
        ["staticEndpoint"] = staticEndpoint
    };
});
```

```yaml
name: azure-native-static-website-yaml
runtime: yaml
description: An example that deploys all of the resources for a static website on Azure.

resources:
  # [1] Create a resource group.
  resourceGroup:
    type: azure-native:resources:ResourceGroup
    properties:
      location: eastus

  # [2] Create a blob storage account.
  storageAccount:
    type: azure-native:storage:StorageAccount
    properties:
      accountName: websiteblob
      resourceGroupName: ${resourceGroup.name}
      kind: "StorageV2"
      sku: { name: "Standard_LRS" }

  # [3] Configure the storage account as a website.
  staticWebsite:
    type: azure-native:storage:StorageAccountStaticWebsite
    properties:
      resourceGroupName: ${resourceGroup.name}
      accountName: ${storageAccount.name}
      indexDocument: index.html
      error404Document: 404.html

  # Upload the website files
  index.html:
    type: azure-native:storage:Blob
    properties:
      resourceGroupName: ${resourceGroup.name}
      accountName: ${storageAccount.name}
      containerName: ${staticWebsite.containerName}
      contentType: text/html
      type: "Block"
      source:
        fn::fileAsset: ./wwwroot/index.html
  error.html:
    type: azure-native:storage:Blob
    properties:
      resourceGroupName: ${resourceGroup.name}
      accountName: ${storageAccount.name}
      containerName: ${staticWebsite.containerName}
      contentType: text/html
      type: "Block"
      source:
        fn::fileAsset: ./wwwroot/error.html

# Export the URL of the website.
outputs:
```

## Clean up

Before moving on, tear down the resources that are part of your stack to avoid incurring any charges.

1. Run `pulumi destroy` to tear down all resources. You'll be prompted to make sure you really want to delete these resources. A destroy operation may take some time, since Pulumi waits for the resources to finish shutting down before it considers the destroy operation to be complete.
2. To delete the stack itself, run `pulumi stack rm`. Note that this command deletes all deployment history from the Pulumi Service.

## Next steps

In this tutorial, you made a resource group and a storage account, and you configured your storage account as a static website by referencing the Pulumi Registry. You also reviewed resource properties and example usage of various resources.

To learn more about creating resources in Pulumi, take a look at the following resources:

- Learn more about stack outputs and references in the [Reference AWS Resources Across Stacks tutorial](https://www.pulumi.com/dev/tutorials/stack-outputs-refs-azure/) tutorial.
- Learn more about inputs and outputs in the [Inputs and Outputs](https://www.pulumi.com/docs/concepts/inputs-outputs/) documentation.
- Learn more about [resource names](https://www.pulumi.com/docs/concepts/resources/names/), [options](https://www.pulumi.com/docs/concepts/options/), and [providers](https://www.pulumi.com/docs/concepts/resources/providers/) in the Pulumi documentation.
