# How to migrate from Linode (Akamai) to Quake AI with OpenTofu

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

---

# How to migrate from Linode (Akamai) to Quake AI with OpenTofu

Linode (now branded **Akamai Cloud Computing**) and Quake AI attract similar audiences: cost-conscious engineers who self-manage infrastructure. If you already use Terraform or OpenTofu with the [linode provider](https://registry.terraform.io/providers/linode/linode/latest), migrating to Quake AI is a provider swap with resource remapping.

## Conceptual mapping

Both platforms offer similar primitives, but the APIs and resource names differ:

| Concept | Linode (linode provider) | Quake AI (OpenStack) |
|---|---|---|
| Provider | `linode/linode` | `terraform-provider-openstack/openstack` |
| Compute Instance | `linode_instance` | `openstack_compute_instance_v2` |
| Plan | `g6-nanode-1`, `g6-standard-2`, `g6-dedicated-4`, etc. | `s1a.small`, `m2a.large`, `c2a.xlarge`, `r2a.large`, etc. |
| SSH key | `linode_sshkey` | `openstack_compute_keypair_v2` |
| Reserved IP / Floating IP | (Reserved IPs managed in Cloud Manager) | `openstack_networking_floatingip_v2` |
| Cloud Firewall | `linode_firewall` | `openstack_networking_secgroup_v2` + rules |
| Block Storage Volume | `linode_volume` | `openstack_blockstorage_volume_v3` |
| VPC | `linode_vpc` + `linode_vpc_subnet` | `openstack_networking_network_v2` + `openstack_networking_subnet_v2` |
| NodeBalancer | `linode_nodebalancer` + `linode_nodebalancer_config` + `linode_nodebalancer_node` | Self-managed reverse proxy or API gateway instance with a floating IP |
| Object Storage bucket | `linode_object_storage_bucket` | `openstack_objectstorage_container_v1` (Swift) or S3 client via `aws_s3_bucket` against the Quake AI endpoint |
| LKE Cluster | `linode_lke_cluster` | `openstack_containerinfra_cluster_v1` (Magnum) is the primary equivalent; self-managed RKE2 or k3s on Nova is the alternative. See [migrate from LKE](/docs/kubernetes/migration/migrate-from-lke). |
| Image | Linode public images (`linode/ubuntu24.04`, etc.) | Quake AI images (`Ubuntu-24.04`, etc.) |

## Resource translation examples

### Compute Instance

Linode:

```hcl
resource "linode_instance" "web" {
  label  = "web-1"
  region = "us-east"
  type   = "g6-standard-2"
  image  = "linode/ubuntu24.04"

  authorized_keys = [linode_sshkey.main.ssh_key]
}
```

Quake AI:

```hcl
resource "openstack_compute_instance_v2" "web" {
  name        = "web-1"
  image_name  = "Ubuntu-24.04"
  flavor_name = "m2a.large"

  key_pair = openstack_compute_keypair_v2.main.name

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

### Cloud Firewall to security group

Linode:

```hcl
resource "linode_firewall" "web" {
  label = "web-firewall"

  inbound_policy  = "DROP"
  outbound_policy = "ACCEPT"

  inbound {
    label    = "allow-http"
    action   = "ACCEPT"
    protocol = "TCP"
    ports    = "80"
    ipv4     = ["0.0.0.0/0"]
  }

  inbound {
    label    = "allow-https"
    action   = "ACCEPT"
    protocol = "TCP"
    ports    = "443"
    ipv4     = ["0.0.0.0/0"]
  }

  linodes = [linode_instance.web.id]
}
```

Quake AI:

```hcl
resource "openstack_networking_secgroup_v2" "web" {
  name = "web-secgroup"
}

resource "openstack_networking_secgroup_rule_v2" "http" {
  security_group_id = openstack_networking_secgroup_v2.web.id
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 80
  port_range_max    = 80
  remote_ip_prefix  = "0.0.0.0/0"
}

resource "openstack_networking_secgroup_rule_v2" "https" {
  security_group_id = openstack_networking_secgroup_v2.web.id
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 443
  port_range_max    = 443
  remote_ip_prefix  = "0.0.0.0/0"
}
```

Apply the security group to instances via the `security_groups` argument on `openstack_compute_instance_v2`.

### Block Storage Volume

Linode:

```hcl
resource "linode_volume" "data" {
  label  = "data-vol"
  region = "us-east"
  size   = 50
}
```

Quake AI:

```hcl
resource "openstack_blockstorage_volume_v3" "data" {
  name = "data-vol"
  size = 50
}
```

Volume attachment and formatting happen through `openstack_compute_volume_attach_v2` and cloud-init, respectively.

### VPC

Linode bundles a VPC and a single subnet through two resources; Quake AI exposes network and subnet independently.

Linode:

```hcl
resource "linode_vpc" "main" {
  label  = "main-vpc"
  region = "us-east"
}

resource "linode_vpc_subnet" "private" {
  vpc_id = linode_vpc.main.id
  label  = "private"
  ipv4   = "10.0.0.0/24"
}
```

Quake AI:

```hcl
resource "openstack_networking_network_v2" "main" {
  name = "main-network"
}

resource "openstack_networking_subnet_v2" "private" {
  name       = "private"
  network_id = openstack_networking_network_v2.main.id
  cidr       = "10.0.0.0/24"
  ip_version = 4
}
```

### NodeBalancer to a self-managed edge proxy

Replace a NodeBalancer with a Caddy, Nginx, HAProxy, or API gateway instance on a private network. Attach one floating IP to the edge instance, terminate TLS there, and route requests to backend instance ports over private addresses. The [Edge Reverse Proxy template](/resources/iac-templates/edge-reverse-proxy) provides a Caddy-based starting point, while the [API Gateway template](/resources/iac-templates/api-gateway) adds API routing and policy controls.

Linode:

```hcl
resource "linode_nodebalancer" "web" {
  label  = "web-lb"
  region = "us-east"
}

resource "linode_nodebalancer_config" "http" {
  nodebalancer_id = linode_nodebalancer.web.id
  port            = 80
  protocol        = "tcp"
  algorithm       = "roundrobin"
}

resource "linode_nodebalancer_node" "web1" {
  nodebalancer_id = linode_nodebalancer.web.id
  config_id       = linode_nodebalancer_config.http.id
  label           = "web-1"
  address         = "${linode_instance.web.private_ip_address}:80"
  weight          = 100
}
```

Model the replacement in OpenTofu as:

- One `openstack_compute_instance_v2` edge instance running the proxy.
- One `openstack_networking_port_v2` on the application subnet.
- One `openstack_networking_floatingip_v2` associated with the edge port.
- Security group rules for ports 80 and 443 on the edge, with backend ports restricted to the edge instance's private address.
- Proxy configuration that lists each backend private address and its health-check path.

## Migration workflow

1. **Export your Linode state.** Run `tofu show` (or `terraform show`) to document current resources.
2. **Map Linode plans to Quake AI flavors.** Compare vCPU/RAM specs between Linode plan SKUs and Quake AI flavors. See [migrate from Linode (compute)](/docs/compute/migration/migrate-from-linode) for a per-family mapping.
3. **Rewrite the provider block.** Replace `linode/linode` with `terraform-provider-openstack/openstack`. Authenticate via standard `OS_*` environment variables (or `cloud:` blocks).
4. **Translate resources.** Start with a single instance and security group, then add networking and storage.
5. **Set up data migration.** For volumes, use `rsync` or `scp` to copy data between instances. For S3-compatible storage, use `rclone`. See [migrate from Linode Object Storage](/docs/object/migration/migrate-from-linode).
6. **Test with `tofu plan`.** Validate the configuration before applying.
7. **Apply and verify.** Deploy on Quake AI and confirm services are reachable.

## Key differences from Linode

- **Authentication.** The Linode provider takes a single API token. The OpenStack provider uses Keystone with username, password, project, and domain set via environment variables (or [application credentials](/docs/identity/how-to/create-application-credential), which are the recommended path for CI).
- **Networking model.** Linode auto-assigns a public IPv4 to every Linode. Quake AI uses Floating IPs that you allocate explicitly and associate with a port.
- **Firewall vs security group.** Linode Cloud Firewalls are standalone resources attached to a Linode or NodeBalancer. Quake AI security groups attach to ports/instances with individual rules as separate resources.
- **Object storage.** Both Linode and Quake AI expose S3-compatible object storage; for IaC, see the [S3 Storage with ACLs template](/resources/iac-templates/s3-storage-acl).
- **Managed Kubernetes.** Map `linode_lke_cluster` to `openstack_containerinfra_cluster_v1` (Magnum) for the closest LKE-like experience; the platform provides the cluster template, control plane, and load-balanced API endpoint. If you need a custom CNI, kubelet flags, CRI, or a Kubernetes version outside the template catalog, provision Nova instances with OpenTofu and bootstrap with `kubeadm`, `k3s`, or `rke2` instead. See [migrate from LKE](/docs/kubernetes/migration/migrate-from-lke).
- **Pricing model.** Linode bills hourly with a monthly cap; Quake AI uses fixed monthly plans tied to a resource tier, with a small list of per-resource add-ons. See the [pricing model](/docs/platform#pricing). Compare plan and add-on costs in the [Akamai pricing page](https://www.akamai.com/cloud/pricing) and the Quake AI dashboard before you commit.

## See also

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