# File Storage

Source: /azure/services/file-storage/

## Introduction

Azure Files offers fully managed file shares in a storage account, accessible over the SMB and NFS protocols and through the Azure Files REST API.
File shares are commonly mounted by containers and Kubernetes pods, used as shared configuration or content stores, and used to lift and shift applications that expect a file system. For more information, see [What is Azure Files?](https://learn.microsoft.com/en-us/azure/storage/files/storage-files-introduction).

LocalStack for Azure provides a local environment for building and testing applications that make use of Azure Files.
You manage file shares through the Azure Resource Manager API, and read and write their files through the Azure Files REST API.
The supported APIs are available on our [API Coverage section](#api-coverage), which provides information on the extent of Azure Files' integration with LocalStack.

## Getting started

This guide is designed for users new to Azure Files and assumes basic knowledge of the Azure CLI and our `lstk az` proxy.

Launch LocalStack using your preferred method. For more information, see [Introduction to LocalStack for Azure](/azure/getting-started/). Once the container is running, enable Azure CLI interception by running:

```bash
lstk az start-interception
```

This command points the `az` CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API.
To revert this configuration, run:

```bash
lstk az stop-interception
```

This reconfigures the `az` CLI to send commands to the official Azure management REST API.

### Create a resource group and a storage account

Create a resource group and a general-purpose v2 storage account:

```bash
az group create \
  --name rg-files-demo \
  --location westeurope

az storage account create \
  --name stfilesdemo \
  --resource-group rg-files-demo \
  --location westeurope \
  --sku Standard_LRS \
  --kind StorageV2
```

### Create a file share

Create a file share with a quota of 10 GiB:

```bash
az storage share-rm create \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --name share-demo \
  --quota 10 \
  --enabled-protocols SMB
```

```bash title="Output"
{
  "enabledProtocols": "SMB",
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-files-demo/providers/Microsoft.Storage/storageAccounts/stfilesdemo/fileServices/default/shares/share-demo",
  "leaseState": "available",
  "leaseStatus": "unlocked",
  "name": "share-demo",
  "resourceGroup": "rg-files-demo",
  "shareQuota": 10,
  "signedIdentifiers": [],
  "type": "Microsoft.Storage/storageAccounts/fileServices/shares",
  ...
}
```

### Update and list file shares

Raise the quota to 20 GiB:

```bash
az storage share-rm update \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --name share-demo \
  --quota 20
```

```bash title="Output"
{
  "accessTier": "TransactionOptimized",
  "enabledProtocols": "SMB",
  "name": "share-demo",
  "shareQuota": 20,
  "type": "Microsoft.Storage/storageAccounts/fileServices/shares",
  ...
}
```

Then list the file shares of the storage account:

```bash
az storage share-rm list \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --output table
```

```bash title="Output"
AccessTier            AccessTierChangeTime         EnabledProtocols    LastModifiedTime             LeaseState    LeaseStatus    Name        ResourceGroup    ShareQuota
--------------------  ---------------------------  ------------------  ---------------------------  ------------  -------------  ----------  ---------------  ------------
TransactionOptimized  2026-10-20T10:32:01.689190Z  SMB                 2026-10-20T10:32:05.182839Z  available     unlocked       share-demo  rg-files-demo    20
```

### Upload and download files

Retrieve the storage account's connection string:

```bash
CONNECTION_STRING=$(az storage account show-connection-string \
  --name stfilesdemo \
  --resource-group rg-files-demo \
  --query connectionString \
  --output tsv)
```

The connection string points the file endpoint at LocalStack, for example `FileEndpoint=https://stfilesdemo.file.core.azure.localhost.localstack.cloud:4566`.

Create a directory in the share, and upload a file to it:

```bash
echo "Hello from LocalStack for Azure Files" > hello.txt

az storage directory create \
  --share-name share-demo \
  --name docs \
  --connection-string "$CONNECTION_STRING"

az storage file upload \
  --share-name share-demo \
  --source hello.txt \
  --path docs/hello.txt \
  --connection-string "$CONNECTION_STRING"
```

List the files in the directory:

```bash
az storage file list \
  --share-name share-demo \
  --path docs \
  --connection-string "$CONNECTION_STRING" \
  --output table
```

```bash title="Output"
Name       Content Length    Type    Last Modified
---------  ----------------  ------  -------------------------
hello.txt  38                file    2026-10-20T10:32:10+00:00
```

Download the file again:

```bash
az storage file download \
  --share-name share-demo \
  --path docs/hello.txt \
  --dest ./hello-copy.txt \
  --connection-string "$CONNECTION_STRING"

cat hello-copy.txt
```

```bash title="Output"
Hello from LocalStack for Azure Files
```

The share's usage reflects the uploaded file:

```bash
az storage share-rm show \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --name share-demo \
  --expand stats \
  --query shareUsageBytes
```

```bash title="Output"
38
```

### Create a share snapshot

Create a read-only snapshot of the share:

```bash
az storage share-rm snapshot \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --name share-demo
```

```bash title="Output"
{
  "name": "share-demo",
  "shareQuota": 20,
  "shareUsageBytes": 38,
  "snapshotTime": "2026-10-20T10:32:14.343070Z",
  "type": "Microsoft.Storage/storageAccounts/fileServices/shares",
  ...
}
```

### Soft delete and restore a share

Enable soft delete for file shares, with a retention period of 7 days:

```bash
az storage account file-service-properties update \
  --account-name stfilesdemo \
  --resource-group rg-files-demo \
  --enable-delete-retention true \
  --delete-retention-days 7
```

```bash title="Output"
{
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-files-demo/providers/Microsoft.Storage/storageAccounts/stfilesdemo/fileServices/default",
  "name": "default",
  "shareDeleteRetentionPolicy": {
    "allowPermanentDelete": null,
    "days": 7,
    "enabled": true
  },
  "type": "Microsoft.Storage/storageAccounts/fileServices",
  ...
}
```

Delete the share together with its snapshots, then list the shares including the deleted ones:

```bash
az storage share-rm delete \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --name share-demo \
  --include snapshots \
  --yes

az storage share-rm list \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --include-deleted \
  --query "[].{name:name,deleted:deleted,version:version,remainingRetentionDays:remainingRetentionDays}"
```

```bash title="Output"
[
  {
    "deleted": true,
    "name": "share-demo",
    "remainingRetentionDays": 7,
    "version": "01DD607E47B092C0"
  }
]
```

Restore the deleted share by its version:

```bash
DELETED_VERSION=$(az storage share-rm list \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --include-deleted \
  --query "[?deleted].version" \
  --output tsv)

az storage share-rm restore \
  --storage-account stfilesdemo \
  --resource-group rg-files-demo \
  --name share-demo \
  --deleted-version "$DELETED_VERSION"
```

:::note
LocalStack restores the share itself, but not the files it held when it was deleted: the restored share is empty.
:::

### Check storage account usage

Show how many storage accounts the subscription uses in a region, against the limit:

```bash
az storage account show-usage \
  --location westeurope
```

```bash title="Output"
{
  "currentValue": 1,
  "limit": 250,
  "name": {
    "localizedValue": "Storage Accounts",
    "value": "StorageAccounts"
  },
  "unit": "Count"
}
```

### Clean up

Delete the resource group and everything in it:

```bash
az group delete \
  --name rg-files-demo \
  --yes
```

## Features

The Azure Files emulator supports the following features:

- **File shares**: Create, get, update, list, and delete file shares, with quota, access tier, enabled protocols (SMB, or NFS on `FileStorage` accounts) and metadata.
- **Azure Files REST API**: Create and list directories, upload, download and delete files, copy files within a storage account, read file properties and manage file metadata, using the Azure CLI or the Azure Storage SDKs with a connection string, the account key or an account SAS.
- **Quota enforcement**: Range uploads that would exceed the share's quota fail with `ShareQuotaExceeded`.
- **Share snapshots**: Create snapshots of a share's contents, and delete a share together with its snapshots.
- **Soft delete and restore**: With `shareDeleteRetentionPolicy` enabled, deleted shares stay listed with `--include-deleted` for the retention period and can be restored.
- **Leases**: Acquire, renew, change, release, and break leases on a share; a leased share cannot be updated without its lease.
- **Usage statistics**: Get a share's usage in bytes with `--expand stats`. The share's snapshots count towards it.
- **Mounting from workloads**: Shares are also served over SMB 3 and NFS 4.1. AKS clusters include the Azure Files CSI driver, so pods can mount shares with the storage account key, and Container Apps environment storage can mount them as volumes.

## Configuration

| Variable | Default | Effect |
|---|---|---|
| `LS_AZURE_FILES_SMB_PORT` | `4445` | Port of the emulator's SMB proxy, which AKS nodes reach as the standard SMB port 445. Change it if the port is already in use. |
| `LS_AZURE_FILES_NFS_PORT` | `42049` | Port of the emulator's NFS proxy, which AKS nodes reach as the standard NFS port 2049. |

## Limitations

- **Setting file properties is not supported**: Set File Properties, which `az storage file update` and the SDKs' `set_http_headers` call, fails and leaves the file empty.
- **Restored shares are empty**: Restoring a soft-deleted share through Azure Resource Manager brings back the share and its settings, but not its files. Undeleting a share through the Azure Files REST API is not supported.
- **Soft delete is off until you enable it**: Getting the file service properties always reports share soft delete as enabled for 7 days, but deleted shares are only kept after you enable it with `az storage account file-service-properties update`, as shown above. Until then, a deleted share is removed permanently.
- **Snapshots are not listed**: Creating a snapshot works, but `az storage share-rm list --include-snapshot` does not return it.
- **Access tiers are recorded only**: Changing a share's access tier has no effect on behavior.
- **Identity-based access**: SMB access uses the storage account's primary key (`key1`); the secondary key does not work there. Microsoft Entra and Kerberos authentication are not emulated.
- **Container Instances**: Azure Files volumes in container groups are not mounted.

## API Coverage


### File Storage API coverage

Source service: `file-storage`. 12 of 12 tracked operations are implemented.

Service documentation: /azure/services/file-storage/

| Operation | Status |
| --- | --- |
| FileServices.GetServiceProperties | Implemented |
| FileServices.GetServiceUsage | Implemented |
| FileServices.List | Implemented |
| FileServices.ListServiceUsages | Implemented |
| FileServices.SetServiceProperties | Implemented |
| FileShares.Create | Implemented |
| FileShares.Delete | Implemented |
| FileShares.Get | Implemented |
| FileShares.Lease | Implemented |
| FileShares.List | Implemented |
| FileShares.Restore | Implemented |
| FileShares.Update | Implemented |
