Azure Government Cloud Example¶
This example demonstrates deploying a Qumulo cluster on Azure Government Cloud with FedRAMP-compliant settings.
Azure Government Cloud requires environment = "usgovernment" in the azure {} provider
block:
provider "qumulo" {
azure {
subscription_id = "your-subscription-id"
environment = "usgovernment" # Required for Azure Government Cloud
}
}
Prerequisites¶
- Azure Government subscription with Contributor permissions
- Enabling
deletion_protectionadditionally requiresMicrosoft.Authorization/locks/*, carried by Owner, User Access Administrator, or a custom role (Contributor alone cannot manage management locks) - Existing virtual network and subnet in a government region
- SSH public key for node access
- Terraform >= 1.0
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.
Usage¶
-
Edit
main.tfwith your values (look for<-- Replacecomments) -
Configure Azure CLI for government cloud:
-
Initialize and deploy:
Government-Specific Settings¶
This example includes:
environment = "usgovernment"in theazure {}provider block- Government regions only (usgovvirginia, usgovtexas, usgoviowa, usgovarizona)
- Multi-zone deployment for compliance
- Mandatory CIDR restrictions (do not leave
allow_cidrsempty) - Compliance-appropriate tagging (Agency, Classification, BackupRetention)
Available Regions¶
usgovvirginia- US Gov Virginiausgovtexas- US Gov Texasusgoviowa- US Gov Iowausgovarizona- US Gov Arizona
Outputs¶
After deployment, you'll get:
cluster_name: The name of your clustercluster_uuid: UUID of the Qumulo clusterendpoint_ips: IP addresses for client connections (floating IPs if configured, otherwise primary IPs)primary_ips: Per-node primary IPs, for per-node accessendpoints: Pre-formatted connection strings for web UI, API, NFS, and SMBdeployment_unique_name: Unique deployment identifier
Full Configuration¶
# Example: Azure Government Cloud Qumulo Cluster
# This example shows deployment to Azure Government Cloud with FedRAMP compliance settings.
# The resource group is automatically created if it doesn't exist.
# Edit the values below directly, then run: terraform init -upgrade && terraform apply
terraform {
required_version = ">= 1.0"
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
}
}
# Qumulo Provider configured for Azure Government Cloud
provider "qumulo" {
azure {
subscription_id = "your-subscription-id" # <-- Replace with your Azure Government subscription ID
environment = "usgovernment" # Required for Azure Government Cloud
}
}
variable "ssh_public_key_path" {
description = "Path to SSH public key file for cluster node access"
type = string
default = "~/.ssh/id_rsa.pub"
}
# Qumulo cluster on Azure Government Cloud
# Note: The resource group is automatically created if it doesn't exist.
# If it exists, the provider will use it (location must match).
resource "qumulo_filesystem_azure" "cluster" {
provider = qumulo
# =============================================================================
# All attributes (alphabetical order)
# Uncomment any attribute to use it. Required attributes are not commented.
# =============================================================================
# Admin password for cluster access.
# 8-128 characters, must include 3+ of: uppercase, lowercase, digit, special character.
# Immutable after creation - use Qumulo UI or CLI to change.
# Note: Minimum 12 characters recommended for government compliance.
admin_password = "YourSecureGovPassword123!"
# CIDR blocks allowed to access the cluster.
# Empty list means no IP-based restrictions (use with caution).
# IMPORTANT: Required for government compliance - do not leave empty.
allow_cidrs = ["10.0.0.0/8"]
# Availability zones for node distribution.
# Controls both node placement and VM disk storage type:
# - With zones: Uses PremiumV2_LRS disks (better price/performance).
# - Without zones: Uses Premium_LRS disks (required for zoneless regions).
# Omit for single-zone or zoneless regions (e.g., northcentralus).
# Example: ["1", "2", "3"] for multi-AZ high availability.
availability_zones = ["1", "2", "3"]
# # User-assigned managed identity for cluster nodes.
# # When provided, RBAC roles must be pre-configured (not auto-created).
# # Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{name}
# cluster_node_identity_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.ManagedIdentity/userAssignedIdentities/xxx"
# Cluster storage product type.
# HOT: Optimized for frequently accessed data (default).
# COLD: Optimized for archival/infrequently accessed data.
# Immutable after creation.
cluster_product_type = "HOT"
# Qumulo software version (pin to a tested version for GovCloud compliance).
# Immutable after creation - use Qumulo UI or CLI to upgrade.
cluster_version = "7.5.0" # Replace with your tested/approved version
# # Custom managed image ID for cluster nodes.
# # Use for hardened or pre-configured VMs.
# # WARNING: Changes trigger cluster replacement!
# # Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Compute/images/{name}
# # Create private endpoints in the cluster subnet.
# # Set the matching private_link_appconfig_dns_zone_id,
# # private_link_keyvault_dns_zone_id, or private_link_storage_dns_zone_id to also
# # register them in an Azure Private DNS zone. Without a zone, read the computed
# # appconfig_private_endpoint / keyvault_private_endpoint /
# # storage_private_endpoints outputs and create the records yourself.
# # create_keyvault_private_endpoint conflicts with key_vault_id.
# # Each endpoint carries a per-hour Azure cost.
# create_appconfig_private_endpoint = false
# create_keyvault_private_endpoint = false
# create_storage_private_endpoint = false
# custom_image_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/images/xxx"
# # Disable App Configuration public network access.
# # When true, requires private_link_appconfig_dns_zone_id.
# disable_appconfig_public_network_access = false
# # Disable Key Vault public network access.
# # When true, requires private_link_keyvault_dns_zone_id.
# disable_keyvault_public_network_access = false
# # Floating IP addresses for client access.
# # Use for DNS round-robin or custom load balancing.
# # When set, endpoint_ips output returns these instead of node IPs.
# # Number of floating IPs for client access. The provider picks the
# # addresses from the cluster subnet and reports them in floating_ips.
# floating_ip_count = 3
# # Customer-managed Key Vault resource ID.
# # When provided, the provider uses this vault instead of creating one.
# # Conflicts with disable_keyvault_public_network_access and private_link_keyvault_dns_zone_id.
# # Immutable after creation. You own vault lifecycle, network, and access policies.
# # The vault must permit access from the cluster subnet - the nodes read their
# # storage SAS tokens from it. See "Customer-Managed Key Vault" in azure-production.md.
# # Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/{name}
# key_vault_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.KeyVault/vaults/xxx"
# Azure region for deployment.
# Azure Government regions: usgovvirginia, usgovtexas, usgoviowa, usgovarizona
location = "usgovvirginia" # <-- Azure Government region
# # Azure Marketplace image for cluster nodes.
# # Alternative to custom_image_id for standard enterprise images.
# # WARNING: Changes trigger cluster replacement!
# marketplace_image = [{
# publisher = "Canonical"
# offer = "0001-com-ubuntu-server-jammy"
# sku = "22_04-lts-gen2"
# version = "latest"
# }]
# qfsd cluster name, shown in the Qumulo UI (2-15 chars, case preserved).
cluster_name = "qumulogov"
# Prefix for the Azure resources this cluster creates (2-15 lowercase chars).
deployment_name = "qumulogov"
# # Custom naming templates for Azure resources.
# # vm_name must contain exactly one {node_id} placeholder.
# # storage_account must contain exactly one {index} or {index:N} placeholder.
# # {index} is the unpadded index. {index:N} zero-pads the index to width N, so
# # {index:2} yields "01", "02", ... ({index:02} is equivalent -- the leading 0 is redundant).
# # Changing either forces replacement of the affected resource.
# naming = [{
# vm_name = "myapp-{node_id}"
# storage_account = "myappstor{index:02}"
# }]
# # Network management mode.
# # "host_managed" (default) for clusters created by this provider.
# # "qumulo_managed" only for clusters originally created by azure-terraform-cnq.
# # Immutable after creation. Mixing modes across nodes is prohibited.
# networking_mode = "host_managed"
# # Qumulo Nexus registration key for remote support.
# # Obtain from https://nexus.qumulo.com/user/registration-key
# # Only applied during initial cluster creation.
# nexus_registration_key = "your-nexus-key"
# Number of nodes in the cluster.
# Valid values: 1 (single node), or 3-24 (4 nodes: single-zone only).
# Note: 2 is not a valid node count.
node_count = 5
# # Enable ICMP ingress (ping) in network security group.
# # Useful for network diagnostics.
# nsg_allow_ingress_icmp = false
# # Resource group containing persistent storage accounts and KeyVault.
# # Required when migrating from the legacy azure-terraform-cnq module, where persistent
# # storage lived in a separate resource group. Defaults to resource_group_name when omitted.
# persistent_storage_resource_group = "rg-qumulo-persistent"
# # Private DNS zone ID for App Configuration private endpoint.
# # Required when disable_appconfig_public_network_access is true.
# # Requires create_appconfig_private_endpoint = true.
# # Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/privateDnsZones/privatelink.azconfig.azure.us
# private_link_appconfig_dns_zone_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/privateDnsZones/privatelink.azconfig.azure.us"
# # Private DNS zone ID for Key Vault private endpoint.
# # Required when disable_keyvault_public_network_access is true.
# # Requires create_keyvault_private_endpoint = true.
# # Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.usgovcloudapi.net
# private_link_keyvault_dns_zone_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.usgovcloudapi.net"
# # Private DNS zone ID for the storage private endpoints.
# # Requires create_storage_private_endpoint = true.
# # Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.usgovcloudapi.net
# private_link_storage_dns_zone_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.usgovcloudapi.net"
# # Custom managed image ID for provisioner VM.
# # Does NOT trigger cluster replacement when changed.
# provisioner_custom_image_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/images/xxx"
# # User-assigned managed identity for provisioner VM.
# # When provided, RBAC roles must be pre-configured.
# provisioner_identity_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.ManagedIdentity/userAssignedIdentities/xxx"
# # Azure Marketplace image for provisioner VM.
# # Does NOT trigger cluster replacement when changed.
# provisioner_marketplace_image = [{
# publisher = "Canonical"
# offer = "0001-com-ubuntu-server-jammy"
# sku = "22_04-lts-gen2"
# version = "latest"
# }]
# # VM size for the provisioner instance.
# # Used during deployment operations only.
# provisioner_vm_type = "Standard_B2s"
# Azure resource group name.
# The resource group is automatically created if it doesn't exist.
# If it exists, the provider will use it (location must match).
resource_group_name = "rg-qumulo-gov" # <-- Name your resource group
# Soft capacity limit in TB (50-10000).
# Can be increased to add storage, but cannot be decreased.
soft_capacity_limit_tb = 1000
# SSH public key for cluster node access.
# Point to your public key file (e.g., ~/.ssh/id_rsa.pub).
ssh_public_key = file(var.ssh_public_key_path)
# Azure storage replication type for storage accounts only (does not affect VM disks).
# LRS: Locally redundant (3 copies in single datacenter).
# ZRS: Zone redundant (3 copies across availability zones) - RECOMMENDED for multi-AZ clusters.
# Note: VM disk redundancy is controlled by availability_zones (see above).
# Immutable after creation.
storage_replication_type = "ZRS"
# Full Azure resource ID of the subnet for cluster deployment.
# The subnet must already exist before deploying the cluster.
# Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet}
subnet_id = "/subscriptions/your-subscription-id/resourceGroups/rg-network/providers/Microsoft.Network/virtualNetworks/vnet-main/subnets/subnet-qumulo"
# Tags to apply to all Azure resources (including the resource group if created).
# Government-compliant tags for compliance tracking.
tags = {
Environment = "Production"
Agency = "Your-Agency-Name"
Classification = "CUI"
ComplianceFramework = "FedRAMP"
ManagedBy = "Terraform"
BackupRetention = "7Years"
}
# Azure VM size for cluster nodes.
# Only L-series storage-optimized VMs are supported.
# Examples: Standard_L8s_v3, Standard_L16s_v3, Standard_L32s_v3
vm_type = "Standard_L8s_v3"
deletion_protection = true # recommended: guard the cluster's VMs and storage accounts
timeouts {
create = "90m"
delete = "30m"
}
}
output "cluster_name" {
description = "Name of the Qumulo cluster"
value = qumulo_filesystem_azure.cluster.cluster_name
}
output "cluster_uuid" {
description = "UUID of the Qumulo cluster"
value = qumulo_filesystem_azure.cluster.cluster_uuid
}
output "deployment_unique_name" {
description = "Unique deployment identifier"
value = qumulo_filesystem_azure.cluster.deployment_unique_name
}
output "endpoint_ips" {
description = "Client-facing IPs. Floating IPs if configured, otherwise primary IPs."
value = qumulo_filesystem_azure.cluster.endpoint_ips
}
output "primary_ips" {
description = "Per-node primary IPs. Use these directly when no floating IPs are configured, or for per-node access."
value = qumulo_filesystem_azure.cluster.primary_ips
}
output "endpoints" {
description = "Connection endpoints for various protocols"
value = {
web_ui = "https://${try(qumulo_filesystem_azure.cluster.endpoint_ips[0], "pending")}"
api = "https://${try(qumulo_filesystem_azure.cluster.endpoint_ips[0], "pending")}:8000"
nfs = "${try(qumulo_filesystem_azure.cluster.endpoint_ips[0], "pending")}:/"
smb = "\\\\${try(qumulo_filesystem_azure.cluster.endpoint_ips[0], "pending")}\\share"
}
}