qumulo_filesystem_azure (Resource)¶
Creates and manages a Qumulo filesystem deployment on Azure.
Subnet Service Endpoints Required
Your Virtual Network subnet must have the Microsoft.KeyVault and Microsoft.Storage service endpoints enabled before deploying a cluster. To verify, go to the Azure Portal, navigate to Virtual networks > your VNet > Settings > Service endpoints, and confirm both endpoints are added for the target subnet. Deployment will fail without these service endpoints.
Example Usage¶
terraform {
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
}
}
provider "qumulo" {
azure {
subscription_id = "your-azure-subscription-id"
environment = "public"
}
}
resource "qumulo_filesystem_azure" "cluster" {
cluster_name = "mycluster"
deployment_name = "mycluster"
resource_group_name = "rg-qumulo"
location = "eastus2"
subnet_id = var.subnet_id
node_count = 5
vm_type = "Standard_L8s_v3"
admin_password = var.admin_password
ssh_public_key = file("~/.ssh/id_rsa.pub")
allow_cidrs = ["10.0.0.0/8"]
cluster_product_type = "COLD"
soft_capacity_limit_tb = 1000
key_vault_id = var.key_vault_id
deletion_protection = true # recommended: guard the cluster's VMs and storage accounts
marketplace_image = [{
publisher = "RedHat"
offer = "RHEL"
sku = "93-gen2"
version = "latest"
}]
naming = [{
vm_name = "myapp-{node_id}"
storage_account = "myappstor{index:02}"
}]
tags = {
environment = "production"
}
}
Schema¶
Required¶
NOTE: Write-only arguments are supported in Terraform 1.11 and later.
admin_password(String, Sensitive, Write-only) Administrator password for the cluster. Must be 8-128 characters and include at least 3 of: lowercase letter, uppercase letter, number, special character. To change the admin password after creation, use the Qumulo UI or qumulo-cli.allow_cidrs(Set of String) List of CIDR blocks allowed to access the cluster.location(String) Azure region for deployment.node_count(Number) Number of nodes in the cluster (1, or 3-24; 2 is not supported, and 4 requires a single availability zone).resource_group_name(String) Azure resource group name.subnet_id(String) Full Azure resource ID of the subnet. The cluster's storage accounts are restricted to this subnet (public network access enabled, scoped to selected networks), so the subnet must have the Microsoft.Storage service endpoint enabled. Example: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet}vm_type(String) Azure VM size for cluster nodes. Only L-series storage-optimized VMs are supported (changing triggers cluster replacement).
Optional¶
NOTE: Write-only arguments are supported in Terraform 1.11 and later.
availability_zones(Set of String) Availability zones for deployment. Omit for zoneless regions (e.g., northcentralus, westus, ukwest). Zone support is validated dynamically. Changing triggers replacement.cluster_fqdn(String) Fully qualified domain name for Qumulo Core authoritative DNS. When set, the cluster answers DNS queries for this name with its floating IPs (round-robin). Requires at least one floating IP and cluster_version >= 7.5.0. Remove to disable authoritative DNS. Delegating or forwarding this name to the cluster's floating IPs is your responsibility.cluster_name(String) Name of the Qumulo cluster as it appears in qfsd and the Qumulo UI (2-15 characters; case preserved). When omitted, defaults toname. Not refreshed from the running cluster. Changing it forces a new cluster. Requiresdeployment_name.cluster_node_identity_id(String) Resource ID of user-assigned managed identity for cluster nodes. When provided, RBAC roles are not auto-created. Example: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{name}cluster_product_type(String) Qumulo cluster product type (immutable after creation). HOT or COLD. The storage backing a HOT cluster is selected by storage_class.cluster_uuid(String) UUID of the Qumulo cluster. Set this only when importing an existing cluster whose UUID cannot be recovered automatically; new clusters receive a generated UUID and the value cannot be changed afterward.cluster_version(String) Qumulo cluster version. If omitted, the latest available version is used. New clusters must meet the provider's minimum supported version. Immutable after creation.create_appconfig_private_endpoint(Boolean) Create a private endpoint for the deployment's App Configuration store in the cluster subnet. Setprivate_link_appconfig_dns_zone_idas well to register the endpoint in an Azure Private DNS zone. Without a zone, readappconfig_private_endpointafter apply and create the DNS record yourself. Turning this off deletes the private endpoint. Remove any DNS records that point at it first. Each endpoint carries a per-hour Azure cost. If a privatelink.azconfig.io DNS zone is already linked to the VNet, setprivate_link_appconfig_dns_zone_idtoo, or the resource stops resolving inside the VNet.create_keyvault_private_endpoint(Boolean) Create a private endpoint for the Key Vault this deployment creates, in the cluster subnet. Cannot be used withkey_vault_id. The provider only builds private endpoints for vaults it creates. Setprivate_link_keyvault_dns_zone_idas well to register the endpoint in an Azure Private DNS zone. Turning this off deletes the private endpoint. Remove any DNS records that point at it first. If a privatelink.vaultcore.azure.net DNS zone is already linked to the VNet, setprivate_link_keyvault_dns_zone_idtoo, or the resource stops resolving inside the VNet.create_storage_private_endpoint(Boolean) Create one blob private endpoint per cluster storage account, in the cluster subnet. A capacity increase that adds accounts gives each new account its own endpoint. Setprivate_link_storage_dns_zone_idas well to register them in an Azure Private DNS zone. Turning this off deletes the private endpoints. Remove any DNS records that point at them first. Each endpoint carries a per-hour Azure cost, so a large cluster creates a correspondingly large number of them. If a privatelink.blob.core.windows.net DNS zone is already linked to the VNet, setprivate_link_storage_dns_zone_idtoo, or the resource stops resolving inside the VNet.custom_image_id(String) Custom VM image ID to use instead of default Ubuntu image.deletion_protection(Boolean) Protects the cluster's VMs and storage accounts from deletion — includingterraform destroy, the Azure portal, and the Azure CLI — withCanNotDeletemanagement locks. Whiletrue,terraform destroyrefuses to run. Deleting a protected cluster is a deliberate two-step gesture: setdeletion_protection = false, runterraform apply, then runterraform destroy. Provider-managed operations (scaling, node replacement) succeed transparently while protection is on. Managing locks requires theMicrosoft.Authorization/locks/*permission (Owner, User Access Administrator, or a custom role) — Contributor alone is not enough. Defaults tofalse.deployment_name(String) Seed for every Azure resource name (VMs, disks, storage accounts, NSGs) (2-15 characters: letters, digits, and interior hyphens; capped at 15 by Azure's 24-char storage-account limit). Derived Azure resource names are lowercased, so case is cosmetic: changing only the case of an existingdeployment_namerenames nothing and never replaces the cluster. The provider appends an immutable random suffix on first deploy to formdeployment_unique_name, the actual naming seed. When omitted, defaults to the lowercasedname. Changing it to a different name forces a new cluster. Requirescluster_name.disable_appconfig_public_network_access(Boolean) Disable public network access to App Configuration.disable_keyvault_public_network_access(Boolean) Disable public network access to Key Vault.floating_ip_count(Number) Number of floating IPs to assign to the cluster. Must be 0 (disabled) or between 3 and 100. Requires networking_mode 'host_managed'. Resolves to 0 on create, and on the first plan after import, when unset. Once a count has been applied, omitting the attribute keeps the previous value — set it to 0 explicitly to remove floating IPs.key_vault_id(String) Full Azure resource ID of a customer-managed Key Vault. When provided, the provider uses this vault instead of creating one. The vault must permit network access from the cluster subnet: the nodes read their storage SAS tokens from it during cluster creation and for the life of the cluster. If the vault restricts network access, either add aMicrosoft.KeyVaultservice endpoint on the cluster subnet plus a matching virtual network rule on the vault, or place a Key Vault private endpoint in the cluster subnet. A vault firewall that denies the nodes fails cluster creation with a storage URI validation error. The customer is responsible for vault lifecycle, network configuration, and access policies. Example: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/{name}marketplace_image(Attributes List) Azure Marketplace image specification for cluster nodes (mutually exclusive with custom_image_id). (see below for nested schema)name(String) Back-compat shortcut that sets BOTH the qfsd cluster name and the deployment infrastructure name (2-15 characters: letters, digits, and interior hyphens; no leading or trailing hyphen). Mutually exclusive withcluster_name/deployment_name. Derived Azure resource names are lowercased.naming(Attributes List) Custom naming templates for Azure resources. When omitted, default naming is used. (see below for nested schema)networking_mode(String) Network management mode for cluster nodes. Use 'host_managed' (new clusters default to this) for clusters created by this provider, or 'qumulo_managed' for clusters originally created by azure-terraform-cnq. Immutable after creation. Imported clusters have no mode until you declare one, because no API reports how an existing cluster was deployed.nexus_registration_key(String, Sensitive, Deprecated, Write-only) Single-use Qumulo Nexus onboarding OTP that binds the cluster to a Nexus account on first boot. Whennexus_api_tokenis configured on the provider, this attribute is auto-minted via the Nexus API; any value supplied here is ignored. For deployments withoutnexus_api_token, supply an OTP minted from https://nexus.qumulo.com/user/registration-key. Only applied during cluster creation. This is a write-only attribute: its value is sent to the provider during apply but never persisted to Terraform state, so the single-use OTP cannot leak from the state file. Write-only attributes require Terraform CLI 1.11 or later.node_hooks(Attributes) Customer shell spliced into the node boot script at the pre_run / post_run anchors. Runs as root; must be idempotent; do not embed secrets. See the Customizing Cluster Boot guide for anchor timing, the shell variables in scope, and safety rules. (see below for nested schema)nsg_allow_ingress_icmp(Boolean) Enable ICMP ingress in NSG rules for network diagnostics (ping).persistent_storage_resource_group(String) Resource group containing persistent storage accounts and KeyVault. Required for clusters created with the legacy azure-terraform-cnq module, where persistent storage lives in a separate resource group. If omitted, defaults to resource_group_name.private_link_appconfig_dns_zone_id(String) Full Azure resource ID of the privatelink.azconfig.io DNS zone. Enables private endpoints for App Configuration. Example: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/privateDnsZones/privatelink.azconfig.io. Requires create_appconfig_private_endpoint = true.private_link_keyvault_dns_zone_id(String) Full Azure resource ID of the privatelink.vaultcore.azure.net DNS zone. Enables private endpoints for Key Vault. Example: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net. Requires create_keyvault_private_endpoint = true.private_link_storage_dns_zone_id(String) Full Azure resource ID of the privatelink.blob.core.windows.net DNS zone. Registers the storage private endpoints in that zone. Removing this while the endpoints stay in place deletes only the DNS zone group, not the endpoints themselves. Requires create_storage_private_endpoint = true. Example: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.netprovisioner_custom_image_id(String) Custom VM image ID for the provisioner instead of default Ubuntu.provisioner_hooks(Attributes) Customer shell spliced into the provisioner boot script at the pre_run / post_run anchors. Runs as root; must be idempotent; do not embed secrets. See the Customizing Cluster Boot guide for anchor timing, the shell variables in scope, and safety rules. (see below for nested schema)provisioner_identity_id(String) Resource ID of user-assigned managed identity for provisioner VM. When provided, RBAC roles are not auto-created. Example: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{name}provisioner_marketplace_image(Attributes List) Azure Marketplace image specification for provisioner VM. (see below for nested schema)provisioner_vm_type(String) VM size for the provisioner instance used during deployment operations.soft_capacity_limit_tb(Number) Soft capacity limit in TB (50TB to 10000TB). Can be increased to add storage accounts, but cannot be decreased. Increases are limited to less than 5000TB per apply; larger changes must be applied in steps.ssh_public_key(String) SSH public key content for cluster access. Use file(var.ssh_public_key_path) to read from a file.storage_class(String) Storage backing the cluster's persistent data (immutable after creation). HOT clusters support STANDARD (Hot-tier storage accounts, plain hot storage) and INTELLIGENT_TIERING (Smart-tier storage accounts, intelligent tiering; requires Qumulo Core 7.8.4 or newer and storage_replication_type = ZRS, since Azure only permits the Smart access tier on zone-redundant storage). Defaults to INTELLIGENT_TIERING on Core 7.8.4+, STANDARD on older versions. COLD clusters use STANDARD.storage_replication_type(String) Azure storage replication type (immutable after creation). LRS or ZRS. LRS is incompatible with storage_class INTELLIGENT_TIERING, which requires zone-redundant storage.tags(Map of String) Tags to apply to Azure resources.timeouts(Block, Optional) (see below for nested schema)
Read-Only¶
appconfig_private_endpoint(Attributes) FQDN and private IPv4 address of the App Configuration private endpoint, or null whencreate_appconfig_private_endpointis false. Use these to create a DNS record when you run your own DNS. (see below for nested schema)cluster_reference(Attributes) Aggregated cluster identity for downstream resources. Equivalent to{ cluster_api_endpoint, cluster_name, cluster_uuid, endpoint_ips, resource_group_name, subnet_id, uses_floating_ips }— pass directly toqumulo_threat_detection_azure.cluster_referenceso the customer can wire one reference instead of seven. (see below for nested schema)deployment_unique_name(String) The immutable unique deployment name (<deployment_name>-<random suffix>) used to name and tag every cloud resource, and the Terraform import ID. Stable for the deployment's life.endpoint_ips(List of String) Endpoint IP addresses for client access: the cluster's floating IPs when it has any, otherwise the node VM private IP addresses.floating_ips(Set of String) Floating IP addresses assigned to the cluster. Empty when floating_ip_count is 0. Refreshed from the node NICs on every read, so out-of-band changes surface as drift.id(String) Unique identifier for the resource (deployment name).internal_state(String) Internal state for tracking multi-phase operations.keyvault_private_endpoint(Attributes) FQDN and private IPv4 address of the Key Vault private endpoint, or null whencreate_keyvault_private_endpointis false. (see below for nested schema)knowledge_base_url(String) URL to the Qumulo Terraform provider documentation.nexus_organization(String) Operator-visible label for the Nexus organization this cluster was onboarded to at apply time. Rendered asName (organization ID N)when the provider could resolve the org name, otherwiseorganization ID N. Null whennexus_api_tokenis not configured.
Immutable historical record: this value is stamped at create time and preserved across refreshes via UseStateForUnknown. It does NOT change when an operator later edits nexus_account_id on the provider block. The value is resolved at Configure time and written once — the cluster's onboarded organization is fixed at apply time.
- primary_ips (List of String) Primary IP addresses for each cluster node. Can change during scaling operations.
- resource_group_created (Boolean) Whether the provider created the resource group. Used to determine if the resource group should be deleted on destroy.
- storage_private_endpoints (Attributes Map) FQDN and private IPv4 address of each storage account's private endpoint, keyed by storage account name. Empty when create_storage_private_endpoint is false. On a capacity increase the whole map is unknown at plan time, because Terraform cannot know keys for accounts that do not exist yet, so a downstream for_each over it needs -target or a second apply. (see below for nested schema)
- subscription_id (String) Azure subscription ID resolved from the provider configuration.
Nested Schema for marketplace_image¶
Required:
offer(String) Image offer (e.g., 0001-com-ubuntu-server-jammy, RHEL).publisher(String) Image publisher (e.g., Canonical, RedHat).sku(String) Image SKU (e.g., 22_04-lts, 8-lvm-gen2).version(String) Image version (e.g., latest or specific version).
Nested Schema for naming¶
Optional:
storage_account(String) Template for storage account names. Must contain exactly one {index} or {index:N} placeholder (N = zero-pad width). Example: "mystr{index:02}".vm_name(String) Template for VM names. Must contain exactly one {node_id} placeholder. Example: "myapp-{node_id}".
Nested Schema for node_hooks¶
Optional:
post_run(String) Shell run on each node after qumulo-core is installed. Runs as root; must be idempotent; do not embed secrets.pre_run(String) Shell run on each node after distro detection, before the provider's first network operation (connectivity check, package-cache refresh, package download). Runs as root; must be idempotent; do not embed secrets.
Nested Schema for provisioner_hooks¶
Optional:
post_run(String) Shell run on the provisioner after the cluster is formed and configured, before the provisioner signals success. Runs as root; must be idempotent; do not embed secrets.pre_run(String) Shell run on the provisioner after deployment variables are set and error-handling is armed, before any provider network operation or bucket-access validation. Runs as root; must be idempotent; do not embed secrets (logged under set -x, stored in Terraform state). See the Customizing Cluster Boot guide for the exact shell variables in scope.
Nested Schema for provisioner_marketplace_image¶
Required:
offer(String) Image offer (e.g., 0001-com-ubuntu-server-jammy, RHEL).publisher(String) Image publisher (e.g., Canonical, RedHat).sku(String) Image SKU (e.g., 22_04-lts, 8-lvm-gen2).version(String) Image version (e.g., latest or specific version).
Nested Schema for timeouts¶
Optional:
create(String) A string that can be parsed as a duration consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Defaults to 1h30m0s. Covers resource group/storage/managed-identity provisioning, VMSS bring-up, and qfsd boot. Typical wall-clock is well under the default.delete(String) A string that can be parsed as a duration consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs. Defaults to 30m0s.update(String) A string that can be parsed as a duration consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Defaults to 1h0m0s.
Nested Schema for appconfig_private_endpoint¶
Read-Only:
endpoint_name(String) Name of the private endpoint resourcefqdn(String) Fully qualified domain name the private endpoint answers for.ip_address(String) Private IPv4 address assigned to the endpoint's network interface in the cluster subnet.resource_group(String) Resource group holding the endpointtarget_resource_id(String) ARM ID of the resource the endpoint fronts. This is the object to PATCH when disabling public network access.
Nested Schema for cluster_reference¶
Read-Only:
cluster_api_endpoint(String) The single cluster API target downstream resources dial (equals endpoint_ips[0]). Threat Detection keys VM replacement on this stable field rather than the whole endpoint_ips list, so cluster scaling does not needlessly replace the appliance. With floating IPs configured this is a float, which stays constant across scaling and node replacement.cluster_name(String) Resolved qfsd cluster name (cluster_name, ornamewhen the pair is not used; case preserved). Used by downstream resources for operator-recognizable resource naming.cluster_uuid(String) UUID of the Qumulo cluster.endpoint_ips(List of String) Endpoint IP addresses for client access.resource_group_name(String) Azure resource group containing the Qumulo cluster.subnet_id(String) Subnet resource ID hosting the cluster.uses_floating_ips(Boolean) True when the cluster has floating IPs configured. Downstream resources use this to pick an HA strategy that matches the cluster's actual network: with floats, endpoint_ips[0] is a float and qfsd handles failover at the network layer; without, endpoint_ips[0] is a node primary and clients need their own discovery to reach the other primaries.
Nested Schema for keyvault_private_endpoint¶
Read-Only:
endpoint_name(String) Name of the private endpoint resourcefqdn(String) Fully qualified domain name the private endpoint answers for.ip_address(String) Private IPv4 address assigned to the endpoint's network interface in the cluster subnet.resource_group(String) Resource group holding the endpointtarget_resource_id(String) ARM ID of the resource the endpoint fronts. This is the object to PATCH when disabling public network access.
Nested Schema for storage_private_endpoints¶
Read-Only:
endpoint_name(String) Name of the private endpoint resourcefqdn(String) Fully qualified domain name the private endpoint answers for.ip_address(String) Private IPv4 address assigned to the endpoint's network interface in the cluster subnet.resource_group(String) Resource group holding the endpointtarget_resource_id(String) ARM ID of the resource the endpoint fronts. This is the object to PATCH when disabling public network access.