How to manage multiple environments with OpenTofu
Coming from another cloud?
▸AWS·Terraform Workspaces
This Quake AI feature maps to AWS’s Terraform Workspaces.
▸Google Cloud·Terraform Environments
This Quake AI feature maps to Google Cloud’s Terraform Environments.
How to manage multiple environments with OpenTofu
Most production workloads need at least two environments: one for development and testing, one for production. This guide covers two approaches to managing multiple environments on Quake AI with OpenTofu: variable files and directory structure.
Prerequisites#
- OpenTofu or Terraform installed
- Quake AI credentials configured (see How to get started with IaC)
- Familiarity with OpenTofu variables and modules
Approach 1: Variable files per environment#
The most straightforward approach uses a single set of .tf files with different .tfvars files for each environment.
Project structure#
project/
main.tf
variables.tf
outputs.tf
backend.tf
envs/
dev.tfvars
staging.tfvars
production.tfvarsDefine variables#
In variables.tf, parameterize everything that differs between environments:
variable "environment" {
type = string
description = "Environment name (dev, staging, production)"
}
variable "instance_count" {
type = number
default = 1
}
variable "flavor_name" {
type = string
description = "Compute flavor for instances"
}
variable "network_cidr" {
type = string
description = "CIDR block for the private network"
}Create per-environment variable files#
envs/dev.tfvars:
environment = "dev"
instance_count = 1
flavor_name = "s1a.small"
network_cidr = "10.0.1.0/24"envs/production.tfvars:
environment = "production"
instance_count = 3
flavor_name = "m2a.large"
network_cidr = "10.0.10.0/24"Use environment-specific state#
Configure the backend to use a different state key per environment. Pass the key during initialization:
tofu init -backend-config="key=dev/terraform.tfstate"Or use a backend configuration file per environment:
# envs/dev.backend.hcl
key = "dev/terraform.tfstate"tofu init -backend-config=envs/dev.backend.hclApply to a specific environment#
tofu plan -var-file=envs/dev.tfvars
tofu apply -var-file=envs/dev.tfvarsFor production:
tofu plan -var-file=envs/production.tfvars
tofu apply -var-file=envs/production.tfvarsResource naming#
Use the environment variable in resource names to avoid collisions:
data "openstack_images_image_v2" "ubuntu" {
name = "Ubuntu-24.04"
most_recent = true
}
resource "openstack_compute_instance_v2" "app" {
count = var.instance_count
name = "${var.environment}-app-${count.index}"
flavor_name = var.flavor_name
block_device {
uuid = data.openstack_images_image_v2.ubuntu.id
source_type = "image"
destination_type = "volume"
volume_size = 10
delete_on_termination = true
}
network {
name = openstack_networking_network_v2.main.name
}
}Approach 2: Directory-per-environment#
For teams that prefer complete isolation, use a separate directory for each environment. Each directory has its own .tf files and state.
Project structure (Approach 2: Directory-per-environment)#
project/
modules/
app/
main.tf
variables.tf
outputs.tf
environments/
dev/
main.tf
backend.tf
staging/
main.tf
backend.tf
production/
main.tf
backend.tfShared module#
Put reusable infrastructure in modules/app/:
# modules/app/main.tf
variable "environment" { type = string }
variable "instance_count" { type = number }
variable "flavor_name" { type = string }
data "openstack_images_image_v2" "ubuntu" {
name = "Ubuntu-24.04"
most_recent = true
}
resource "openstack_compute_instance_v2" "app" {
count = var.instance_count
name = "${var.environment}-app-${count.index}"
flavor_name = var.flavor_name
block_device {
uuid = data.openstack_images_image_v2.ubuntu.id
source_type = "image"
destination_type = "volume"
volume_size = 10
delete_on_termination = true
}
network {
name = "PublicEphemeral"
}
}Environment entry points#
Each environment calls the module with its own values:
# environments/dev/main.tf
module "app" {
source = "../../modules/app"
environment = "dev"
instance_count = 1
flavor_name = "s1a.small"
}# environments/production/main.tf
module "app" {
source = "../../modules/app"
environment = "production"
instance_count = 3
flavor_name = "m2a.large"
}Apply per environment#
cd environments/dev
tofu init && tofu apply
cd ../production
tofu init && tofu applyWhich approach to use#
| Factor | Variable files | Directory-per-environment |
|---|---|---|
| State isolation | Same config, separate state keys | Fully separate state and config |
| Drift between environments | Environments stay in sync by default | Can diverge intentionally |
| Complexity | Lower (one set of files) | Higher (duplicate entry points) |
| CI/CD integration | Pass -var-file flag | Change directory |
| Best for | Small-to-medium teams, similar environments | Large teams, environments with different architectures |
For most Quake AI projects, variable files (Approach 1) are sufficient. Use directory-per-environment when production and development have fundamentally different resource configurations.
See also#
Usage Guidelines
The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.
For the full policy, see Usage Guidelines.
Last validated: 25.05.2026
See Also
Terraform and OpenTofu on Quake AI
Prerequisite
How to add a block volume to a template
Shares: IaC, Terraform
How to deploy an application to a Quake AI VM from CI
Shares: IaC, Terraform
How to emulate a branchable Postgres workflow
Shares: IaC, Terraform
How to integrate OpenTofu with CI/CD
Shares: IaC, Terraform