How to use Azure Blob Storage for server backups
Azure Blob Storage keeps backups as blobs in a container inside a storage account, and it doesn't speak the S3 API, so you upload with AzCopy, the Azure CLI or rclone's azureblob backend. Create a general-purpose v2 account, give each server a container SAS that can read, create, write and list but not delete (or a managed identity on Azure VMs), and let lifecycle rules, soft delete and versioning handle retention. Lock a time-based retention policy if backups must survive a stolen credential.
Blob Storage doesn't speak S3
As of October 2026, Microsoft documents no S3-compatible endpoint for Blob Storage. Data goes in through the Blob REST API (used by AzCopy, the Azure CLI, rclone and the Azure SDKs), NFS 3.0 or SFTP, so a tool that only speaks S3 needs a gateway in between.
SFTP needs a hierarchical-namespace account, which rules out blob versioning, and costs $0.30 an hour while enabled in East US, as of October 2026.
Create the storage account and container
az storage account create --name acmebackups01 --resource-group backups-rg --location eastus --sku Standard_LRS --kind StorageV2 --access-tier Hot --min-tls-version TLS1_2 --allow-blob-public-access false--name: 3 to 24 lowercase letters and numbers, unique across Azure. It becomeshttps://acmebackups01.blob.core.windows.net.--sku: the redundancy, below. Leave it out and the CLI picksStandard_RAGRS.--kind StorageV2: general-purpose v2, which Microsoft recommends.--access-tier: the default tier for new blobs,Hot,CoolorCold. Archive can't be the default.--allow-blob-public-access false: no container can be made public.
az storage container create --name server-backups --account-name acmebackups01Container names: 3 to 63 lowercase letters, numbers and single dashes. Without --auth-mode login, the CLI fetches the account key using your login; with it, you need a Storage Blob Data role, since owning the account grants no data access. Then turn on data protection:
az storage account blob-service-properties update --account-name acmebackups01 --resource-group backups-rg --enable-delete-retention true --delete-retention-days 7 --enable-container-delete-retention true --container-delete-retention-days 7 --enable-versioning trueThe portal turns blob soft delete on by default for new accounts; the CLI doesn't.
Pick a redundancy option
| `--sku` | Where copies live | Durability per year | Archive tier |
|---|---|---|---|
Standard_LRS | One datacenter in the primary region | At least 11 nines | Yes |
Standard_ZRS | Three or more availability zones, written synchronously | At least 12 nines | No |
Standard_GRS | LRS, then copied asynchronously to a secondary region hundreds of miles away | At least 16 nines | Yes |
Standard_GZRS | ZRS, then copied asynchronously to a secondary region | At least 16 nines | No |
The RA- versions (Standard_RAGRS, Standard_RAGZRS) add read access to the secondary. Geo-replication is asynchronous, so a regional disaster can lose the newest writes. When backups already live at a different provider from your servers, LRS is often enough.
Access tiers and rehydration
| Tier | Minimum days | Retrieval | Storage, East US LRS |
|---|---|---|---|
| Hot | None | Free | $0.0208 per GB-month |
| Cool | 30 | $0.01 per GB | $0.0152 per GB-month |
| Cold | 90 | $0.03 per GB | $0.0036 per GB-month |
| Archive | 180 | $0.02 per GB, or $0.10 at high priority | $0.00099 per GB-month |
Prices as of October 2026, first 50 TB. Deleting, overwriting or re-tiering a blob before its minimum bills the remaining days, prorated; with soft delete on, the deletion counts when soft delete ends.
Hot, Cool and Cold read back in milliseconds. Archive is offline: rehydrating a blob takes up to 15 hours at standard priority, or under an hour at high priority for blobs under 10 GB, capped at 10 GiB an hour per account. Keep the copy you'd restore first out of Archive.
Give the server access
| Method | Scope | Notes |
|---|---|---|
| Service SAS on a stored access policy | One container, chosen permissions | Signed with the account key; revoke by deleting the policy |
| Managed identity with Storage Blob Data Contributor | The container the role covers | No secret on disk; Azure VMs, or other servers via Azure Arc; can delete |
| User delegation SAS | Like a service SAS | Signed with Entra ID; 7 days at most |
| Account key | All data, and can sign any SAS | Keep it off servers |
For a server outside Azure, create a stored access policy and a SAS that uses it, with your admin login:
az storage container policy create --container-name server-backups --name web01-upload --permissions rcwl --expiry 2027-04-01T00:00:00Z --account-name acmebackups01az storage container generate-sas --name server-backups --policy-name web01-upload --https-only --account-name acmebackups01 --output tsvrreads,ccreates new blobs,wwrites content and block lists,llists. Withoutd, the server can't delete backups.calone can complete a block upload only from REST service version 2026-04-06, so keepwunless your tool sends that version.- Revoke it by deleting or editing the policy, at most five per container. Regenerating the account key kills every SAS signed with it.
--https-onlyrefuses plain HTTP, and--output tsvprints only the token, without its leading?; add one when you append it to a URL.--expiryis in UTC.
Anyone holding the SAS has these rights until it expires or is revoked, so keep it readable only by the backup user. Turning Shared Key off (--allow-shared-key-access false) disables service SAS tokens too.
On an Azure VM, turn on the system-assigned identity under Security > Identity and grant its object (principal) ID the role on the container; changes can take 10 minutes:
az role assignment create --role "Storage Blob Data Contributor" --assignee-object-id <principal-id> --assignee-principal-type ServicePrincipal --scope "/subscriptions/<subscription-id>/resourceGroups/backups-rg/providers/Microsoft.Storage/storageAccounts/acmebackups01/blobServices/default/containers/server-backups"Upload with AzCopy
azcopy copy '/var/backups/web-01-2026-10-04.tar.gz' 'https://acmebackups01.blob.core.windows.net/server-backups/web-01/2026-10-04.tar.gz?<SAS>' --put-md5 --overwrite=false- Single quotes protect the
&characters in the SAS from the shell. --put-md5stores an MD5 that downloads check.--overwrite=falsefails on a name clash; the default istrue.--block-blob-tier=Coolsets the tier:Hot,Cool,ColdorArchive.
To stream an archive without a temporary file:
tar -czf - /etc /var/www | azcopy copy 'https://acmebackups01.blob.core.windows.net/server-backups/web-01/2026-10-04-files.tar.gz?<SAS>' --from-to PipeBlob--from-to PipeBlob tells AzCopy the source is a pipe. With a managed identity, export AZCOPY_AUTO_LOGIN_TYPE=MSI and drop the SAS from the URL. Schedule uploads with cron.
Upload with the Azure CLI
az storage blob upload --account-name acmebackups01 --container-name server-backups --name web-01/2026-10-04.tar.gz --file /var/backups/web-01-2026-10-04.tar.gz --sas-token '<SAS>'--overwrite defaults to false here, so a repeated name fails with ResourceExistsError. --tier Cool sets the tier, and --auth-mode login uses Entra ID instead of a SAS.
Use rclone's azureblob backend
[azure]
type = azureblob
sas_url = https://acmebackups01.blob.core.windows.net/server-backups?<SAS>
no_check_container = truerclone copy /var/backups/web-01/ azure:server-backups/web-01/A container SAS URL limits rclone to that container; on an Azure VM, use account = acmebackups01 and use_msi = true instead. no_check_container skips checking or creating the container. rclone stores MD5s for chunked uploads from local disk, so rclone check works. See rclone backups.
Expire old backups with lifecycle management
{
"rules": [
{
"enabled": true,
"name": "expire-server-backups",
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["server-backups/web-01/"]
},
"actions": {
"baseBlob": { "delete": { "daysAfterModificationGreaterThan": 30 } },
"version": { "delete": { "daysAfterCreationGreaterThan": 30 } }
}
}
}
]
}az storage account management-policy create --account-name acmebackups01 --resource-group backups-rg --policy @policy.jsonblobTypesis required.prefixMatchstarts with the container name; up to 10 per rule, no wildcards.baseBlob: the current version, deleted 30 days after its last change. With versioning on, it becomes a previous version.version: previous versions, deleted 30 days after first written, so on the next run. Lifecycle won't delete a current version that still has previous ones.- Soft delete then keeps them 7 days, billed: about 37 days per backup.
- The policy is written whole; changes take up to 24 hours. Lifecycle runs and deletes are free.
Soft delete and versioning
Blob soft delete keeps deleted blobs and the old content of overwritten ones for 1 to 365 days; container soft delete covers deleted containers; versioning keeps prior versions readable. Microsoft recommends all three, and their data is billed like live data. None protects the storage account itself: put a Resource Manager lock on it.
az storage blob undelete --account-name acmebackups01 --container-name server-backups --name web-01/2026-10-04.tar.gzWith versioning on, a deleted backup is a previous version: find it with az storage blob list --include v, then download it with az storage blob download --version-id, or copy it back over the current blob.
Immutable storage: time-based retention and legal holds
A time-based retention policy stops blobs being modified or deleted for 1 to 146,000 days from each blob's creation (--period is in days), while new blobs can still be written. After it expires, blobs can be deleted but still not overwritten. A legal hold blocks the same until it is cleared.
az storage container immutability-policy create --resource-group backups-rg --account-name acmebackups01 --container-name server-backups --period 14- New policies are unlocked and can be shortened or deleted, and Microsoft's container-level WORM page says unlocked policies don't provide delete protection. Lock it, typically within 24 hours, with
az storage container immutability-policy lockand the ETag fromaz storage container immutability-policy show. - A locked container-level policy can't be deleted or shortened, only extended, at most five times. The account can't be deleted while a container has one.
az storage container legal-hold set --tags case1 --container-name server-backups --account-name acmebackups01 --resource-group backups-rgsets a hold;legal-hold clearremoves it.- Microsoft's lifecycle docs say the delete action doesn't work on blobs in an immutable container. Check that expired backups really go, or delete them yourself after the period.
A locked policy can't be undone, and you pay for the storage until every blob in it expires. Test with a short unlocked policy first.
Verify a backup
az storage blob list --account-name acmebackups01 --container-name server-backups --prefix web-01/ --sas-token '<SAS>' --output tableazcopy copy 'https://acmebackups01.blob.core.windows.net/server-backups/web-01/2026-10-04.tar.gz?<SAS>' /tmp/restore-test.tar.gz && sha256sum /tmp/restore-test.tar.gz && tar -tzf /tmp/restore-test.tar.gz > /dev/null && echo OKAzCopy checks the stored MD5 (--check-md5, default FailIfDifferent) and the length on download. Compare the SHA-256 with one recorded before upload. See testing a restore.
What it costs
- Storage per GB-month, East US LRS, first 50 TB: Hot $0.0208, Cool $0.0152, Cold $0.0036, Archive $0.00099. GRS Hot is $0.0458. Soft-deleted data and versions count.
- Write operations per 10,000: Hot $0.05, Cool $0.10, Cold $0.18. Read operations per 10,000: Hot $0.004, Cool $0.01, Cold $0.10. Deletes are free.
- Data in is free. Internet egress: the first 100 GB a month is free, then $0.087 per GB from North America or Europe for the next 10 TB, over Microsoft's network.
Example, at October 2026 prices: 30 daily 5 GB backups under the policy above keep about 150 GB live plus 35 GB in soft delete, about $3.85 a month in Hot or $2.81 in Cool. A one-backup restore fits in the free 100 GB of egress, plus $0.05 retrieval from Cool.
Common errors
| Error | Cause and fix |
|---|---|
AuthorizationPermissionMismatch: This request is not authorized to perform this operation using this permission. | The SAS lacks a permission, or the identity has no Storage Blob Data role. Account owners don't get data access automatically. Add it and wait up to 10 minutes. |
AuthenticationFailed: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. | An expired SAS, clock skew, a regenerated key, or a SAS for another container. Make a new SAS and check the server clock. |
KeyBasedAuthenticationNotPermitted: Key based authentication is not permitted on this storage account. | Shared Key is off, which also blocks service SAS tokens. Use Entra ID or a user delegation SAS. |
AuthorizationFailure | The account's firewall or network rules block the server. Allow its IP address or network. |
BlobImmutableDueToPolicy: This operation is not permitted as the blob is immutable due to a policy. | A retention policy or legal hold. Wait, or upload under a new name. |
BlobArchived: This operation is not permitted on an archived blob. | Reading an Archive blob. Rehydrate it first. |
Keep a second copy outside this account, per the 3-2-1 rule, and encrypt backups before upload to keep them private.
Frequently asked questions
- Is Azure Blob Storage S3-compatible?
- No. As of October 2026, Microsoft documents no S3 endpoint for Blob Storage. Use AzCopy, the Azure CLI, rclone's
azureblobbackend or the Azure SDKs, or put an S3 gateway in front of it. - Which Azure access tier is best for backups?
- Hot for backups kept under 30 days, Cool for 30 days or more, Cold for 90 days or more. Archive is cheapest but offline, and rehydrating can take up to 15 hours at standard priority.
- Can a SAS token upload without being able to delete?
- Yes. A container SAS with
r,c,wandlcan read, create, write and list blobs, but not delete them, because it has nod.
How this was checked
Commands, limits and prices were checked against these official pages, on October 4, 2026:
- Azure Storage docs: Create a storage account
- Azure CLI reference: az storage account
- Azure Storage docs: Azure Storage redundancy
- Azure Storage docs: Create a blob container (naming rules)
- Azure CLI reference: az storage container
- Azure Storage docs: Secure File Transfer Protocol (SFTP) support for Blob Storage
- Azure Storage docs: Access tiers for blob data
- Azure Storage docs: Blob rehydration from the archive tier
- Azure Storage docs: Scalability and performance targets for Blob storage
- Azure Storage docs: Grant limited access with shared access signatures (SAS)
- Azure Storage REST API: Create a service SAS
- Azure Storage REST API: Create a user delegation SAS
- Azure Storage REST API: Put Blob
- Azure Storage REST API: Put Block List
- Azure CLI reference: az storage container policy
- Azure Storage docs: Manage storage account access keys
- Azure Storage docs: Prevent Shared Key authorization
- Azure RBAC docs: Built-in roles for Storage
- Azure Storage docs: Assign an Azure role for access to blob data
- Azure CLI reference: az role assignment
- Microsoft Entra docs: Configure managed identities on Azure VMs
- Azure Storage docs: Get started with AzCopy
- Azure Storage docs: Authorize AzCopy with a managed identity
- Azure Storage docs: Upload files to Blob Storage with AzCopy
- AzCopy reference: azcopy copy
- Azure CLI reference: az storage blob
- rclone docs: Microsoft Azure Blob Storage
- Azure Storage docs: Lifecycle management overview
- Azure Storage docs: Lifecycle management policy structure
- Azure Storage docs: Configure a lifecycle management policy
- Azure Storage docs: Lifecycle policies that delete blobs
- Azure Storage docs: Soft delete for blobs
- Azure Storage docs: Enable and manage soft delete for blobs
- Azure Storage docs: Soft delete for containers
- Azure Storage docs: Enable and manage soft delete for containers
- Azure Storage docs: Blob versioning
- Azure Storage docs: Enable and manage blob versioning
- Azure Storage docs: Immutable storage for blob data
- Azure Storage docs: Container-level WORM policies
- Azure Storage docs: Configure immutability policies for containers
- Azure CLI reference: az storage container immutability-policy
- Azure Storage REST API: Blob Storage error codes
- Azure Storage REST API: Common error codes
- Azure troubleshooting: 403 errors in Azure Blob Storage
- Microsoft Q&A: AuthorizationPermissionMismatch (raw service response)
- Azure Blob Storage pricing
- Azure bandwidth pricing