# How to migrate from AWS CloudFormation to OpenTofu on Quake AI

Source: https://docs.quake.ai/docs/automation/migration/from-aws-cloudformation
Markdown: https://docs.quake.ai/docs/automation/migration/from-aws-cloudformation.md

---

# How to migrate from AWS CloudFormation to OpenTofu on Quake AI

If your infrastructure runs on AWS and is defined in CloudFormation, moving to Quake AI means rewriting those stack definitions in OpenTofu HCL. This guide maps common CloudFormation resource types to their Quake AI OpenTofu equivalents and outlines a practical migration workflow.

## Conceptual mapping

CloudFormation and OpenTofu serve the same purpose (declarative infrastructure definition) but differ in execution:

| Concept | CloudFormation | OpenTofu on Quake AI |
|---|---|---|
| Template format | JSON or YAML | HCL (.tf files) |
| State management | Server-side (AWS manages) | Client-side state file (local or S3 remote) |
| Provider model | AWS-only (with some Custom Resources) | Multi-provider (OpenStack + AWS S3 + DNS) |
| Change preview | Change Sets | `tofu plan` |
| Execution | AWS service | Local CLI or CI runner |
| Rollback | Automatic on failure | Manual (restore state or re-apply) |

## Resource equivalents

| AWS CloudFormation Resource | Quake AI OpenTofu Resource | Notes |
|---|---|---|
| `AWS::EC2::Instance` | `openstack_compute_instance_v2` | Map AMIs to Quake AI images |
| `AWS::EC2::VPC` | `openstack_networking_network_v2` + `openstack_networking_subnet_v2` | Quake AI uses flat networking; no NAT gateway equivalent |
| `AWS::EC2::SecurityGroup` | `openstack_networking_secgroup_v2` + rules | Same concept, different API |
| `AWS::EC2::EIP` | `openstack_networking_floatingip_v2` | Associate with `openstack_compute_floatingip_associate_v2` |
| `AWS::ElasticLoadBalancingV2::LoadBalancer` | Self-managed reverse proxy or API gateway instance with a floating IP | Translate listeners and target groups into proxy routes and private backend addresses |
| `AWS::RDS::DBInstance` | `openstack_compute_instance_v2` + cloud-init | No managed DB yet; use [Self-Managed PostgreSQL template](/resources/iac-templates/self-managed-postgres) |
| `AWS::S3::Bucket` | `aws_s3_bucket` (with Quake AI S3 endpoint) | See [S3 Storage with ACLs template](/resources/iac-templates/s3-storage-acl) |
| `AWS::EC2::Volume` | `openstack_blockstorage_volume_v3` | NVMe block storage |
| `AWS::CloudFormation::Stack` (nested) | OpenTofu modules | Use `module` blocks for composition |

## Migration workflow

### 1. Audit your CloudFormation stacks

Export your current stack resources:

```bash
aws cloudformation describe-stack-resources \
  --stack-name YOUR_STACK_NAME \
  --query 'StackResources[].{Type:ResourceType,Logical:LogicalResourceId,Physical:PhysicalResourceId}' \
  --output table
```

Document each resource type and its configuration. Pay attention to:
- Instance types and AMIs (map to Quake AI flavors and images)
- VPC CIDR ranges and subnet layout
- Security group rules
- Load balancer listeners and target groups
- S3 bucket policies and lifecycle rules

### 2. Map to Quake AI resources

For each CloudFormation resource, identify the OpenTofu equivalent from the table above. Start with the Quake AI [template library](/resources/iac-templates); many common patterns are already authored:

- EC2 instance with EIP → [Simple VM template](/resources/iac-templates/simple-vm)
- VPC + subnets + ALB → [Edge Reverse Proxy template](/resources/iac-templates/edge-reverse-proxy) or [API Gateway template](/resources/iac-templates/api-gateway)
- Multi-tier app (web + app + DB) → [Three-Tier Application template](/resources/iac-templates/three-tier-app)
- RDS PostgreSQL → [Self-Managed PostgreSQL template](/resources/iac-templates/self-managed-postgres)

### 3. Write OpenTofu configuration

Start with a single resource (typically a compute instance) and validate the provider setup:

```hcl
terraform {
  required_version = ">= 1.6.0"

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

provider "openstack" {}

data "openstack_images_image_v2" "ubuntu" {
  name        = "Ubuntu-24.04"
  most_recent = true
}

resource "openstack_compute_instance_v2" "web" {
  name        = "web-server"
  flavor_name = "s1a.medium"

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

  network {
    name = "PublicStatic"
  }
}
```



Every Quake AI flavor reports zero ephemeral disk (`disk=0`), so each `openstack_compute_instance_v2` needs a `block_device` block that boots from a Cinder volume. A bare `image_name` without `block_device` fails at apply with `Only volume-backed servers are allowed for flavors with zero disk (HTTP 403)`. See the [Compute FAQ](/docs/compute/faq) and the [Simple VM template](/resources/iac-templates/simple-vm) for the full network topology.



Run `tofu plan` to verify the configuration is valid, then iterate to add the rest of your resources.

### 4. Set up remote state

Before applying, configure [remote state with Quake AI S3](/docs/automation/how-to/state-management) so your team can collaborate on the infrastructure.

### 5. Apply incrementally

Deploy resources in dependency order:
1. Networking (networks, subnets, security groups)
2. Storage (block volumes, S3 buckets)
3. Compute (instances, cloud-init)
4. Edge proxy or API gateway and DNS

### Key differences from AWS

- **No managed databases.** Use the [Self-Managed PostgreSQL template](/resources/iac-templates/self-managed-postgres), or pair Quake AI with the managed database service your architecture uses externally.
- **Network translation.** Instances use floating IPs or direct network attachment for internet access. Put a self-managed [edge reverse proxy](/resources/iac-templates/edge-reverse-proxy) or [API gateway](/resources/iac-templates/api-gateway) on one floating IP when several private backends need a shared public entry point.
- **No IAM roles.** Authentication uses OpenStack Keystone credentials via environment variables.
- **Fixed monthly pricing.** No per-hour billing surprises; plan capacity based on monthly cost rather than usage estimates.

## See also

- [Migration Explorer](/resources/migration): interactive service comparison across cloud providers
- [IaC on Quake AI](/docs/automation/concepts/iac-comparison)
- [Infrastructure Templates](/resources/iac-templates)
- [How to get started with Infrastructure as Code on Quake AI](/docs/automation/how-to/getting-started-iac)
