Skip to content

Authoring IaC templates for Quake AI

Explanation

Coming from another cloud?

▸AWS·Stacks

Stackshigh

  • Quake AI offers Heat (legacy OpenStack orchestration) and recommends OpenTofu for new IaC work; EKS uses declarative console/CLI.
  • EKS Auto Mode automates data plane; Quake AI uses OpenTofu modules for infrastructure provisioning.
  • CloudFormation stacks are managed via AWS-specific REST API (e.g., cloudformation.us-east-1.amazonaws.com) requiring AWS SigV4 auth, while Heat (legacy) uses OpenStack Identity API v3 (keystoneauth) and OpenTofu uses the OpenStack provider with application credentials. Migrators notice different endpoint discovery and auth flows.
  • Stacks support StackSets for cross-region/account deployment; Heat has no equivalent. OpenTofu workspaces offer a different multi-environment pattern.
AWS docs ↗
▸Azure·Resource Manager deployment (deployment)

Azure Resource Manager deployment (deployment)high

  • Authoring format differs: ARM templates are JSON documents for Azure Resource Manager deployments, whereas Quake AI offers Heat (legacy, HOT/YAML format) and recommends OpenTofu (HCL) for new infrastructure automation.
  • Deployment target/scope differs: ARM templates can deploy at multiple scopes (resource group, subscription, management group, tenant) via Azure Resource Manager's management layer, while Heat orchestrates within a single OpenStack project/tenant. OpenTofu can target multiple projects via provider configuration.
  • Change-preview behavior differs: ARM supports a built-in “what-if” style preview of changes via Resource Manager deployments, while OpenTofu provides `tofu plan` for change previews. Heat relies on stack update events (legacy workflow).
  • Resource coverage lifecycle differs: ARM templates support Azure resource types exposed by Azure resource providers; OpenTofu covers OpenStack resource types via the OpenStack provider, and Heat (legacy) supports a narrower set via built-in resource plugins.
Azure docs ↗
▸Google Cloud·Deployment Manager

Deployment Managerhigh

  • Uses YAML configurations with optional Jinja2/Python templates expanded server-side; Quake AI offers Heat (legacy, HOT/YAML) and recommends OpenTofu (HCL) for new work.
  • Resource types named as service.v1.resource (e.g., compute.v1.instance) tied to GCP APIs, vs OpenStack prefixed types like OS::Nova::Server.
  • Single integrated GCP service (no separate API/engine processes); Heat has a multi-service architecture (heat-api, heat-engine) but is legacy. OpenTofu runs client-side with no server component.
  • No additional service fee; bills only for deployed GCP resources, same as OpenStack resources billing via provider.
Google Cloud docs ↗

Authoring IaC templates for Quake AI

You write OpenTofu or Terraform templates against the OpenStack provider the same way you would on any Antelope-era cloud. Quake AI adds a small, fixed catalog of flavors, networks, and volume types, a second AWS provider path for S3-compatible object storage, and Magnum behaviors that differ from generic OpenStack tutorials. This page collects those rules so a new template matches the infrastructure template library and passes CI validation.

If you are new to IaC on the platform, start with Get started with IaC and IaC on Quake AI. If you know OpenStack but not Quake AI branding, read How Quake AI uses OpenStack first.

What is different on Quake AI#

Quake AI runs Antelope (2023.1). The OpenStack provider resource names (openstack_compute_instance_v2, openstack_networking_port_v2, and the rest) are standard. The differences show up in catalog literals (which flavor and network names resolve), auth (application credentials plus separate S3 keys), and platform limits (Magnum trust rules and no managed VPN).

The platform keeps the decision space small on purpose: 26 public flavors in four families, one boot volume type, two shared external networks, and project-scoped roles instead of IAM policies. Templates that hard-code those literals correctly are easier to validate and less likely to fail tofu plan in a new project.

Authentication and providers#

OpenStack provider#

Authenticate with application credentials, not username and password in HCL. Export the variables from the file you generate in Generate app credentials:

bash
export OS_AUTH_URL="https://keystone.rumble.cloud/v3"
export OS_AUTH_TYPE="v3applicationcredential"
export OS_APPLICATION_CREDENTIAL_ID="YOUR_APP_CREDENTIAL_ID"
export OS_APPLICATION_CREDENTIAL_SECRET="YOUR_APP_CREDENTIAL_SECRET"
export OS_REGION_NAME="us-east-1"

Declare an empty provider block and keep secrets out of .tf files:

HCL
terraform {
  required_providers {
    openstack = {
      source  = "terraform-provider-openstack/openstack"
      version = "~> 2.0"
    }
  }
}

provider "openstack" {}

Regions: us-east-1, us-east-2, us-west-1. Parameterize the region in endpoint examples when your template README shows object storage URLs.

AWS provider for object storage#

Object storage buckets use the AWS provider pointed at Quake AI's S3-compatible endpoint. The OpenStack application credential does not satisfy the AWS provider. Mint EC2-compatible credentials with the OpenStack CLI and export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY before tofu plan. The S3 storage template README documents the bootstrap; mirror that pattern in any template that creates buckets.

HCL
provider "aws" {
  region                      = var.s3_region
  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true

  endpoints {
    s3 = var.s3_endpoint
  }
}

Catalog literals#

These values come from the live platform catalog. Wrong defaults produce empty data sources on tofu plan even when tofu validate passes.

LiteralUse in templatesCommon mistake
ImageUbuntu-24.04 (hyphenated Glance name)Ubuntu 24.04 with a space
Flavorsm2a.*, c2a.*, r2a.*, s1a.* onlyFabricated names or other clouds' size IDs
External networkPublicEphemeral or PublicStaticPublicNetwork, ext-net, or external
Volume typeBoot from Cinder volume; platform storage is NVMe (Flash_Premium)Picking a volume type that does not exist in the project
Object endpointhttps://object.{region}.rumble.cloudGlobal s3.* hostnames that do not match the region

Link flavor choice to Compute flavors and capacity planning. Shared vCPU sizes (s1a.*) suit demos; dedicated families (m2a, c2a, r2a) suit production workloads.

External network policy#

Quake AI exposes two shared external networks. Pick the default in variables.tf based on what the template teaches:

ClassDefaultUse when
Throwaway / quickstart-alignedPublicEphemeralSingle-VM demos, labs, or templates that mirror the quickstart ephemeral path
Production / multi-tierPublicStaticPersisted floating IPs, edge reverse proxies, multi-tier stacks, and workloads that must retain an address across instance rebuilds

Readers can override either value in terraform.tfvars. Document which class your template belongs to in the README.

Most compute templates in the library follow the same Neutron shape: private network, router on the external network, security group rules, port with security groups attached by ID, boot-from-volume instance, optional floating IP.

HCL
data "openstack_images_image_v2" "os" {
  name        = var.image_name
  most_recent = true
}

data "openstack_networking_network_v2" "external" {
  name = var.external_network
}

resource "openstack_networking_network_v2" "private" {
  name           = "${var.instance_name}-net"
  admin_state_up = true
}

resource "openstack_networking_subnet_v2" "private" {
  network_id = openstack_networking_network_v2.private.id
  cidr       = var.private_cidr
  ip_version = 4
}

resource "openstack_networking_router_v2" "main" {
  external_network_id = data.openstack_networking_network_v2.external.id
}

resource "openstack_networking_router_interface_v2" "private" {
  router_id = openstack_networking_router_v2.main.id
  subnet_id = openstack_networking_subnet_v2.private.id
}

resource "openstack_networking_secgroup_v2" "app" {
  name = "${var.instance_name}-sg"
}

resource "openstack_networking_port_v2" "app" {
  network_id         = openstack_networking_network_v2.private.id
  security_group_ids = [openstack_networking_secgroup_v2.app.id]

  depends_on = [openstack_networking_router_interface_v2.private]
}

resource "openstack_compute_instance_v2" "app" {
  flavor_name = var.flavor_name
  key_pair    = var.key_name

  block_device {
    uuid                  = data.openstack_images_image_v2.os.id
    source_type           = "image"
    destination_type      = "volume"
    volume_size           = 20
    boot_index            = 0
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.app.id
  }
}

resource "openstack_networking_floatingip_v2" "app" {
  pool = var.external_network
}

resource "openstack_networking_floatingip_associate_v2" "app" {
  floating_ip = openstack_networking_floatingip_v2.app.address
  port_id     = openstack_networking_port_v2.app.id
}

Conventions embedded in that skeleton:

  • Attach security groups to the port with security_group_ids = [....id]. Avoid security_groups = [....name] on the instance; Nova name lookup can match multiple groups after partial applies.
  • Prefix security group and network resource names with var.instance_name or a dedicated prefix variable so repeated applies do not collide with orphaned groups.
  • Use openstack_networking_floatingip_associate_v2, not the deprecated openstack_compute_floatingip_associate_v2 resource.
  • Wait for the router interface before creating ports that need routing (depends_on as shown).

The simple-vm template in iac/templates/simple-vm/ is the canonical reference implementation.

Variables, secrets, and cloud-init#

Standard variables#

Expose a consistent surface so readers can reuse terraform.tfvars patterns across templates:

VariableRequiredTypical default
key_nameYesnone (must exist in the project)
image_nameNoUbuntu-24.04
flavor_name (or tier-specific flavors)Nosize appropriate to the workload
external_networkNoper network policy table above
private_cidrNounused /24 in the project
instance_nameNotemplate slug

Document every variable from variables.tf on the template reference page Parameters table.

SSH keypairs#

Require an existing project keypair via var.key_name. Do not create openstack_compute_keypair_v2 in new templates unless the template explicitly owns key lifecycle and the README states that the private key lands in Terraform state. Prefer the import-key flow from Add an SSH key.

Secrets#

Never commit passwords, API keys, or credential defaults in HCL. Accept secrets through terraform.tfvars (gitignored), CI secret stores, or generated values on the instance via cloud-init.

cloud-init and templatefile#

Use templatefile() for user-data. Do not pass computed resource attributes (for example a floating IP address) into templatefile() variables when that creates a dependency cycle; render those values on the instance or split the bootstrap script.

Platform quirks for template authors#

AreaWhat to encode in templates
Public application entry pointsAttach a floating IP to a self-managed reverse proxy or API gateway instance. Use the Edge Reverse Proxy, API Gateway, or Edge WAF template as a starting point.
Kubernetes (Magnum)Magnum provisions cluster infrastructure; you operate the control plane. Application credentials cannot satisfy Magnum trust delegation; password-scoped sessions are required for openstack coe cluster create. See Kubernetes FAQ. Self-managed Kubernetes on Nova via OpenTofu is the path documented for new clusters in IaC comparison.
HeatCLI validation uses openstack orchestration template validate, not openstack stack template validate.
VPNNo managed VPNaaS. Use the private network + VPN template or your own WireGuard stack.
Volume backupsCinder backup creation is not available; use snapshots or clones for data protection callouts in README prose.
QuotasCLI quota output uses names like public_ip; older docs may say floatingip. Size templates against Resource tiers.
Authorizationadmin, member, and reader at project scope only. Split environments by project, not by IAM-style resource policies.

For the full OpenStack mapping and Console naming, see How Quake AI uses OpenStack.

Validation expectations#

Every template in the library passes tofu validate in CI before it ships. That check confirms the HCL parses and matches the provider schema. It does not mean the template was applied in your project or that your quotas allow the default flavors.

Treat validated OpenTofu templates as a correct starting point. Run tofu plan in your project, adjust flavors and counts for your tier, then apply. For the full validation program, see How the platform validates its content.

See also#

Related content

Pages

deployment

Templates

Was this page helpful?