VPS Snaps

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.

10 min readUpdated Checked against official documentation

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

Terminal
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 becomes https://acmebackups01.blob.core.windows.net.
  • --sku: the redundancy, below. Leave it out and the CLI picks Standard_RAGRS.
  • --kind StorageV2: general-purpose v2, which Microsoft recommends.
  • --access-tier: the default tier for new blobs, Hot, Cool or Cold. Archive can't be the default.
  • --allow-blob-public-access false: no container can be made public.
Terminal
az storage container create --name server-backups --account-name acmebackups01

Container 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:

Terminal
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 true

The portal turns blob soft delete on by default for new accounts; the CLI doesn't.

Pick a redundancy option

`--sku`Where copies liveDurability per yearArchive tier
Standard_LRSOne datacenter in the primary regionAt least 11 ninesYes
Standard_ZRSThree or more availability zones, written synchronouslyAt least 12 ninesNo
Standard_GRSLRS, then copied asynchronously to a secondary region hundreds of miles awayAt least 16 ninesYes
Standard_GZRSZRS, then copied asynchronously to a secondary regionAt least 16 ninesNo

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

TierMinimum daysRetrievalStorage, East US LRS
HotNoneFree$0.0208 per GB-month
Cool30$0.01 per GB$0.0152 per GB-month
Cold90$0.03 per GB$0.0036 per GB-month
Archive180$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

MethodScopeNotes
Service SAS on a stored access policyOne container, chosen permissionsSigned with the account key; revoke by deleting the policy
Managed identity with Storage Blob Data ContributorThe container the role coversNo secret on disk; Azure VMs, or other servers via Azure Arc; can delete
User delegation SASLike a service SASSigned with Entra ID; 7 days at most
Account keyAll data, and can sign any SASKeep it off servers

For a server outside Azure, create a stored access policy and a SAS that uses it, with your admin login:

Terminal
az storage container policy create --container-name server-backups --name web01-upload --permissions rcwl --expiry 2027-04-01T00:00:00Z --account-name acmebackups01
Terminal
az storage container generate-sas --name server-backups --policy-name web01-upload --https-only --account-name acmebackups01 --output tsv
  • r reads, c creates new blobs, w writes content and block lists, l lists. Without d, the server can't delete backups.
  • c alone can complete a block upload only from REST service version 2026-04-06, so keep w unless 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-only refuses plain HTTP, and --output tsv prints only the token, without its leading ?; add one when you append it to a URL. --expiry is 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:

Terminal
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

Terminal
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-md5 stores an MD5 that downloads check.
  • --overwrite=false fails on a name clash; the default is true.
  • --block-blob-tier=Cool sets the tier: Hot, Cool, Cold or Archive.

To stream an archive without a temporary file:

Terminal
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

Terminal
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

~/.config/rclone/rclone.conf
[azure]
type = azureblob
sas_url = https://acmebackups01.blob.core.windows.net/server-backups?<SAS>
no_check_container = true
Terminal
rclone 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

policy.json
{
  "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 } }
        }
      }
    }
  ]
}
Terminal
az storage account management-policy create --account-name acmebackups01 --resource-group backups-rg --policy @policy.json
  • blobTypes is required. prefixMatch starts 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.

Terminal
az storage blob undelete --account-name acmebackups01 --container-name server-backups --name web-01/2026-10-04.tar.gz

With 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.

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.

Terminal
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 lock and the ETag from az 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-rg sets a hold; legal-hold clear removes 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

Terminal
az storage blob list --account-name acmebackups01 --container-name server-backups --prefix web-01/ --sas-token '<SAS>' --output table
Terminal
azcopy 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 OK

AzCopy 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

ErrorCause 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.
AuthorizationFailureThe 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 azureblob backend 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, w and l can read, create, write and list blobs, but not delete them, because it has no d.

How this was checked

Commands, limits and prices were checked against these official pages, on October 4, 2026: