Building your SaaS Product using Terraform¶
Getting started¶
The Omnistrate Terraform Integration streamlines the deployment and management of cloud infrastructure by combining the power of Terraform with the flexibility of Omnistrate. This integration allows you to inject dynamic metadata directly into your Terraform templates, automate complex multi-cloud deployments, and modularize infrastructure components for efficient management. By integrating with other deployment types such as Helm charts, Operators or Kustomize, Omnistrate enhances orchestration capabilities, enabling users to create scalable and adaptable Plans. With Omnistrate, you can simplify your infrastructure-as-code workflows and ensure smooth, automated provisioning across various cloud environments and tenants.
Note
Support for Terraform Integration is available for AWS, GCP, Azure, OCI, and Nebius. You can define your Plan to use the corresponding stack depending on the cloud provider that is being deployed, making your service multi-cloud.
Warning
Omnistrate manages the Terraform state backend using Kubernetes secrets. Any custom backend configuration in your Terraform files (such as S3, GCS, or Azure Blob Storage) will be removed during deployment. Do not include a custom backend block — Omnistrate handles state management automatically.
Integrating Terraform on your Plan¶
Terraform stacks require a Plan specification file that defines your overall service topology on Omnistrate. Unlike Docker Compose deployments where the service specification can be embedded within the compose file, Terraform deployments must use a separate Plan specification file. A complete description of the Plan specification can be found on Plan Spec
Here is an example of a using Terraform to configure a SaaS Product:
provider "aws" {
region = "{{ $sys.deploymentCell.region }}"
}
# Create a Security Group for RDS and ElastiCache
resource "aws_security_group" "rds_elasticache_sg" {
name = "e2e-rds-elasticache-security-group-{{ $sys.id }}"
description = "Security group for RDS and ElastiCache instances"
vpc_id = "{{ $sys.deploymentCell.cloudProviderNetworkID }}"
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Adjust for appropriate security
}
ingress {
from_port = 11211 # Default Memcached port
to_port = 11211
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Adjust accordingly
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Create a DB Subnet Group for RDS
resource "aws_db_subnet_group" "rds_subnet_group" {
name = "e2e-rds-subnet-group-{{ $sys.id }}"
description = "My RDS subnet group"
subnet_ids = [
"{{ $sys.deploymentCell.publicSubnetIDs[0].id }}",
"{{ $sys.deploymentCell.publicSubnetIDs[1].id }}",
"{{ $sys.deploymentCell.publicSubnetIDs[2].id }}"
]
}
# Create a Subnet Group for ElastiCache
resource "aws_elasticache_subnet_group" "elasticache_subnet_group" {
name = "e2e-elasticache-subnet-group-{{ $sys.id }}"
description = "My ElastiCache subnet group"
subnet_ids = [
"{{ $sys.deploymentCell.publicSubnetIDs[0].id }}",
"{{ $sys.deploymentCell.publicSubnetIDs[1].id }}",
"{{ $sys.deploymentCell.publicSubnetIDs[2].id }}"
]
}
# Create RDS instances
resource "aws_db_instance" "example1" {
identifier = "e2e-instance-1-{{ $sys.id }}"
engine = "mysql"
instance_class = "db.t3.micro"
allocated_storage = 20
db_subnet_group_name = aws_db_subnet_group.rds_subnet_group.name
vpc_security_group_ids = [aws_security_group.rds_elasticache_sg.id]
username = "admin"
password = "yourpassword"
parameter_group_name = "default.mysql8.0"
engine_version = "8.0.37"
skip_final_snapshot = true
depends_on = [
aws_security_group.rds_elasticache_sg,
aws_db_subnet_group.rds_subnet_group
]
}
resource "aws_db_instance" "example2" {
identifier = "e2e-instance-2-{{ $sys.id }}"
engine = "mysql"
instance_class = "db.t3.micro"
allocated_storage = 20
db_subnet_group_name = aws_db_subnet_group.rds_subnet_group.name
vpc_security_group_ids = [aws_security_group.rds_elasticache_sg.id]
username = "admin"
password = "yourpassword"
parameter_group_name = "default.mysql8.0"
engine_version = "8.0.37"
skip_final_snapshot = true
depends_on = [aws_db_instance.example1]
}
# Create ElastiCache Cluster for Memcached
resource "aws_elasticache_cluster" "example_memcached" {
cluster_id = "e2e-memcached-{{ $sys.id }}"
engine = "memcached"
node_type = "cache.t3.micro"
num_cache_nodes = 2 # Adjust as needed
subnet_group_name = aws_elasticache_subnet_group.elasticache_subnet_group.name
security_group_ids = [aws_security_group.rds_elasticache_sg.id]
depends_on = [
aws_db_instance.example2 # Ensure ElastiCache is created after all RDS instances
]
}
Warning
Please ensure that the main file for your terraform stack contains the definition on the provider.
Terraform templates can be referenced from a GitHub repository, either private or public. One repository can contain multiple Terraform stacks, and can be referenced using a specific git reference (tag or branch) and a folder path within that repository. Omnistrate allows you to configure a reference to a Git repository and path where the Terraform stack is stored. When selecting a path for your repository, Omnistrate expects the entire Terraform definition to be under that folder structure.
You can also use a local Terraform artifact with omnistrate-ctl build. Use artifactRelativePath in the Plan spec and run CTL from the workspace root that contains that relative path.
Example workspace:
Example local-artifact spec:
name: Terraform Local Artifact
deployment:
hostedDeployment:
awsAccountId: "<AWS_ACCOUNT_ID>"
awsBootstrapRoleAccountArn: "arn:aws:iam::<AWS_ACCOUNT_ID>:role/omnistrate-bootstrap-role"
services:
- name: terraform
internal: true
terraformConfigurations:
configurationPerCloudProvider:
aws:
terraformPath: /
artifactRelativePath: terraform/aws
Build the Plan with CTL:
cd my-service
omnistrate-ctl build \
--spec-type ServicePlanSpec \
--file spec.yaml \
--product-name "Terraform Local Artifact" \
--release-as-preferred
There are two paths to configure:
artifactRelativePathtells CTL which local file or directory to upload.terraformPathtells Omnistrate where to run OpenTofu or Terraform inside that uploaded content.
For example, if your Terraform module is in terraform/aws, you can upload that module directory directly:
Or you can upload its parent directory and point terraformPath at the module subdirectory:
Use one Terraform source per cloud-provider entry: set either gitConfiguration or artifactRelativePath, not both. Prefer relative artifact paths such as terraform/aws; paths that escape the workspace root, such as ../terraform, are rejected.
Within the Terraform templates, the Omnistrate platform provides system parameters that can be used to reference to information about the current cluster, for instance:
$sys.deploymentCell.publicSubnetIDs[i].id$sys.deploymentCell.privateSubnetIDs[i].id$sys.deploymentCell.region$sys.deploymentCell.cloudProviderNetworkID$sys.deploymentCell.cidrRange
You can inject these values into your Terraform templates, and these values will be dynamically rendered during deployment.
In addition, the Omnistrate platform will automatically output all values defined in the Terraform templates' output block. You can use these outputs to inject into other deployment components, as shown in the example below:
Info
You can use system parameters to customize Terraform templates. A detailed list of system parameters be found on Build Guide / System Parameters.
Registering a Service using a Terraform stack¶
Terraform stacks are managed through a specification file that defines your overall service topology on Omnistrate. A complete description of the Plan specification can be found on Getting started / Plan Spec. Consider using Git tags to version the terraform stack and ensure consistency across Plan versions.
Here is an example of a SaaS Product that deploys Redis Clusters using a Helm chart.
Note
This example uses the legacy operatorCRDConfiguration.template and readinessConditions fields to show Terraform outputs flowing into an operator resource. For new operator-backed services, prefer systemWorkflows for lifecycle resources, readiness, failure conditions, and outputs. See Build from Kubernetes Operators.
Example:
name: Terraform Resources
deployment:
byoaDeployment:
awsAccountId: "<AWS_ACCOUNT_ID>"
awsBootstrapRoleAccountArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/omnistrate-bootstrap-role
services:
- name: terraform
internal: true
terraformConfigurations:
configurationPerCloudProvider:
aws:
terraformPath: /artifacts/terraform/aws
gitConfiguration:
reference: refs/heads/main
repositoryUrl: https://github.com/omnistrate-community/examples.git
- name: CNPG
dependsOn:
- terraform
operatorCRDConfiguration:
template: |
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
namespace: default # Should ignore this namespace
spec:
instances: 3
storage:
size: 1Gi
readinessConditions:
"$var._crd.status.phase": "Cluster in healthy state"
"$var._crd.status.readyInstances": 3
'$var._crd.status.conditions[?(@.type=="Ready")].status': "True"
outputParameters:
"Postgres Container Image": "$var._crd.status.image"
"Status": "$var._crd.status.phase"
"Topology": "$var._crd.status.topology"
helmChartDependencies:
- chartName: cloudnative-pg
chartVersion: 0.22.1
chartRepoName: cnpg
chartRepoURL: https://cloudnative-pg.github.io/charts
You can register this spec using our CLI:
omnistrate-ctl build -f spec.yaml --name 'Multiple Resources' --release-as-preferred --spec-type ServicePlanSpec
# Example output shown below
✓ Successfully built service
Check the Plan result at: https://omnistrate.cloud/product-tier?serviceId=s-xxx&environmentId=se-xxx
Access your SaaS Product at: https://saasportal.instance-xxx.hc-xxx.us-east-2.aws.f2e0a955bb84.cloud/service-plans?serviceId=s-xxxx&environmentId=se-xxx
More Real-World Examples¶
Using Terraform outputs¶
Omnistrate platform will automatically output all values defined in the Terraform templates output block. You can use these outputs to inject into other deployment components.
For example, a resource can define output parameters on the stack
output "rds_endpoints_1" {
value = aws_db_instance.example1.endpoint
}
output "rds_endpoints_2" {
value = {
endpoint: aws_db_instance.example2.endpoint
}
sensitive = true
}
output "elasticache_endpoint" {
value = aws_elasticache_cluster.example_memcached.cache_nodes[0].address
}
and in the dependent resource we can reference to the terraform output properties:
{{ $terraformChild.out.rds_endpoints_1 }}
{{ $terraformChild.out.rds_endpoints_2.endpoint }}
{{ $terraformChild.out.elasticache_endpoint }}
If you want selected Terraform outputs to appear as exported fields on the Terraform resource in Omnistrate, declare them explicitly under requiredOutputs:
services:
- name: terraformChild
internal: true
terraformConfigurations:
configurationPerCloudProvider:
aws:
terraformPath: /terraform/aws
gitConfiguration:
reference: refs/heads/main
repositoryUrl: https://github.com/your-org/infra-repo.git
requiredOutputs:
- key: rds_endpoints_1
exported: true
- key: elasticache_endpoint
exported: true
For a deeper explanation of output mapping versus exported Terraform outputs, see Input Parameters and Output Mapping.
Additional permissions for Terraform¶
Using a terraform stack normally requires to define permissions to create, update and delete the entities involved. You can configure a custom policy / role that will be used when applying each Terraform stack defined as a resource in Omnistrate.
Custom Terraform permissions for BYOA Deployment Model¶
To configure permissions required to provision Terraform resources within BYOA Deployment Model, you can configure a Custom Terraform Policy. This feature is configured on the Plan level and Omnistrate will adjust onboarding scripts for your customers to include appropriate resources (depending on cloud provider).
- For AWS, configuration is provider as a policy document. Omnistrate will create a dedicated AWS IAM role per-model when onboarding your customers. With each update, a new version of the cloud formation stack will be created.
- For GCP, configuration is provided as a list of GCP IAM roles. Omnistrate will create a dedicated GCP IAM service account per-role with specified roles bound. GCP CLI commands will always reflect the latest configuration.
- For Azure, configuration is provided as a list of RBAC roles. Omnistrate will create a single service principal with permissions merged across all service models. RBAC permissions are scoped to the subscription level. Entra roles can be bound by specifying the type as "Entra" and are bound to the root tenant level. Just like for the GCP, an Azure CLI onboarding script will always reflect the latest configuration.
- For OCI, configuration is provided as a list of OCI IAM permission fragments under
permissions.oci, such asmanage queuesandmanage ons-topics. During onboarding, Omnistrate creates a Terraform user and renders these fragments into policy statements scoped to the account compartment created for the account config:Allow any-user to <permission> in compartment id <account_config_compartment> where request.principal.id='<terraform_user_ocid>'. During provisioning, this custom identity (AWS IAM role / GCP IAM service account) is used to modify Terraform resources within the Plan.
To configure custom terraform permissions using the service spec file, add the "CUSTOM_TERRAFORM_POLICY" feature such as:
features:
CUSTOM_TERRAFORM_POLICY:
policies:
aws: |
{
"Statement": [
{
"Action": [
"sqs:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
roles:
gcp:
- name: roles/pubsub.admin
- name: roles/cloudsql.admin
azure:
- name: "Network Contributor"
- name: "Storage Account Contributor"
- name: "Virtual Machine Contributor"
- name: "Global Reader"
type: "Entra"
permissions:
oci:
- "manage queues"
- "manage ons-topics"
In the example above, Terraform will be allowed to manage OCI Queues and OCI Notifications (ONS) topics.
To achieve the same effect using Omnistrate CTL, you can use the following command:
omctl service-plan enable-feature 'product name' 'Plan name' --feature CUSTOM_TERRAFORM_POLICY --feature-configuration-file ../path/to/config-file
With config file having the following content (AWS policy itself needs to be provided as JSON string):
{
"policies": {
"aws": "{\"Statement\":[{\"Action\": [\"sqs:*\"],\"Effect\": \"Allow\",\"Resource\": \"*\"}]}"
},
"roles": {
"gcp": [
{"name": "roles/pubsub.admin"},
{"name": "roles/cloudsql.admin"}
],
"azure": [
{"name": "Network Contributor"},
{"name": "Storage Account Contributor"},
{"name": "Virtual Machine Contributor"},
{"name": "Global Reader", "type": "Entra"}
]
},
"permissions": {
"oci": [
"manage queues",
"manage ons-topics"
]
}
}
To disable this feature, use the following command:
Warning
Each time the custom terraform policy is updated, a new version of the onboarding script is generated. Your customers might need to re-run their account onboarding, otherwise they might not be able to provision your service. This requires updating their account onboarding CloudFormation stack (for AWS), or getting latest GCP CLI commands and running them (for GCP).
Custom Terraform execution identity for SaaS Provider hosted model¶
For SaaS Provider hosted deployments, Omnistrate manages Terraform execution identities for each cloud provider. For AWS, GCP, Azure, and OCI, the identity is auto-created — you only need to assign the permissions your Terraform stack requires. You do not need to specify the identity in the Plan spec.
- AWS (auto-created): Omnistrate creates an IAM role named
omnistrate-terraform-execution-rolein your AWS account. Assign the permissions your Terraform stack needs to this role. - GCP (auto-created): Omnistrate creates a service account named
omnistrate-tf-<org-id>in your GCP project. Assign the permissions your Terraform stack requires to this service account. - Azure (auto-created): Omnistrate creates a service principal named
terraform-<org-id>-<subscription-id>. Assign the permissions your Terraform stack requires to this service principal. - OCI (auto-created): Omnistrate creates a user named
<org-id>-terraform-user. Assign the permissions your Terraform stack requires to this user.
name: Multiple Resources
deployment:
hostedDeployment:
awsAccountId: "<AWS_ACCOUNT_ID>"
awsBootstrapRoleAccountArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/omnistrate-bootstrap-role
services:
- name: terraform
internal: true
terraformConfigurations:
configurationPerCloudProvider:
aws:
terraformPath: /terraform
gitConfiguration:
reference: refs/heads/main
repositoryUrl: https://github.com/omnistrate-community/examples.git
gcp:
terraformPath: /terraform
gitConfiguration:
reference: refs/heads/main
repositoryUrl: https://github.com/omnistrate-community/examples.git
Nebius Terraform authentication¶
Nebius uses explicit service-account authentication. Configure the service-account credentials on the nebius Terraform entry:
services:
- name: terraform
internal: true
terraformConfigurations:
configurationPerCloudProvider:
nebius:
terraformPath: /terraform/nebius
serviceAccountID: "serviceaccount-e00vqdp9fskhmmaan8"
publicKeyID: "publickey-e00h9scsyy9mbefrjf"
privateKeyPEM: "$secret.nebiusTerraformPrivateKey"
gitConfiguration:
reference: refs/heads/main
repositoryUrl: https://github.com/your-org/infra-repo.git
Notes:
serviceAccountID,publicKeyID, andprivateKeyPEMare all required forconfigurationPerCloudProvider.nebius.privateKeyPEMcan be inline, but prefer$secret.<name>so the PEM stays out of source control.- Omnistrate resolves
$secretreferences before it hands the stack to Terraform. - Keep the Terraform source provider block minimal. Omnistrate injects the Nebius credential wiring at runtime; for example:
terraform {
required_providers {
nebius = {
source = "terraform-provider.storage.eu-north1.nebius.cloud/nebius/nebius"
}
}
}
provider "nebius" {
domain = "api.eu.nebius.cloud:443"
}
- When Nebius auth is specified, Omnistrate uses it for that Terraform resource instead of the default host-cluster Terraform identity.
Control-Plane-Targeted Terraform¶
Some Terraform resources manage provider-side assets that should run in the Omnistrate control plane account instead of the data plane deployment cell. For those resources, set deploymentTarget.account: ControlPlane on the Terraform resource.
Example:
services:
- name: controlPlaneInfra
internal: true
deploymentTarget:
account: ControlPlane
terraformConfigurations:
configurationPerCloudProvider:
aws:
terraformPath: /terraform/control_plane
gitConfiguration:
reference: refs/heads/main
repositoryUrl: https://github.com/your-org/infra-repo.git
Note
For control-plane-targeted Terraform, ensure that the appropriate execution identity exists in your cloud account. For AWS, GCP, Azure, and OCI, Omnistrate auto-creates the identity. Assign the permissions your Terraform stack requires to the identity.
Notes:
- For control-plane-targeted Terraform, define only the cloud provider entry that actually executes the stack. A control-plane-targeted AWS stack does not need placeholder
gcp,azure, ornebiusentries. - There is no shared shorthand outside
configurationPerCloudProvider; each provider entry is defined explicitly. - This is useful for shared control-plane resources such as DNS, registry, or other provider-side integrations that are not created inside each deployment cell.
AWS Terraform role¶
Omnistrate pre-creates the omnistrate-terraform-execution-role IAM role for Terraform executions during account setup. You do not need to create this role for AWS.
AWS requirements for Terraform role¶
The role uses the exact name omnistrate-terraform-execution-role. Omnistrate creates the role with the required Trusted Entity configuration:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AWS_ACCOUNT_ID>:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/dataplane-agent-iam-role-*"
}
}
}
]
}
Info
Omnistrate creates the IAM role with the exact name omnistrate-terraform-execution-role.
Pre-created principals¶
Omnistrate will by default pre-create empty IAM principals for Terraform resources during account setup.
- For AWS, IAM role
omnistrate-terraform-execution-rolewill be created (this role starts withomnistrate-and has a trusted entity configuration) - For GCP, IAM service account
omnistrate-tf-<org-id>will be created (this service account will have IAM binding to Omnistrate dataplane) - For Azure, service principal
terraform-<org-id>-<subscription-id>will be created - For OCI, user
<org-id>-terraform-userwill be created
These principals are pre-created with necessary configuration (as described above). You can configure them with the necessary permissions for your Terraform stack. This pre-created-principal flow does not apply to Nebius Terraform resources; use the Nebius service-account fields shown above.
Terraform Variables Override with Inline File¶
Omnistrate supports overriding Terraform variables using inline file content through the variablesValuesFileOverride property. This feature allows you to define Terraform variable values directly within your Plan specification without requiring a separate .tfvars file in your repository.
The variablesValuesFileOverride property accepts a multi-line string containing Terraform variable definitions in the standard .tfvars format. You can use Omnistrate system parameters within these variable definitions to inject dynamic values during deployment.
Configuration Example¶
Here's an example of how to use the variablesValuesFileOverride feature:
name: Multiple Resources
deployment:
byoaDeployment:
awsAccountId: "<AWS_ACCOUNT_ID>"
awsBootstrapRoleAccountArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/omnistrate-bootstrap-role
gcpProjectId: "<GCP_INFO>"
gcpProjectNumber: "<GCP_INFO>"
gcpServiceAccountEmail: "<GCP_INFO>"
azureSubscriptionId: '<AZURE_INFO>'
azureTenantId: '<AZURE_INFO>'
services:
- name: terraformChild
internal: true
terraformConfigurations:
configurationPerCloudProvider:
aws:
terraformPath: /terraform
variablesValuesFileOverride: |
vpc_id = "{{ $sys.deploymentCell.cloudProviderNetworkID }}"
region = "{{ $sys.deploymentCell.region }}"
instance_type = "t3.medium"
environment = "production"
subnet_ids = [
"{{ $sys.deploymentCell.publicSubnetIDs[0].id }}",
"{{ $sys.deploymentCell.publicSubnetIDs[1].id }}"
]
gitConfiguration:
reference: refs/tags/12.0
repositoryUrl: https://github.com/omnistrate-community/sample/TestKustomizeTemplate.git
Using System Parameters¶
You can inject Omnistrate system parameters into your variable values:
variablesValuesFileOverride: |
# Network configuration from deployment cell
vpc_id = "{{ $sys.deploymentCell.cloudProviderNetworkID }}"
region = "{{ $sys.deploymentCell.region }}"
availability_zones = [
"{{ $sys.deploymentCell.region }}a",
"{{ $sys.deploymentCell.region }}b"
]
# Dynamic naming with system ID
resource_prefix = "omnistrate-{{ $sys.id }}"
# Subnet configuration
public_subnets = [
"{{ $sys.deploymentCell.publicSubnetIDs[0].id }}",
"{{ $sys.deploymentCell.publicSubnetIDs[1].id }}"
]
private_subnets = [
"{{ $sys.deploymentCell.privateSubnetIDs[0].id }}",
"{{ $sys.deploymentCell.privateSubnetIDs[1].id }}"
]
Tip
The variablesValuesFileOverride feature is particularly useful when you want to customize Terraform behavior on Omnistrate platform without modifying the underlying Terraform code.
Custom OpenTofu CLI Configuration¶
Omnistrate runs your Terraform stack with OpenTofu. Use the cliConfigFileOverride property to supply a custom OpenTofu CLI configuration file for a Terraform Resource — without baking it into your repository or a custom runner image.
The property accepts a multi-line string containing the CLI configuration file content. Omnistrate writes it into the Terraform workspace and points TF_CLI_CONFIG_FILE at it for every operation on the stack (init, plan, apply, destroy) for the cloud provider entry where you specify it. It works for both Git-based and artifact-based Terraform sources.
Common uses include provider installation mirrors and credentials for private module registries.
Example: Alternate Provider Mirrors for Specific Registries¶
The following configuration installs hashicorp/* providers from an internal network mirror while all other providers continue to install directly from their origin registries — useful when the public registry is unreachable from your deployment environment, or when provider binaries must come from a vetted internal source:
services:
- name: terraformResource
internal: true
terraformConfigurations:
configurationPerCloudProvider:
aws:
terraformPath: /terraform
cliConfigFileOverride: |
provider_installation {
network_mirror {
url = "https://terraform-mirror.internal.example.com/providers/"
include = ["registry.opentofu.org/hashicorp/*"]
}
direct {
exclude = ["registry.opentofu.org/hashicorp/*"]
}
}
gitConfiguration:
reference: refs/heads/main
repositoryUrl: https://github.com/your-org/infra-repo.git
With this configuration, tofu init resolves any provider matching registry.opentofu.org/hashicorp/* through the mirror at terraform-mirror.internal.example.com, and falls back to direct installation for everything else.
See the OpenTofu CLI configuration documentation for the full set of supported blocks, including credentials for private registries and oci_default_credentials for OCI-based mirrors.
Tip
Like variablesValuesFileOverride, the CLI configuration content supports Omnistrate system parameters, so mirror URLs or registry tokens can be injected dynamically at deployment time.
Note
CLI configuration files can contain credentials. Omnistrate stores the content on the Terraform Resource and redacts cliConfigFileOverride in API responses for users with read-only roles.
Dive Deeper¶
Now that you have a working Terraform-based SaaS Product, explore the build guides to extend your deployment:
- Terraform deployment strategy — Browse the Terraform-specific strategy and guide set
- Terraform Troubleshooting — Diagnose failed Terraform plans and applies
- Terraform Multi-Cloud Configuration — Configure Terraform stacks across AWS, GCP, Azure, OCI, and Nebius
- Terraform Input Parameters and Output Mapping — Map API parameters to Terraform variables and expose outputs
- Helm and Terraform — Combine Terraform-managed infrastructure with Helm-deployed applications
- Plan Specification Reference — Complete reference for the Plan spec format, including the Terraform configuration schema
- API Parameters — Expose customer-configurable parameters through your SaaS APIs
- System Parameters — Inject dynamic platform values into your Terraform variables
- Resource Dependencies — Set up dependencies between Terraform and other resources (Helm, Operators)