Terraform Configuration
The following shows how to configure Terraform.
Backend Prerequisites
The Terraform state is stored in OCI Object Storage. If the state bucket has not been created yet, it must be provisioned in the following way before running terraform init:
# Create the state bucket (one-time setup)
oci os bucket create \
--compartment-id <compartment-ocid> \
--name "your-terraform-state-bucket" \
--storage-tier Standard \
--profile <profile>Backend configuration
The backend.tf file declares an empty OCI backend block:
backend "oci" {}
Backend parameters are supplied via .hcl files in backend-configs/:
| File | Purpose |
|---|---|
backend-configs/primary-oci-example.hcl
| Primary workspace backend config template |
backend-configs/secondary-oci-example.hcl
| Secondary workspace backend config template |
Backend configuration fields:
| Field | Description |
|---|---|
| Bucket | Name of the OCI Object Storage bucket used to store Terraform state |
| namespace | OCI Object Storage namespace for the tenancy (retrieve with oci os ns get) |
| region | OCI region where the state bucket resides |
| key |
State file path within the bucket; the env:/ prefix enables
per-workspace state isolation
|
| auth |
Authentication method for the OCI provider (ApiKey for API key-based
auth)
|
config_file_profile
|
OCI CLI config profile to use for authentication (e.g.,
DEFAULT)
|
Example .hcl file:
bucket = "your-terraform-state-bucket"
namespace = "your-oci-namespace"
region = "<your-region>"
key = "env:/logscale-oci-oke"
auth = "ApiKey"
config_file_profile = "DEFAULT"
Separate backend configurations are required because each workspace stores state
independently. Using separate .hcl files ensures that primary and secondary
states don't collide and allows different backend configurations per environment.
Workspace Setup
Each cluster uses a separate Terraform workspace. The workspace name must match the
workspace_name value in the corresponding tfvars file.
Workspaces must be created after terraform init (the backend must be
initialized before workspace commands are available).
Important
terraform init is run once per backend configuration.
To switch between state files, use: terraform init -backend-config=<config> -reconfigure.
The -reconfigure flag tells Terraform to re-initialize the backend with the new config without migrating state.
Standalone deployment (single workspace):
# 1. Initialize with backend config (first time only)
terraform init -backend-config=backend-configs/primary-oci.hcl
# 2. Create the workspace (only needed once)
terraform workspace new primarySwitching between workspaces:
terraform workspace select primaryWorkspace Safety Validation
A safety mechanism prevents applying the wrong tfvars file against the
wrong workspace. Each tfvars file includes a workspace_name variable, and a
check block in validation.tf verifies that this value matches the current terraform.workspace at
plan/apply time
Example tfvars:
workspace_name = "primary"
dr = ""
# ... other variablesSee the Terraform Variables README for a full list of configuration values.
If the current workspace does not match the workspace_name in the tfvars file, Terraform will fail with an error:
============================================================================
ERROR: WORKSPACE MISMATCH DETECTED!
============================================================================
Current Terraform workspace: 'default'
workspace_name in tfvars: 'secondary'
To fix this, either:
1. Switch to the correct workspace:
terraform workspace select secondary
2. Or use the correct tfvars file for the 'default' workspace:
terraform plan -var-file=default-<region>.tfvars
============================================================================This prevents accidentally applying the primary configuration to the secondary cluster or vice versa.
Additional validation checks (validation.tf also enforces):
| Check | Type | Condition | Error if violated |
|---|---|---|---|
bastion_client_allow_list_required
| check (warning) |
provision_bastion=true requires non-empty
bastion_client_allow_list
| Bastion deployed without client allow list |
control_plane_cidrs_required_for_public_endpoint
| check (warning) |
endpoint_public_access=true requires non-empty
control_plane_allowed_cidrs | Public endpoint with no CIDR restrictions |
control_plane_cidrs_no_wildcard
| check (warning) |
control_plane_allowed_cidrs must not contain
0.0.0.0/0
| Kubernetes API exposed to the internet |
Hard validation locals (validation.tf). These fire as blocking errors
at plan time:
| Local | Condition | Error if violated |
|---|---|---|
cluster_config_validation
| Validates production readiness, storage, network, and security configuration | Aggregated error with specific failure details |
_resource_limit_check
| Validates total instances and block volumes within OCI per-AD limits | Requested resources exceed OCI limits |
security_compliant
|
0.0.0.0/0 in public_lb_cidrs only allowed when
use_external_health_check=true | Security compliance failed |