Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions modules/azure-sa-backup/.terraform-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
formatter: "markdown"

version: ""

Comment on lines +3 to +4
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An empty version field is ambiguous and may be treated as invalid by tooling depending on terraform-docs version/config parsing. Prefer removing the version key entirely (if not needed) or setting it to an explicit supported version constraint/value.

Suggested change
version: ""

Copilot uses AI. Check for mistakes.
header-from: docs/header.md
footer-from: docs/footer.md

recursive:
enabled: false
path: modules
include-main: true

sections:
hide: []
show: []

content: ""

output:
file: "README.md"
mode: inject
template: |-
<!-- BEGIN_TF_DOCS -->
{{ .Content }}
<!-- END_TF_DOCS -->
Comment on lines +23 to +25
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With output.mode: inject, the README should contain the BEGIN_TF_DOCS / END_TF_DOCS markers, but the injected template content generally should not include those same markers. Keeping markers inside the injected template can lead to nested/duplicated markers on subsequent terraform-docs runs. Recommendation: remove the markers from the template (keep only {{ .Content }}), and rely on the README markers for injection boundaries.

Suggested change
<!-- BEGIN_TF_DOCS -->
{{ .Content }}
<!-- END_TF_DOCS -->
{{ .Content }}

Copilot uses AI. Check for mistakes.

output-values:
enabled: false
from: ""

sort:
enabled: true
by: name

settings:
anchor: true
color: true
default: true
description: false
escape: true
hide-empty: false
html: true
indent: 2
lockfile: true
read-comments: true
required: true
sensitive: true
type: true
139 changes: 98 additions & 41 deletions modules/azure-sa-backup/README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,18 @@
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.7.0 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | ~> 4.6.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | ~> 4.6.0 |

## Resources

| Name | Type |
|------|------|
| [azurerm_backup_container_storage_account.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_container_storage_account) | resource |
| [azurerm_backup_policy_file_share.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_policy_file_share) | resource |
| [azurerm_backup_protected_file_share.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_protected_file_share) | resource |
| [azurerm_data_protection_backup_instance_blob_storage.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/data_protection_backup_instance_blob_storage) | resource |
| [azurerm_data_protection_backup_policy_blob_storage.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/data_protection_backup_policy_blob_storage) | resource |
| [azurerm_data_protection_backup_vault.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/data_protection_backup_vault) | resource |
| [azurerm_recovery_services_vault.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/recovery_services_vault) | resource |
| [azurerm_role_assignment.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_backup_blob"></a> [backup\_blob](#input\_backup\_blob) | Specifies the backup configuration for the storage blob | <pre>object({<br/> vault_name = string<br/> datastore_type = string<br/> redundancy = string<br/> identity_type = optional(string)<br/> role_assignment = string<br/> instance_blob_name = string<br/> storage_account_container_names = optional(list(string))<br/> policy = object({<br/> name = string<br/> backup_repeating_time_intervals = optional(list(string))<br/> operational_default_retention_duration = optional(string)<br/> retention_rule = optional(list(object({<br/> name = string<br/> duration = string<br/> criteria = object({<br/> absolute_criteria = optional(string)<br/> days_of_month = optional(list(number))<br/> days_of_week = optional(list(string))<br/> months_of_year = optional(list(string))<br/> scheduled_backup_times = optional(list(string))<br/> weeks_of_month = optional(list(string))<br/> })<br/> life_cycle = object({<br/> data_store_type = string<br/> duration = string<br/> })<br/> priority = number<br/> })))<br/> time_zone = optional(string)<br/> vault_default_retention_duration = optional(string)<br/> retention_duration = optional(string)<br/> })<br/> })</pre> | `null` | no |
| <a name="input_backup_resource_group_name"></a> [backup\_resource\_group\_name](#input\_backup\_resource\_group\_name) | The name for the resource group for the backups | `string` | n/a | yes |
| <a name="input_backup_share"></a> [backup\_share](#input\_backup\_share) | Specifies the backup configuration for the storage share | <pre>object({<br/> policy_name = string<br/> recovery_services_vault_name = string<br/> sku = string<br/> soft_delete_enabled = optional(bool)<br/> storage_mode_type = optional(string, "GeoRedundant")<br/> cross_region_restore_enabled = optional(bool)<br/> source_file_share_name = list(string)<br/> identity = optional(object({<br/> type = optional(string, "SystemAssigned")<br/> identity_ids = optional(list(string), [])<br/> }))<br/> encryption = optional(object({<br/> key_id = optional(string, null)<br/> infrastructure_encryption_enabled = optional(bool, false)<br/> user_assigned_identity_id = optional(string, null)<br/> use_system_assigned_identity = optional(bool, false)<br/> }))<br/> timezone = optional(string)<br/> backup = object({<br/> frequency = string<br/> time = string<br/> })<br/> retention_daily = object({<br/> count = number<br/> })<br/> retention_weekly = optional(object({<br/> count = number<br/> weekdays = optional(list(string), ["Sunday"])<br/> }))<br/> retention_monthly = optional(object({<br/> count = number<br/> weekdays = optional(list(string), ["Sunday"])<br/> weeks = optional(list(string), ["First"])<br/> days = optional(list(number))<br/> }))<br/> retention_yearly = optional(object({<br/> count = number<br/> months = optional(list(string), ["January"])<br/> weekdays = optional(list(string), ["Sunday"])<br/> weeks = optional(list(string), ["First"])<br/> days = optional(list(number))<br/> }))<br/> })</pre> | `null` | no |
| <a name="input_lifecycle_policy_rule"></a> [lifecycle\_policy\_rule](#input\_lifecycle\_policy\_rule) | n/a | <pre>list(object({<br/> name = string<br/> enabled = bool<br/> filters = object({<br/> prefix_match = list(string)<br/> blob_types = list(string)<br/> })<br/> actions = object({<br/> base_blob = object({ delete_after_days_since_creation_greater_than = number })<br/> snapshot = object({ delete_after_days_since_creation_greater_than = number })<br/> version = object({ delete_after_days_since_creation = number })<br/> })<br/> }))</pre> | `null` | no |
| <a name="input_storage_account_id"></a> [storage\_account\_id](#input\_storage\_account\_id) | The ID of the storage account | `string` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to resources | `map(string)` | `{}` | no |
| <a name="input_tags_from_rg"></a> [tags\_from\_rg
<!-- BEGIN_TF_DOCS -->
# Azure Storage Account Backup Terraform Module

## Overview

## Outputs
This Terraform module allows you to configure backup for Azure Storage Accounts, supporting both file shares and blob storage, with advanced retention and policy options.

No outputs.
## Main features
- Configure backup for file shares and blob storage.
- Support for Recovery Services Vault and Data Protection Vault.
- Advanced retention, scheduling, and policy configuration.
- Flexible tagging and resource group selection.
- Realistic configuration example.

## Example
## Complete usage example

```yaml
values:
Expand Down Expand Up @@ -119,3 +89,90 @@ No outputs.
vault_default_retention_duration: "P30D"
retention_duration: "P30D"
```

## Notes
- The `backup_share` and `backup_blob` blocks allow for advanced backup and retention configuration.
- You can use tags and inherit them from the resource group.
- Supports both Recovery Services Vault and Data Protection Vault for different backup scenarios.

## File structure

```
.
├── main.tf
├── variables.tf
├── outputs.tf
├── blobs.tf
├── shares.tf
├── locals.tf
├── README.md
├── CHANGELOG.md
└── docs/
├── header.md
└── footer.md
```

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.7.0 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | ~> 4.6.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | ~> 4.6.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [azurerm_backup_container_storage_account.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_container_storage_account) | resource |
| [azurerm_backup_policy_file_share.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_policy_file_share) | resource |
| [azurerm_backup_protected_file_share.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_protected_file_share) | resource |
| [azurerm_data_protection_backup_instance_blob_storage.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/data_protection_backup_instance_blob_storage) | resource |
| [azurerm_data_protection_backup_policy_blob_storage.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/data_protection_backup_policy_blob_storage) | resource |
| [azurerm_data_protection_backup_vault.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/data_protection_backup_vault) | resource |
| [azurerm_recovery_services_vault.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/recovery_services_vault) | resource |
| [azurerm_role_assignment.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_backup_blob"></a> [backup\_blob](#input\_backup\_blob) | Specifies the backup configuration for the storage blob | <pre>object({<br/> vault_name = string<br/> datastore_type = string<br/> redundancy = string<br/> identity_type = optional(string)<br/> role_assignment = string<br/> instance_blob_name = string<br/> storage_account_container_names = optional(list(string))<br/> policy = object({<br/> name = string<br/> backup_repeating_time_intervals = optional(list(string))<br/> operational_default_retention_duration = optional(string)<br/> retention_rule = optional(list(object({<br/> name = string<br/> duration = string<br/> criteria = object({<br/> absolute_criteria = optional(string)<br/> days_of_month = optional(list(number))<br/> days_of_week = optional(list(string))<br/> months_of_year = optional(list(string))<br/> scheduled_backup_times = optional(list(string))<br/> weeks_of_month = optional(list(string))<br/> })<br/> life_cycle = object({<br/> data_store_type = string<br/> duration = string<br/> })<br/> priority = number<br/> })))<br/> time_zone = optional(string)<br/> vault_default_retention_duration = optional(string)<br/> retention_duration = optional(string)<br/> })<br/> })</pre> | `null` | no |
| <a name="input_backup_resource_group_name"></a> [backup\_resource\_group\_name](#input\_backup\_resource\_group\_name) | The name for the resource group for the backups | `string` | n/a | yes |
| <a name="input_backup_share"></a> [backup\_share](#input\_backup\_share) | Specifies the backup configuration for the storage share | <pre>object({<br/> policy_name = string<br/> recovery_services_vault_name = string<br/> sku = string<br/> soft_delete_enabled = optional(bool)<br/> storage_mode_type = optional(string, "GeoRedundant")<br/> cross_region_restore_enabled = optional(bool)<br/> source_file_share_name = list(string)<br/> identity = optional(object({<br/> type = optional(string, "SystemAssigned")<br/> identity_ids = optional(list(string), [])<br/> }))<br/> encryption = optional(object({<br/> key_id = optional(string, null)<br/> infrastructure_encryption_enabled = optional(bool, false)<br/> user_assigned_identity_id = optional(string, null)<br/> use_system_assigned_identity = optional(bool, false)<br/> }))<br/> timezone = optional(string)<br/> backup = object({<br/> frequency = string<br/> time = string<br/> })<br/> retention_daily = object({<br/> count = number<br/> })<br/> retention_weekly = optional(object({<br/> count = number<br/> weekdays = optional(list(string), ["Sunday"])<br/> }))<br/> retention_monthly = optional(object({<br/> count = number<br/> weekdays = optional(list(string), ["Sunday"])<br/> weeks = optional(list(string), ["First"])<br/> days = optional(list(number))<br/> }))<br/> retention_yearly = optional(object({<br/> count = number<br/> months = optional(list(string), ["January"])<br/> weekdays = optional(list(string), ["Sunday"])<br/> weeks = optional(list(string), ["First"])<br/> days = optional(list(number))<br/> }))<br/> })</pre> | `null` | no |
| <a name="input_lifecycle_policy_rule"></a> [lifecycle\_policy\_rule](#input\_lifecycle\_policy\_rule) | n/a | <pre>list(object({<br/> name = string<br/> enabled = bool<br/> filters = object({<br/> prefix_match = list(string)<br/> blob_types = list(string)<br/> })<br/> actions = object({<br/> base_blob = object({ delete_after_days_since_creation_greater_than = number })<br/> snapshot = object({ delete_after_days_since_creation_greater_than = number })<br/> version = object({ delete_after_days_since_creation = number })<br/> })<br/> }))</pre> | `null` | no |
| <a name="input_storage_account_id"></a> [storage\_account\_id](#input\_storage\_account\_id) | The ID of the storage account | `string` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to resources | `map(string)` | `{}` | no |
| <a name="input_tags_from_rg"></a> [tags\_from\_rg](#input\_tags\_from\_rg) | Use resource group tags as base for module tags | `bool` | `false` | no |

## Outputs

No outputs.

## Examples

For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples):

- [basic](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples/basic) - Backup configuration for file shares and blobs with daily policies.

## Resources and support

- [Official Azure Backup documentation](https://learn.microsoft.com/en-us/azure/backup/)
- [Terraform reference for azurerm\_backup\_container\_storage\_account](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_container_storage_account)
- [Terraform reference for azurerm\_data\_protection\_backup\_policy\_blob\_storage](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/data_protection_backup_policy_blob_storage)
- [Terraform reference for azurerm\_backup\_policy\_file\_share](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_policy_file_share)

## Support

For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
<!-- END_TF_DOCS -->
50 changes: 50 additions & 0 deletions modules/azure-sa-backup/_examples/basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Basic example: configure backup for Azure Storage Account (file shares + blobs)

module "azure_sa_backup" {
source = "../../"

backup_resource_group_name = "example-backup-rg"
storage_account_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Storage/storageAccounts/examplestorage"

backup_share = {
policy_name = "daily-backup-policy"
recovery_services_vault_name = "example-backup-vault"
sku = "Standard"
soft_delete_enabled = true
storage_mode_type = "GeoRedundant"
cross_region_restore_enabled = true
source_file_share_name = ["datadir"]
timezone = "UTC"
backup = {
frequency = "Daily"
time = "02:00"
}
retention_daily = {
count = 7
}
}

backup_blob = {
vault_name = "example-backup-vault"
datastore_type = "AzureBlob"
redundancy = "GeoRedundant"
role_assignment = "Storage Blob Data Reader"
instance_blob_name = "datadir"
storage_account_container_names = ["blob1"]
policy = {
name = "blob-policy"
backup_repeating_time_intervals = ["R/2024-09-01T02:00:00+00:00/P1D"]
operational_default_retention_duration = "P7D"
retention_rule = []
time_zone = "UTC"
vault_default_retention_duration = "P30D"
retention_duration = "P30D"
}
}

lifecycle_policy_rule = []

tags = {
environment = "dev"
}
}
43 changes: 43 additions & 0 deletions modules/azure-sa-backup/_examples/basic/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Basic example values for azure-sa-backup module

backup_resource_group_name: example-backup-rg
storage_account_id: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Storage/storageAccounts/examplestorage

backup_share:
policy_name: daily-backup-policy
recovery_services_vault_name: example-backup-vault
sku: Standard
soft_delete_enabled: true
storage_mode_type: GeoRedundant
cross_region_restore_enabled: true
source_file_share_name:
- datadir
timezone: UTC
backup:
frequency: Daily
time: "02:00"
retention_daily:
count: 7

backup_blob:
vault_name: example-backup-vault
datastore_type: AzureBlob
redundancy: GeoRedundant
role_assignment: Storage Blob Data Reader
instance_blob_name: datadir
storage_account_container_names:
- blob1
policy:
name: blob-policy
backup_repeating_time_intervals:
- R/2024-09-01T02:00:00+00:00/P1D
operational_default_retention_duration: P7D
retention_rule: []
time_zone: UTC
vault_default_retention_duration: P30D
retention_duration: P30D

lifecycle_policy_rule: []

tags:
environment: dev
Loading