All case studiesConfiguration Management

Multi-Cloud Provisioning from One Config

One Terraform configuration that stands up a VM in AWS, Azure, GCP, and Oracle Cloud at once — no race conditions, no explicit dependency chaining.

TerraformMulti-CloudInfrastructure as Code

The challenge

Coordinating four clouds from one configuration is genuinely tricky. Terraform forbids depends_on, count, and for_each on modules that carry their own provider blocks, and firing concurrent API calls across four providers invites intermittent failures.

Our approach

We use module composition: one root configuration composes four independently written single-cloud child modules via relative source paths. Each child owns its provider configuration, while the root declares all four providers so a single init installs them without duplication. We serialize the whole run with -parallelism=1, so exactly one cloud API operation executes at a time across the entire graph — eliminating cross-cloud races without hand-written dependencies.

Root moduleparallelism = 1AWS · t3.micro (Amazon Linux)Azure · B2ats_v2 Spot (Ubuntu)GCP · e2-micro (Ubuntu)OCI · E2.1.Micro (Ubuntu)

Technical specifics

  • Four VMs, one per cloud: AWS t3.micro (Amazon Linux 2023), Azure Spot Standard_B2ats_v2 (Ubuntu 24.04), GCP e2-micro (Ubuntu 24.04), OCI VM.Standard.E2.1.Micro (Ubuntu 24.04).
  • No secrets in the repo — only account-scoping ids (project, compartment, subscription) in a gitignored tfvars.
  • Outputs are public_ips and ssh_commands maps keyed by cloud, plus a helper script that queries all four cloud CLIs.
  • Auth spans an AWS CLI profile, az login, GCP ADC, and the OCI config profile.
  • Apply and destroy both run with -parallelism=1.

Example configuration

The root declares every provider and composes the four single-cloud modules; -parallelism=1 serializes the whole graph.

main.tf (root)hcl
module "aws"   { source = "../terraform-aws"   name = var.name public_key_path = var.public_key_path }
module "azure" { source = "../terraform-azure" name = var.name public_key_path = var.public_key_path }
module "gcp"   { source = "../terraform-gcp"   name = var.name project_id = var.gcp_project_id }
module "oci"   { source = "../terraform-oci"   name = var.name compartment_id = var.oci_compartment_id }

output "ssh_commands" {
  value = { aws = module.aws.ssh_command, azure = module.azure.ssh_command,
            gcp = module.gcp.ssh_command, oci = module.oci.ssh_command }
}
versions.tf + commandshcl
terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws     = { source = "hashicorp/aws",     version = "~> 5.0" }
    azurerm = { source = "hashicorp/azurerm", version = "~> 4.0" }
    google  = { source = "hashicorp/google",  version = "~> 6.0" }
    oci     = { source = "oracle/oci",        version = "~> 6.0" }
  }
}
# terraform apply -parallelism=1   # one cloud API op at a time — no races
# terraform destroy -parallelism=1

Outcome

A single reproducible configuration stands up and tears down four VMs across four clouds with no race conditions and no explicit dependency chaining — at near-zero cost, with ready-to-use SSH commands as output.

Have a similar challenge?

We deliver this work end to end — from first commit to a secure, live deploy. Let’s talk about yours.