qumulo_filesystem_aws (Resource)¶
Creates and manages a Qumulo filesystem deployment on AWS.
VPC Prerequisites
Your VPC must meet two requirements before deploying a cluster:
- S3 gateway VPC endpoint -- Attach an S3 gateway endpoint to the route table serving the subnet. The provider does not create this (cross-account VPCs may lack permission), and deployment will fail without it.
- Outbound internet access -- Cluster nodes and the provisioner instance must reach the public internet for image downloads and cluster registration. Use a NAT Gateway in a private subnet (recommended). An Internet Gateway in a public subnet also works but reduces network isolation.
Deploying into a VPC owned by another AWS account?
For RAM-shared subnets, see the AWS Cross-Account VPC guide for the additional setup and the cluster_security_group_id / provisioner_security_group_id Bring-your-own pattern.
Supports terraform import via the format <region>/<deployment_unique_name>. See the import guide for the customer-declared-attribute checklist, required IAM permissions, and worked examples.
Example Usage¶
terraform {
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "qumulo" {
aws {}
}
# Upload a local public key file as an EC2 key pair, then reference it
# from the cluster via ec2_key_pair. Swap in any path you prefer.
resource "aws_key_pair" "cluster" {
key_name = "mycluster-key"
public_key = file("~/.ssh/id_rsa.pub")
}
resource "qumulo_filesystem_aws" "cluster" {
cluster_name = "mycluster"
deployment_name = "mycluster"
region = "us-east-1"
node_count = 5
instance_type = "m6idn.2xlarge"
subnet_ids = [var.subnet_id]
admin_password = var.admin_password
cluster_product_type = "HOT"
allow_cidrs = ["0.0.0.0/0"]
ec2_key_pair = aws_key_pair.cluster.key_name
deletion_protection = true # recommended: guard the cluster's EC2 instances and S3 buckets
# Optional: S3 storage class backing the cluster's persistent storage
# (HOT: STANDARD or INTELLIGENT_TIERING; COLD: STANDARD_IA or GLACIER_IR).
# storage_class = "STANDARD"
}
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 (8-128 characters).cluster_product_type(String) Qumulo cluster product type (immutable after creation). HOT or COLD.instance_type(String) EC2 instance type for cluster nodes.node_count(Number) Number of nodes in the cluster (1, or 3-24; 2 is not supported, and 4 requires a single-AZ deployment).region(String) AWS region for deployment (e.g., us-east-1).subnet_ids(List of String) List of subnet IDs for cluster nodes. Use 1 subnet for single-AZ or 3+ subnets for multi-AZ (each in a distinct availability zone). 2 subnets is not supported because it cannot form a majority quorum. Changing this list (including single-AZ ↔ multi-AZ) triggers an in-place cluster replacement (node-by-node swap) that preserves cluster identity and data; the new subnets must be in the same VPC. Node IPs change during the swap.
Optional¶
NOTE: Write-only arguments are supported in Terraform 1.11 and later.
additional_security_group_ids(Set of String) Additional security group IDs to attach to cluster nodes.allow_cidrs(Set of String) CIDR blocks allowed to access the cluster. Required unless Bring-your-own security groups are configured (cluster_security_group_id + provisioner_security_group_id), in which case ingress is owned by the user and this attribute must be omitted.ami_id(String) AMI ID for cluster nodes. If omitted, the latest Ubuntu 24.04 AMI from Canonical is used. The resolved AMI is persisted in state and reused on subsequent operations until the user changes it explicitly. Supports Ubuntu and RHEL 8, 9, and 10 AMIs.audit_log_group_name(String) CloudWatch log group for audit events. Defaults to/qumulo/<deployment_unique_name>-audit-log. Set this to send audit events to a log group you manage; the provider creates it only if it is missing and never changes its retention, encryption, or tags afterward.audit_logging(Boolean) Sends Qumulo audit events to CloudWatch Logs. Whentrue, the provider creates the log group if it does not already exist and configures the cluster to write to it, reasserting that configuration on every apply. Changing this attribute tofalseturns audit logging off on the cluster. While it staysfalse, audit configuration made outside Terraform (for example withqqor thequmulo_audit_cloudwatchresource) is left alone. The log group is never deleted, so audit history survivesterraform destroy. Defaults tofalse.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_iam_role_arn(String) Bring-your-own IAM role ARN for cluster nodes. When set, the provider creates, modifies, and deletes no IAM resources for the cluster role: you own the role, its policies, and its instance profile (the role must be in exactly one instance profile). The role's S3 policy must use the wildcard bucket pattern documented in the Bring Your Own IAM Roles guide, and the deploying credentials need iam:PassRole on this role. Changing this value forces cluster replacement.cluster_name(String) Name of the Qumulo cluster as it appears in qfsd and the Qumulo UI (2-15 characters: letters, digits, and interior hyphens; case preserved). When omitted, defaults toname. Not refreshed from the running cluster. Changing it forces a new cluster. Requiresdeployment_name.cluster_security_group_id(String) Bring-your-own security group ID for cluster nodes. When set, the provider will not create or modify a cluster security group; you must pre-create it in the VPC owner account with the rules documented in the AWS Cross-Account VPC guide. Required together with provisioner_security_group_id. Required for RAM-shared subnets where the consumer account cannot create security groups in the owner's VPC.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.deletion_protection(Boolean) Protects the cluster's EC2 instances and S3 buckets from deletion — includingterraform destroy, the AWS console, and the AWS CLI. 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. Defaults tofalse.deployment_name(String) Seed for every AWS resource name (S3 buckets, IAM roles, security groups, EC2 Name tags) (2-36 characters: letters, digits, and interior hyphens). Derived AWS 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.ec2_key_pair(String) EC2 key pair name for SSH access to cluster nodes.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'. Has no effect while subnet_ids names more than one subnet: floating IPs cannot coexist with multiple availability zones.floating_ip_count_ipv6(Number) Number of IPv6 floating IPs to assign to the cluster, as IPv6 addresses on the node ENIs. Must be 0 (disabled) or between 3 and 100. Requires networking_mode 'host_managed', cluster_version 7.9.2.1 or later, and an IPv6-enabled (dualstack) subnet. Has no effect while subnet_ids names more than one subnet: floating IPs cannot coexist with multiple availability zones. Nodes keep their IPv4 primary addresses for internode and management traffic; only the floating pool is IPv6. Cannot be combined with floating_ip_count: Qumulo Core does not yet support simultaneous IPv4 and IPv6 floating IPs on AWS.kms_key_id(String) KMS key ID for encrypting cluster data (immutable after creation).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: set this OR that pair. Derived AWS resource names are lowercased.networking_mode(String) Network management mode for cluster nodes. Use 'host_managed' (new clusters default to this) for cloud-driven NIC/IP networking, or 'qumulo_managed' for cluster-driven networking. 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)permissions_boundary_arn(String) IAM permissions boundary ARN for cluster roles.provisioner_ami_id(String) AMI ID for the provisioner instance. If omitted, the default Qumulo provisioner AMI (Ubuntu 24.04) is used. Supports Ubuntu and RHEL 8, 9, and 10 AMIs.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_iam_role_arn(String) Bring-your-own IAM role ARN for the provisioner instance. When set, the provider creates, modifies, and deletes no IAM resources for the provisioner role. See cluster_iam_role_arn and the Bring Your Own IAM Roles guide. Changing this value forces cluster replacement.provisioner_instance_type(String) EC2 instance type for the provisioner VM.provisioner_security_group_id(String) Bring-your-own security group ID for the provisioner instance. Required together with cluster_security_group_id. See cluster_security_group_id.s3_log_bucket_name(String) Existing S3 bucket that receives server access logs for the cluster's persistent storage buckets. Leave unset to disable access logging. The bucket must already exist, live in the same region as the cluster, and grant the S3 log delivery service write access. Immutable after creation.s3_log_bucket_prefix(String) Key prefix for delivered S3 access logs (defaults to "log/"). Only used when s3_log_bucket_name is set. Immutable after creation.soft_capacity_limit_tb(Number) Soft capacity limit in TB (50TB to 50000TB). Can be increased but cannot be decreased. Increases are limited to less than 5000TB per apply; larger changes must be applied in steps.storage_class(String) S3 storage class backing the cluster's persistent storage (immutable after creation). HOT clusters support STANDARD and INTELLIGENT_TIERING (default). COLD clusters support STANDARD_IA and GLACIER_IR (default).tags(Map of String) Tags to apply to all AWS resources created for this cluster.timeouts(Block, Optional) (see below for nested schema)vpc_id(String) VPC ID for the cluster deployment.
Read-Only¶
account_id(String) AWS account ID where the cluster is deployed.cluster_reference(Attributes) Aggregated cluster identity for downstream resources. Equivalent to{ cluster_api_endpoint, cluster_name, cluster_uuid, endpoint_ips, region, subnet_ids, uses_floating_ips, vpc_cidr, vpc_id }— pass directly toqumulo_threat_detection_aws.cluster_referenceso the customer can wire one reference instead of nine.subnet_idsmirrors the resource's ownsubnet_idsattribute (a list, since AWS clusters can span multiple subnets across availability zones). (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. Can change during scaling operations.floating_ips(List of String) Floating IP addresses assigned to the cluster. Empty when floating_ip_count is 0. Can change during scaling or reconciliation.id(String) Unique identifier for the resource.internal_state(String) Internal state for tracking multi-phase operations.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.
- vpc_cidr (String) VPC CIDR block, fetched from AWS during cluster creation. Exposed via cluster_reference so the Threat Detection resource can derive its security group rules without operator input.
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 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. AWS Hot CNQ provisioning typically takes 60–80 minutes (S3 bucket creation, IAM propagation, EBS-backed qfsd boot).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 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.region(String) AWS region the cluster is deployed in. Mirrors the resource'sregionattribute. Used by downstream resources so the operator does not have to retype the region.subnet_ids(List of String) Subnet IDs hosting the cluster nodes. Mirrors the resource's subnet_ids attribute.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.vpc_cidr(String) Primary IPv4 CIDR block of the cluster's VPC. Resolved once at Create via DescribeVpcs. Used by downstream resources (e.g. Threat Detection) as the inbound allow source on their security group so cluster nodes (and only cluster nodes) can reach the appliance. Empty if DescribeVpcs was unavailable; downstream resources surface a clearer error in that case when they actually need the value.vpc_id(String) VPC ID the cluster is deployed in. Mirrors the resource'svpc_idattribute.