Backup for Azure VMs, the way the Well‑Architected Framework recommends.
A single, vetted Bicep module that provisions a Recovery Services Vault, an Enhanced (V2) backup policy with long‑term retention, and registers any number of VMs as protected items. Production defaults out of the box. Drop it into your pipeline and ship.
What this module deploys
Three resource families, one orchestrator. Idempotent — re-running adds new VMs without touching existing ones.
Well‑Architected alignment
Defaults are tuned for production. Every safeguard below is on by default — opt out, don't opt in.
| Pillar | Default behavior | Override |
|---|---|---|
| Reliability | GeoRedundant storage with Cross‑Region Restore enabled. | vaultStorageRedundancy |
| Reliability | Long‑term retention: 30 daily / 12 weekly / 12 monthly / 5 yearly. | dailyRetentionDays … |
| Reliability | Enhanced (V2) policy — supports Trusted Launch and 30‑day instant restore. | instantRpRetentionDays |
| Security | Always‑On enhanced soft‑delete (cannot be disabled later). | softDeleteRetentionInDays |
| Security | Immutability enabled (Unlocked → flip to Locked once verified). | immutabilityState |
| Security | System‑assigned managed identity on the vault. | — |
| Security | Public network access toggle for Private Endpoint scenarios. | publicNetworkAccess |
| Operational Excellence | Diagnostic settings (all logs + metrics) to Log Analytics. | logAnalyticsWorkspaceId |
| Operational Excellence | Tags applied to every resource. | tags |
| Cost Optimization | Tiering set to DoNotTier — opt into archive when retention > 3 months. | edit policy module |
Quick start
Three steps. The whole thing is parameterized — most teams only edit the main.bicepparam file.
-
Download or clone the module
Use the Download all files button at the top, or pull it from the internal Bicep registry once published.
-
Edit
main.bicepparamSet
vaultName, yourvmsToProtectarray, andtags. Everything else has sensible production defaults. -
Validate, then deploy
Run a
what-iffirst; deploy when the plan looks right.1# Validate2az deployment group what-if \3 --resource-group rg-platform-rsv \4 --template-file main.bicep \5 --parameters main.bicepparam67# Deploy8az deployment group create \9 --resource-group rg-platform-rsv \10 --template-file main.bicep \11 --parameters main.bicepparam
Files
Six files. Click a tab to view, copy, or download an individual file. Use the button in the hero to grab everything as a ZIP.
Parameters reference
All inputs to main.bicep. Defaults shown — override in your .bicepparam file.
| Name | Type | Default | Description |
|---|---|---|---|
| location | string | resourceGroup().location | Region for the vault and policy. |
| vaultName | string | — | Recovery Services Vault name. Required. |
| vaultStorageRedundancy | string | 'GeoRedundant' | LRS / ZRS / GRS. Use GRS for production. |
| enableCrossRegionRestore | bool | true | Requires GRS. Cannot be disabled later. |
| softDeleteRetentionInDays | int | 14 | 14–180 days. Increase for sensitive workloads. |
| immutabilityState | string | 'Unlocked' | Disabled / Unlocked / Locked. Locked is irreversible. |
| publicNetworkAccess | string | 'Enabled' | Set to Disabled when fronting with Private Endpoint. |
| logAnalyticsWorkspaceId | string | '' | Resource ID of LAW for diagnostics. Empty = skip. |
| backupPolicyName | string | 'bp-vm-daily-enhanced' | Name of the V2 policy created. |
| dailyBackupTime | string | '22:00' | HH:mm in the policy time zone. |
| timeZone | string | 'UTC' | Schedule time zone (e.g. 'Eastern Standard Time'). |
| dailyRetentionDays | int | 30 | Daily recovery points to keep. |
| weeklyRetentionWeeks | int | 12 | Weekly RPs (Sunday). |
| monthlyRetentionMonths | int | 12 | Monthly RPs (1st Sunday). |
| yearlyRetentionYears | int | 5 | Yearly RPs (1st Sunday of January). |
| instantRpRetentionDays | int | 7 | Snapshot retention. V2 supports up to 30. |
| vmsToProtect | array | [] | Each: { name, resourceGroup, subscriptionId? }. |
| tags | object | { workload, managedBy, costCenter } | Applied to every resource. |
Hardening for production
Run through this list before declaring the vault production‑ready.
- Lock immutabilityOnce the policy is reviewed and stable, set
immutabilityState = 'Locked'. This is irreversible — verify first. - Disable public network accessSet
publicNetworkAccess = 'Disabled'and front the vault with a Private Endpoint in your hub network. - Extend soft‑delete windowIncrease
softDeleteRetentionInDaysto 30–90 for regulated workloads. - Enable Multi‑User Authorization (MUA)Associate the vault with a Resource Guard in a separate subscription so destructive operations require a second approver.
- Enforce with Azure PolicyAssign built‑ins: "Azure Backup should be enabled for VMs", "RSV should use private link", "Soft delete should be enabled on RSV".
- Wire alertsAdd alerts for backup job failures, retention drift, and unauthorized policy changes through the diagnostic settings already configured.