Terraform Native Service enables you to deploy and manage Terraform or OpenTofu infrastructure code directly within Qovery. This service type allows you to provision cloud resources, configure external services, and manage infrastructure as code (IaC) using the same environment structure as your applications. Terraform executes within Kubernetes pods on your cluster, with automatic state management, variable injection, and integrated deployment workflows.
This page describes the Terraform service in the Console. To manage a Terraform service with the Qovery Terraform provider, use the qovery_terraform_service resource.
Navigate to the environment where you want to deploy your Terraform infrastructure.
2
Create New Service
Click New Service and select Terraform from the service type options.
3
Configure Service Name
Provide a service name that identifies this Terraform service (e.g., aws-infrastructure, cloudflare-config).
4
Select Git Repository
Choose the Git repository containing your Terraform code. This repository must include your .tf configuration files.Specify the branch and root path if your Terraform code is in a subdirectory.
5
Select Engine
Choose the execution engine:
Terraform - Official HashiCorp Terraform
OpenTofu - Open-source Terraform fork
6
Select Terraform Version
Choose the Terraform version to use for execution. Supported versions depend on your selected engine.
7
State Management
Configure how Terraform stores and manages state files. Qovery supports two state management modes.
Default (Cluster-Managed)
Custom Backend (AWS S3)
By default, Terraform state is managed inside the Kubernetes cluster. State files are stored securely within the cluster and managed automatically by Qovery.This default configuration requires no additional setup and is ideal for getting started quickly.Benefits:
Zero configuration required
Automatic state management
Secure storage within your cluster
No external dependencies
If you prefer to manage your Terraform state in your own backend, you can configure a custom backend. The standard for AWS is to use an S3 backend.PrerequisitesBefore configuring your S3 backend, you need to:
Create an S3 bucket in your AWS account to store the Terraform state
Enable bucket versioning on your S3 bucket to allow state recovery in case of accidental deletions
Configure S3 state locking using the use_lockfile option (this avoids the need for a DynamoDB table)
Prepare AWS credentials with appropriate permissions to access the S3 bucket
Backend ConfigurationAdd a backend configuration block to your main.tf file in your Git repository:
bucket - Name of your S3 bucket for storing state files
key - Path to the state file within the bucket (typically terraform.tfstate)
region - AWS region where your S3 bucket is located
use_lockfile - Set to true to use S3’s native locking mechanism instead of DynamoDB (recommended)
encrypt - Set to true to enable server-side encryption for the state file (recommended)
Using use_lockfile = true eliminates the need to set up a DynamoDB table for state locking, simplifying your infrastructure. This is the recommended approach as DynamoDB-based locking is deprecated and will be removed in a future version of Terraform.
Best Practices:
Enable bucket versioning on your S3 bucket to allow state recovery in case of accidental deletions or corruption
Use encrypt = true to enable server-side encryption for your state files
Never hardcode sensitive values in your backend configuration
Configuring AWS CredentialsTo allow Terraform to access your S3 backend, you must provide AWS credentials as environment variables in the service configuration:
The s3:DeleteObject permission is required for managing the lock file when using use_lockfile = true.
Using Cluster Credentials with Custom BackendIf you choose to use the default cluster credentials (instead of providing custom AWS credentials), be aware that the cluster’s IAM policy only allows access to S3 buckets with names prefixed with qovery-.You have two options:
Name your bucket with the qovery- prefix (e.g., qovery-my-terraform-backend)
Provide custom AWS credentials (recommended) with appropriate permissions for your bucket name
This restriction exists to prevent accidental access to unrelated S3 buckets in your AWS account.
Migration from Default StateIf you’re migrating from the default cluster-managed state to a custom S3 backend:
Add the backend configuration to your main.tf
Configure the AWS credentials as environment variables
Use the Migrate State action from the service’s Action Toolbar to transfer the existing state to your S3 bucket
8
Execution Timeout (Default)
The default timeout is set to 1 hour. This can be customized if your Terraform operations require more time.
9
Cloud Credentials (Default Behavior)
By default, Terraform uses cluster credentials when provisioning resources on the same cloud provider as your cluster.If you need to use custom credentials (e.g., a different AWS account, GCP project, or Azure subscription), you will configure them in the Environment Variables step.
10
Compute Resources (Default)
Terraform execution uses the following default compute resources:
CPU: 500 millicores (500 mCPU or 0.5 vCPU)
Memory: 256 MiB
Storage: 5 GiB
These resources can be updated later in the Service Settings if your Terraform operations require more capacity.These defaults, and the 1 hour timeout, apply to services created from the Console. The Terraform provider has its own defaults, listed on the qovery_terraform_service resource page.
11
Configure Terraform Variables
Qovery provides comprehensive variable management for Terraform, automatically detecting variables from your code and allowing flexible configuration.Automatic Variable DetectionQovery automatically loads variables from:
main.tf
variables.tf
Variables detected by Qovery will appear prefixed with tf_var_.Example:If your variables.tf contains:
variable "bucket_name" { type = string}variable "environment" { type = string default = "production"}
Qovery will create:
tf_var_bucket_name
tf_var_environment
Importing TFVAR FilesYou can import .tfvars files to configure multiple variables at once:
Click Import TFVAR
Select the TFVAR file(s) to import
Choose which TFVAR files to apply
Reorder the TFVAR files as needed
The last TFVAR file applied wins. If multiple TFVAR files define the same variable, the value from the last file in the order takes precedence.
Referencing Qovery Variables Inside a TFVAR FileYou can reference Qovery environment, project, and built-in variables directly inside a .tfvars file using the "{{ VARIABLE_NAME }}" syntax. The file stays in your git repository, and Qovery substitutes the references at deploy time against the variables of the environment being deployed.
Use this pattern to keep one .tfvars template in source control while injecting sensitive or generated values (database credentials, infrastructure outputs from another service) from the matching Qovery environment.
Only the {{ VARIABLE_NAME }} form is interpolated. Other forms such as ${VAR}, ${{VAR}}, or a bare identifier VAR are treated as literals and passed to Terraform unchanged.
Qovery variables of type File or File External Secret cannot be inlined as a Terraform variable value and are left as literals if referenced. A reference to an External Secret is resolved inside your cluster when the Terraform job starts: see Using external secrets with Terraform services.
If a referenced Qovery variable does not exist, the literal {{ NAME }} is passed through unchanged. Define the variable in your environment to have it substituted.
Manual Variable OverrideYou can manually override any variable value in two ways:
Direct Value Entry - Enter a value directly:
tf_var_bucket_name = "my-custom-bucket"
Reference Environment Variable - Reference another environment variable:
tf_var_bucket_name = ${MY_BUCKET_NAME}
Variables Not in main.tf or variables.tfIf you have variables defined in other .tf files that are not in main.tf or variables.tf, Qovery will not automatically detect them. You can create these variables manually using the tf_var_ prefix:
tf_var_my_custom_variable = "value"
12
Configure Environment Variables
Add standard environment variables that will be available during Terraform execution. This is where you configure custom cloud provider credentials, provider-specific settings, and other configuration.Common use cases:Custom Cloud CredentialsOverride the default cluster credentials with your own:AWS:
Use Qovery Secrets for sensitive credentials to ensure they are encrypted and never exposed in logs.
Terraform Environment VariablesYou can also set Terraform-specific environment variables:
TF_LOG=DEBUGTF_WORKSPACE=production
13
Review and Create
Review your configuration and click Create to provision the Terraform service.Optionally, you can select Create & Run Plan to execute terraform plan immediately and preview the execution plan before applying changes.
The Terraform Arguments section allows you to specify additional CLI arguments for each Terraform command. These arguments override default behaviors and enable advanced customization.
Terraform Arguments provide fine-grained control over Terraform execution. Use these to customize init, validate, plan, apply, and destroy operations.
By default, Terraform services run using a base Docker image (Debian-based) containing Terraform (or OpenTofu), dumb-init, rsync, bash, and ca-certificates. If your Terraform code requires additional binaries or tools (e.g., AWS CLI, kubectl, jq, custom scripts), you can customize the build image using a Dockerfile fragment.
Qovery provides two ways to inject custom Dockerfile commands during the build:
File-based: Reference a Dockerfile fragment file stored in your Git repository
Inline: Provide Dockerfile commands directly in the service configuration
File-based Fragment
Inline Fragment
Reference a Dockerfile fragment file from your repository.
1
Create Fragment File
In your Git repository, create a Dockerfile fragment file in your Terraform code directory or a custom location.Example directory structure:
my-repo/├── terraform/│ ├── main.tf│ ├── variables.tf│ └── custom-build.dockerfile # Your fragment file└── README.md
2
Add Dockerfile Instructions
Add valid Dockerfile instructions to install the tools you need. The fragment is injected into the build after your Terraform files are copied and before the final user switch.See the Fragment Examples section below for common use cases.
3
Configure Service
In the Terraform service settings, configure the Dockerfile fragment:
Navigate to Service Settings → Dockerfile Fragment
Select Custom file path
Enter the absolute path to your fragment file (e.g., /terraform/custom-build.dockerfile)
The path must be absolute (starting with /) and located within your service’s root_path.
4
Deploy
Save your changes and deploy. Qovery will inject the fragment contents during the Docker build.
Define Dockerfile commands directly in the service configuration without creating a file in your repository.
1
Configure Service
In the Terraform service settings:
Navigate to Service Settings → Dockerfile Fragment
# Install kubectl (curl is already available in the base image)RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \ chmod +x kubectl && \ mv kubectl /usr/local/bin/
Installing a custom binary from your repository:
# Install a custom tool already present in the repository# (repository files are already copied to /data)RUN cp /data/bin/my-custom-tool /usr/local/bin/my-custom-tool && \ chmod +x /usr/local/bin/my-custom-tool
Downloading and extracting a remote archive:
# Download and extract a tool from the internetADD https://releases.example.com/tool-v1.2.3.tar.gz /tmp/tool.tar.gzRUN tar -xzf /tmp/tool.tar.gz -C /usr/local/bin/ && \ rm /tmp/tool.tar.gz
The fragment supports the following Dockerfile instructions:
RUN - Execute commands during build (install packages, configure tools, etc.)
ADD - Add files with URL/archive support (download and extract remote archives)
Repository files are already present in /data before the fragment executes, so you can reference them in RUN commands without needing COPY.
The fragment runs as root during the build. The container switches to a non-root user (app) after your fragment executes. Make sure any binaries you install are accessible to all users.
This feature is specific to Terraform and OpenTofu services. Applications and Jobs use different build mechanisms.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Qovery","colors":{"primary":"#642DFF","light":"#D8CBFF","dark":"#151B2B"},"logo":{"light":"https://mintcdn.com/qovery/Nvnl0g5BHzA0XQmy/images/logos/qovery-logo-black.svg?fit=max\u0026auto=format\u0026n=Nvnl0g5BHzA0XQmy\u0026q=85\u0026s=fd1a292f8293eb3cf8763f75af6ee9d4","dark":"https://mintcdn.com/qovery/Nvnl0g5BHzA0XQmy/images/logos/qovery-logo-white.svg?fit=max\u0026auto=format\u0026n=Nvnl0g5BHzA0XQmy\u0026q=85\u0026s=93dca33bf2171e9faadba09595bdf80b"},"favicon":"https://mintcdn.com/qovery/ppnp94_itg1qC8g_/favicon.svg?fit=max\u0026auto=format\u0026n=ppnp94_itg1qC8g_\u0026q=85\u0026s=e0709ea668cbf2f32d1159fa6c2b136d","navbar":{"links":[{"icon":"github","href":"https://github.com/Qovery","label":"GitHub"}],"primary":{"type":"button","label":"Console","href":"https://console.qovery.com"}},"footer":{"links":[{"items":[{"label":"Pricing","href":"https://www.qovery.com/pricing"},{"label":"Changelog","href":"https://www.qovery.com/changelog"},{"label":"Roadmap","href":"https://roadmap.qovery.com/en/roadmap"},{"label":"Case Studies","href":"https://www.qovery.com/case-studies"}]},{"items":[{"label":"Documentation","href":"https://qovery.com/docs"},{"label":"Blog","href":"https://www.qovery.com/blog"},{"label":"GitHub","href":"https://github.com/Qovery"},{"label":"Changelog","href":"https://www.qovery.com/changelog"},{"label":"Replibyte","href":"https://www.replibyte.com"}]},{"items":[{"label":"Contact","href":"https://www.qovery.com/contact"},{"label":"Security","href":"https://trust.qovery.com"},{"label":"Terms","href":"https://www.qovery.com/terms-of-service"},{"label":"Privacy Policy","href":"https://www.qovery.com/private-policy"}]}]},"integrations":{"posthog":{"apiKey":"phc_IgdG1K2GveDUte1gJ6hlwNbFHCv9nViWETUyLMU7ciq","apiHost":"https://e.qovery.com","sessionRecording":true}},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"qovery","hasAudioNarration":false,"actualSubdomain":"qovery","customDomains":["www.qovery.com"],"gitSource":{"type":"github","owner":"qovery","repo":"documentation","deployBranch":"main","contentDirectory":"docs","isPrivate":false,"mountPath":"","label":""},"feedback":{"thumbs":true,"issues":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6aedd5a17d3fe39d4f38ac9a","clientVersion":"0.0.4087","searchFilterCounts":[{"language":"default","tag":"API Reference","count":575},{"language":"default","tag":"Configuration","count":88},{"language":"default","tag":"Getting Started","count":69},{"language":"default","tag":"Clusters","count":38},{"language":"default","tag":"CLI","count":33},{"language":"default","tag":"Commands","count":31},{"language":"default","tag":"Cloud Provider Credentials","count":25},{"language":"default","tag":"Organization Main Calls","count":22},{"language":"default","tag":"Tutorials","count":21},{"language":"default","tag":"Advanced Tutorials","count":18}]},"assistantConfig":{},"basePath":"/docs","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"custom.css","content":".logo img,[class*=\"Logo\"] img,header img[alt*=\"logo\"i]{max-height:40px!important;height:40px!important;width:auto!important}header nav a,header a[href],[class*=\"topbar\"] a{color:inherit!important;text-decoration:none!important}#topbar-cta-button a span.bg-primary-dark{background-color:#642dff!important}html[class*=\"dark\"] #topbar-cta-button a span.bg-primary-dark,html[data-theme=\"dark\"] #topbar-cta-button a span.bg-primary-dark,.dark #topbar-cta-button a span.bg-primary-dark{background-color:#d8cbff!important}html[class*=\"dark\"] #topbar-cta-button a span.text-white,html[data-theme=\"dark\"] #topbar-cta-button a span.text-white,.dark #topbar-cta-button a span.text-white{color:#151b2b!important}html[class*=\"dark\"] #topbar-cta-button a svg,html[data-theme=\"dark\"] #topbar-cta-button a svg,.dark #topbar-cta-button a svg{color:#151b2b!important}#topbar-cta-button a div span.text-white::before{content:\"\"!important;display:inline-block!important;width:16px!important;height:16px!important;margin-right:6px!important;background-image:url('data:image/svg+xml,\u003csvg width=\"84\" height=\"96\" viewBox=\"0 0 84 96\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\u003cpath d=\"M80.3554 21.4078L45.5514 1.31333C43.3963 0.0687351 40.7428 0.0687351 38.5906 1.31333L3.78655 21.4078C1.63427 22.6496 0.306152 24.9494 0.306152 27.4358V67.6247C0.306152 70.1111 1.63149 72.4082 3.78655 73.6528L42.071 95.7575V73.6528C42.071 72.4082 42.7336 71.261 43.8112 70.6373L62.9534 59.5864V83.6986L80.3554 73.6528C82.5104 72.4082 83.8358 70.1111 83.8358 67.6247V27.4358C83.8358 24.9494 82.5104 22.6524 80.3554 21.4078ZM40.3308 48.5354L21.1886 59.5864V37.4816C21.1886 36.2371 21.8512 35.0899 22.9288 34.4662L40.3308 24.4204C41.4083 23.7995 42.7336 23.7995 43.8112 24.4204L61.2132 34.4662C62.2907 35.0871 62.9534 36.2371 62.9534 37.4816V59.5864L43.8112 48.5354C42.7336 47.9145 41.4083 47.9145 40.3308 48.5354Z\" fill=\"white\"/>\u003c/svg>')!important;background-size:contain!important;background-repeat:no-repeat!important;background-position:center!important;vertical-align:text-bottom!important;transform:translateY(-1px)!important}html[class*=\"dark\"] #topbar-cta-button a div span.text-white::before,html[data-theme=\"dark\"] #topbar-cta-button a div span.text-white::before,.dark #topbar-cta-button a div span.text-white::before{background-image:url('data:image/svg+xml,\u003csvg width=\"84\" height=\"96\" viewBox=\"0 0 84 96\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\u003cpath d=\"M80.3554 21.4078L45.5514 1.31333C43.3963 0.0687351 40.7428 0.0687351 38.5906 1.31333L3.78655 21.4078C1.63427 22.6496 0.306152 24.9494 0.306152 27.4358V67.6247C0.306152 70.1111 1.63149 72.4082 3.78655 73.6528L42.071 95.7575V73.6528C42.071 72.4082 42.7336 71.261 43.8112 70.6373L62.9534 59.5864V83.6986L80.3554 73.6528C82.5104 72.4082 83.8358 70.1111 83.8358 67.6247V27.4358C83.8358 24.9494 82.5104 22.6524 80.3554 21.4078ZM40.3308 48.5354L21.1886 59.5864V37.4816C21.1886 36.2371 21.8512 35.0899 22.9288 34.4662L40.3308 24.4204C41.4083 23.7995 42.7336 23.7995 43.8112 24.4204L61.2132 34.4662C62.2907 35.0871 62.9534 36.2371 62.9534 37.4816V59.5864L43.8112 48.5354C42.7336 47.9145 41.4083 47.9145 40.3308 48.5354Z\" fill=\"%23151B2B\"/>\u003c/svg>')!important}[data-page-mode=\"custom\"] main,[data-page-mode=\"custom\"] article,html[data-page-mode=\"custom\"] main>div,html[data-page-mode=\"custom\"] article>div{max-width:1280px!important;margin-left:auto!important;margin-right:auto!important;padding-left:2rem!important;padding-right:2rem!important;box-sizing:border-box!important}.card-icon img,.card img[src*=\"/logos/\"]{max-width:24px!important;max-height:24px!important;width:24px!important;height:24px!important;background:transparent!important}[class*=\"CardIcon\"] img,[class*=\"card-icon\"] img{max-width:24px!important;max-height:24px!important;object-fit:contain!important;background:transparent!important}img[src*=\"/scaleway-icon\"],[class*=\"Card\"] img[src*=\"/scaleway-icon\"]{max-width:24px!important;max-height:24px!important;width:auto!important;height:24px!important;object-fit:contain!important}html[class*=\"dark\"] .card-icon,html[data-theme=\"dark\"] .card-icon,html[class*=\"dark\"] [class*=\"CardIcon\"],html[data-theme=\"dark\"] [class*=\"CardIcon\"]{background:transparent!important;background-color:transparent!important}[class*=\"Card\"] img[src*=\"logo\"],.card img[src*=\"logo\"],img[src*=\"/logos/\"]{background:transparent!important;mix-blend-mode:normal!important}.card{display:flex!important;flex-direction:column!important;align-items:flex-start!important}.card-icon{margin-bottom:12px!important}html[class*=\"dark\"] .light-mode-only,html[data-theme=\"dark\"] .light-mode-only{display:none!important}html[class*=\"light\"] .dark-mode-only,html[data-theme=\"light\"] .dark-mode-only,html:not([class*=\"dark\"]):not([data-theme=\"dark\"]) .dark-mode-only{display:none!important}.badge-icon{display:inline-block;height:20px;max-height:20px;width:auto;margin-left:8px;vertical-align:middle;object-fit:contain}img[src*=\"/scaleway-icon\"].badge-icon,img[alt=\"Scaleway\"].badge-icon{height:20px!important;max-height:20px!important;width:auto!important;object-fit:contain!important}.raci-legend{display:flex;gap:1.5rem;margin-bottom:1.5rem;flex-wrap:wrap;padding:1rem;background-color:rgba(100, 45, 255, 0.05);border-radius:8px;border-left:4px solid #642dff}.raci-legend div{font-size:0.9rem}.role-r-text{color:#dc2626;font-weight:600}.role-a-text{color:#2563eb;font-weight:600}.role-c-text{color:#16a34a;font-weight:600}.role-i-text{color:#9333ea;font-weight:600}.raci-table-container{overflow-x:auto;margin:2rem 0;width:100%}table.raci-matrix{width:100%;min-width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0;border:1px solid #e5e7eb;border-radius:8px;overflow:hidden}table.raci-matrix .col-component{width:50%}table.raci-matrix .col-provider,table.raci-matrix .col-qovery,table.raci-matrix .col-customer{width:16.66%}table.raci-matrix th{background-color:#642dff;color:white;font-weight:600;padding:12px;text-align:center;border-bottom:2px solid #5527cc}table.raci-matrix th:first-child{text-align:left}table.raci-matrix tbody tr:hover{background-color:rgba(100, 45, 255, 0.05)}table.raci-matrix tr.layer-header td{background-color:#f3f4f6;font-weight:700;font-size:0.95rem;padding:10px 12px;color:#1f2937;border-top:2px solid #d1d5db;border-bottom:1px solid #d1d5db}table.raci-matrix td{padding:12px;border-bottom:1px solid #e5e7eb;text-align:center}table.raci-matrix td:first-child{text-align:left;font-weight:500}table.raci-matrix .role-ra{background-color:#fee2e2;color:#991b1b;font-weight:700}table.raci-matrix .role-r{background-color:#fef2f2;color:#dc2626;font-weight:600}table.raci-matrix .role-a{background-color:#dbeafe;color:#1e40af;font-weight:600}table.raci-matrix .role-c{background-color:#dcfce7;color:#15803d;font-weight:600}table.raci-matrix .role-i{background-color:#f3e8ff;color:#7c3aed;font-weight:600}table.raci-matrix .role-ci{background-color:#d1fae5;color:#065f46;font-weight:600}.vpc-tooltip-container{position:relative}.info-icon{display:inline-block;width:16px;height:16px;background-color:#642dff;color:white;border-radius:50%;text-align:center;font-size:12px;font-weight:bold;margin-left:6px;cursor:help}.vpc-tooltip{display:none;position:absolute;bottom:100%;left:0;background-color:#1f2937;color:white;padding:12px;border-radius:6px;width:300px;font-size:0.85rem;line-height:1.5;z-index:1000;box-shadow:0 4px 6px -1px rgba(0, 0, 0, 0.1)}.vpc-tooltip-container:hover .vpc-tooltip{display:block}.vpc-tooltip p{margin:0 0 8px 0}.vpc-tooltip p:last-child{margin-bottom:0}html[data-theme=\"dark\"] table.raci-matrix{border-color:#374151}html[data-theme=\"dark\"] table.raci-matrix th{background-color:#642dff;border-bottom-color:#5527cc}html[data-theme=\"dark\"] table.raci-matrix td{border-bottom-color:#374151}html[data-theme=\"dark\"] table.raci-matrix tr.layer-header td{background-color:#1f2937;color:#f9fafb;border-top-color:#4b5563;border-bottom-color:#4b5563}html[data-theme=\"dark\"] .raci-legend{background-color:rgba(100, 45, 255, 0.1)}.badge-icon-scaleway-light{display:inline-block;height:20px;max-height:20px;width:20px;max-width:20px;margin-left:8px;vertical-align:middle;object-fit:contain}.badge-icon-scaleway-dark{display:none;height:20px;max-height:20px;width:20px;max-width:20px;margin-left:8px;vertical-align:middle;object-fit:contain}html[class*=\"dark\"] .badge-icon-scaleway-light,html[data-theme=\"dark\"] .badge-icon-scaleway-light{display:none}html[class*=\"dark\"] .badge-icon-scaleway-dark,html[data-theme=\"dark\"] .badge-icon-scaleway-dark{display:inline-block}.badge-aws,.badge-gcp,.badge-azure,.badge-scw,.badge-app,.badge-container,.badge-cronjob,.badge-job,.badge-helm,.badge-new{display:inline-block;padding:3px 8px;border-radius:4px;font-size:11px;font-weight:600;color:white;margin-right:8px;margin-bottom:4px;white-space:nowrap;line-height:1.4;vertical-align:middle}.badge-aws{background-color:#ff9900}.badge-gcp{background-color:#ea4335}.badge-azure{background-color:#0089d6}.badge-scw{background-color:#4f0599}.badge-app{background-color:#10b981}.badge-container{background-color:#3b82f6}.badge-cronjob{background-color:#f59e0b}.badge-job{background-color:#8b5cf6}.badge-helm{background-color:#0f1689}.badge-new{background-color:#642DFF}.badge-terraform{background-color:#4040b2}.helm-icon{display:inline-block;height:20px;width:auto;margin-right:8px;margin-bottom:4px;vertical-align:middle}.terraform-icon{display:inline-block;height:20px;width:auto;margin-right:8px;margin-bottom:4px;vertical-align:middle}img[src*=\"/terraform-icon.svg\"],img[src*=\"/helm-icon.svg\"],img[src*=\"/aws-icon.svg\"],img[src*=\"/github-icon.svg\"]{}html[class*=\"dark\"] img[src*=\"/terraform-icon.svg\"],html[data-theme=\"dark\"] img[src*=\"/terraform-icon.svg\"],.dark img[src*=\"/terraform-icon.svg\"]{filter:brightness(0) saturate(100%) invert(92%) sepia(8%) saturate(1299%)\n hue-rotate(202deg) brightness(103%) contrast(100%)}html[class*=\"dark\"] img[src*=\"/helm-icon.svg\"],html[data-theme=\"dark\"] img[src*=\"/helm-icon.svg\"],.dark img[src*=\"/helm-icon.svg\"],html[class*=\"dark\"] img[src*=\"/helm-icon-light.svg\"],html[data-theme=\"dark\"] img[src*=\"/helm-icon-light.svg\"],.dark img[src*=\"/helm-icon-light.svg\"]{filter:brightness(0) invert(1)}html[class*=\"dark\"] img[src*=\"/aws-icon.svg\"],html[data-theme=\"dark\"] img[src*=\"/aws-icon.svg\"],.dark img[src*=\"/aws-icon.svg\"]{filter:brightness(0) invert(1)}html[class*=\"dark\"] img[src*=\"/github-icon.svg\"],html[data-theme=\"dark\"] img[src*=\"/github-icon.svg\"],.dark img[src*=\"/github-icon.svg\"]{filter:brightness(0) invert(1)}html[class*=\"dark\"] img[src*=\"/scaleway-icon-light.svg\"],html[data-theme=\"dark\"] img[src*=\"/scaleway-icon-light.svg\"],.dark img[src*=\"/scaleway-icon-light.svg\"]{filter:brightness(0) saturate(100%) invert(92%) sepia(8%) saturate(1299%)\n hue-rotate(202deg) brightness(103%) contrast(100%)}html[class*=\"dark\"] img[src*=\"/logos/provision-logo-only.svg\"],html[data-theme=\"dark\"] img[src*=\"/logos/provision-logo-only.svg\"],.dark img[src*=\"/logos/provision-logo-only.svg\"]{filter:brightness(0) saturate(100%) invert(92%) sepia(8%) saturate(1299%)\n hue-rotate(202deg) brightness(103%) contrast(100%)}html[class*=\"dark\"] img[src*=\"/logos/deploy-logo-only.svg\"],html[data-theme=\"dark\"] img[src*=\"/logos/deploy-logo-only.svg\"],.dark img[src*=\"/logos/deploy-logo-only.svg\"]{filter:brightness(0) saturate(100%) invert(92%) sepia(8%) saturate(1299%)\n hue-rotate(202deg) brightness(103%) contrast(100%)}html[class*=\"dark\"] img[src*=\"/logos/observe-logo-only.svg\"],html[data-theme=\"dark\"] img[src*=\"/logos/observe-logo-only.svg\"],.dark img[src*=\"/logos/observe-logo-only.svg\"]{filter:brightness(0) saturate(100%) invert(92%) sepia(8%) saturate(1299%)\n hue-rotate(202deg) brightness(103%) contrast(100%)}html[class*=\"dark\"] img[src*=\"/logos/optimize-logo-only.svg\"],html[data-theme=\"dark\"] img[src*=\"/logos/optimize-logo-only.svg\"],.dark img[src*=\"/logos/optimize-logo-only.svg\"]{filter:brightness(0) saturate(100%) invert(92%) sepia(8%) saturate(1299%)\n hue-rotate(202deg) brightness(103%) contrast(100%)}html[class*=\"dark\"] img[src*=\"/logos/secure-logo-only.svg\"],html[data-theme=\"dark\"] img[src*=\"/logos/secure-logo-only.svg\"],.dark img[src*=\"/logos/secure-logo-only.svg\"]{filter:brightness(0) saturate(100%) invert(92%) sepia(8%) saturate(1299%)\n hue-rotate(202deg) brightness(103%) contrast(100%)}html[class*=\"dark\"] img[src*=\"/ai-tools/cursor.svg\"],html[data-theme=\"dark\"] img[src*=\"/ai-tools/cursor.svg\"],html[class*=\"dark\"] img[src*=\"/ai-tools/githubcopilot.svg\"],html[data-theme=\"dark\"] img[src*=\"/ai-tools/githubcopilot.svg\"],html[class*=\"dark\"] img[src*=\"/ai-tools/amp.svg\"],html[data-theme=\"dark\"] img[src*=\"/ai-tools/amp.svg\"],html[class*=\"dark\"] img[src*=\"/ai-tools/openai.svg\"],html[data-theme=\"dark\"] img[src*=\"/ai-tools/openai.svg\"],html[class*=\"dark\"] img[src*=\"/ai-tools/goose.png\"],html[data-theme=\"dark\"] img[src*=\"/ai-tools/goose.png\"]{filter:brightness(0) invert(1)}.terminal-window{background:#0d1117;border-radius:10px;overflow:hidden;margin:16px 0 24px;box-shadow:0 4px 24px rgba(0, 0, 0, 0.25)}.terminal-bar{background:#161b22;padding:10px 16px;display:flex;align-items:center;border-bottom:1px solid #21262d}.terminal-dots{display:flex;gap:6px;margin-right:12px}.terminal-dot{width:12px;height:12px;border-radius:50%;flex-shrink:0}.terminal-dot-red{background:#ff5f57}.terminal-dot-yellow{background:#febc2e}.terminal-dot-green{background:#28c840}.terminal-title-bar{flex:1;text-align:center;color:#6e7681;font-size:12px;font-family:'Roboto Mono', monospace}.terminal-copy{background:transparent;border:none;color:#6e7681;cursor:pointer;padding:4px 6px;border-radius:4px;display:flex;align-items:center;transition:color 0.15s, background 0.15s;flex-shrink:0}.terminal-copy:hover{color:#e6edf3;background:rgba(255, 255, 255, 0.08)}.terminal-copy-success{color:#3fb950!important}.terminal-body{padding:20px 24px;font-family:'Roboto Mono', monospace;font-size:13px;line-height:1.8;color:#e6edf3}.terminal-prompt{display:block;margin:4px 0}.terminal-prompt::before{content:'$ ';color:#642DFF;font-weight:700}.terminal-output{display:block;color:#8b949e;padding-left:14px;margin:2px 0}.terminal-success{display:block;color:#3fb950;padding-left:14px;margin:2px 0}.terminal-sep{border:none;border-top:1px solid #21262d;margin:14px 0}@keyframes blink-cursor{0%,50%{opacity:1}51%,100%{opacity:0}}.terminal-cursor{display:inline-block;width:7px;height:13px;background:#e6edf3;animation:blink-cursor 1s step-end infinite;vertical-align:text-bottom;margin-left:2px}.skill-radio{position:absolute;opacity:0;pointer-events:none;width:0;height:0}.skills-grid{display:grid;grid-template-columns:repeat(4, 1fr);gap:8px;margin-bottom:16px}@media (max-width: 640px){.skills-grid{grid-template-columns:repeat(2, 1fr)}}.skill-card{padding:12px 14px;border:1px solid #e5e7eb;border-radius:8px;cursor:pointer;transition:border-color 0.15s, background 0.15s;display:flex;flex-direction:column;gap:3px;user-select:none}html.dark .skill-card,html[data-theme=\"dark\"] .skill-card{border-color:rgba(255, 255, 255, 0.1)}.skill-card:hover{border-color:rgba(100, 45, 255, 0.5);background:rgba(100, 45, 255, 0.05)}.skill-card-name{font-size:12px;font-weight:600;color:#111827;font-family:'Roboto Mono', monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}html.dark .skill-card-name,html[data-theme=\"dark\"] .skill-card-name{color:#e6edf3}.skill-card-desc{font-size:11px;color:#6b7280;line-height:1.35}html.dark .skill-card-desc,html[data-theme=\"dark\"] .skill-card-desc{color:#8b949e}#sk-onboard:checked~.skills-grid label[for=\"sk-onboard\"],#sk-deploy:checked~.skills-grid label[for=\"sk-deploy\"],#sk-troubleshoot:checked~.skills-grid label[for=\"sk-troubleshoot\"],#sk-optimize:checked~.skills-grid label[for=\"sk-optimize\"],#sk-speedup:checked~.skills-grid label[for=\"sk-speedup\"],#sk-preview:checked~.skills-grid label[for=\"sk-preview\"],#sk-builder-env:checked~.skills-grid label[for=\"sk-builder-env\"],#sk-builder-portal:checked~.skills-grid label[for=\"sk-builder-portal\"]{border-color:#642DFF;background:rgba(100, 45, 255, 0.1)}.skills-desc-wrap{padding:12px 14px;min-height:44px;font-size:13.5px;color:#374151;line-height:1.6;border-left:3px solid #642DFF;background:rgba(100, 45, 255, 0.04);border-radius:0 6px 6px 0;margin-bottom:12px}html.dark .skills-desc-wrap,html[data-theme=\"dark\"] .skills-desc-wrap{color:#c9d1d9;background:rgba(100, 45, 255, 0.08)}.sk-desc{display:none}#sk-onboard:checked~.skills-desc-wrap .sk-desc-onboard{display:block}#sk-deploy:checked~.skills-desc-wrap .sk-desc-deploy{display:block}#sk-troubleshoot:checked~.skills-desc-wrap .sk-desc-troubleshoot{display:block}#sk-optimize:checked~.skills-desc-wrap .sk-desc-optimize{display:block}#sk-speedup:checked~.skills-desc-wrap .sk-desc-speedup{display:block}#sk-preview:checked~.skills-desc-wrap .sk-desc-preview{display:block}#sk-builder-env:checked~.skills-desc-wrap .sk-desc-builder-env{display:block}#sk-builder-portal:checked~.skills-desc-wrap .sk-desc-builder-portal{display:block}.sk-prompt{display:none}#sk-onboard:checked~.skills-terminal .sk-prompt-onboard{display:block}#sk-deploy:checked~.skills-terminal .sk-prompt-deploy{display:block}#sk-troubleshoot:checked~.skills-terminal .sk-prompt-troubleshoot{display:block}#sk-optimize:checked~.skills-terminal .sk-prompt-optimize{display:block}#sk-speedup:checked~.skills-terminal .sk-prompt-speedup{display:block}#sk-preview:checked~.skills-terminal .sk-prompt-preview{display:block}#sk-builder-env:checked~.skills-terminal .sk-prompt-builder-env{display:block}#sk-builder-portal:checked~.skills-terminal .sk-prompt-builder-portal{display:block}.terminal-actions{display:flex;align-items:center;gap:6px;margin-left:auto}.terminal-open-cursor{display:flex;align-items:center;gap:5px;background:#2a2a2e;border:1px solid rgba(255, 255, 255, 0.1);color:#ffffff;font-size:11px;font-weight:500;padding:3px 8px;border-radius:5px;cursor:pointer;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;transition:background 0.15s;white-space:nowrap;text-decoration:none;line-height:1}.terminal-open-cursor:hover{background:#3a3a3e}.compare-table{width:100%;border-collapse:collapse;font-size:14px;margin:16px 0}.compare-table thead th{padding:8px 16px 12px;text-align:left;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#6b7280;border-bottom:1px solid #e5e7eb}html.dark .compare-table thead th,html[data-theme=\"dark\"] .compare-table thead th{color:#6e7681;border-bottom-color:#21262d}.compare-table thead th.col-featured{color:#642DFF!important}.compare-table tbody td{padding:12px 16px;border-bottom:1px solid #f3f4f6;font-size:13.5px;vertical-align:middle;color:#374151}html.dark .compare-table tbody td,html[data-theme=\"dark\"] .compare-table tbody td{border-bottom-color:rgba(255,255,255,0.06);color:#c9d1d9}.compare-table tbody td:first-child{font-weight:600;color:#111827}html.dark .compare-table tbody td:first-child,html[data-theme=\"dark\"] .compare-table tbody td:first-child{color:#e6edf3}.compare-table tbody td.col-featured{background:rgba(100, 45, 255, 0.05)}html.dark .compare-table tbody td.col-featured,html[data-theme=\"dark\"] .compare-table tbody td.col-featured{background:rgba(100, 45, 255, 0.09)}.cmp-yes{color:#16a34a;font-weight:500}.cmp-no{color:#9ca3af}.cmp-auto{color:#7c3aed;font-weight:500}html.dark .cmp-yes{color:#3fb950}html.dark .cmp-no,html[data-theme=\"dark\"] .cmp-no{color:#6e7681}html.dark .cmp-auto,html[data-theme=\"dark\"] .cmp-auto{color:#a78bfa}.ai-section{background:linear-gradient(135deg, rgba(100, 45, 255, 0.09) 0%, rgba(100, 45, 255, 0.03) 100%);border:1px solid rgba(100, 45, 255, 0.22);border-radius:16px;padding:28px 28px 20px;margin:8px 0 24px}.ai-section h3{margin-top:0!important}html[class*=\"dark\"] .ai-section,html[data-theme=\"dark\"] .ai-section{background:linear-gradient(135deg, rgba(100, 45, 255, 0.18) 0%, rgba(100, 45, 255, 0.06) 100%);border-color:rgba(100, 45, 255, 0.38)}article>h1:first-of-type,main>h1:first-of-type,[class*=\"Content\"]>h1:first-of-type{display:none!important}footer,[class*=\"footer\"],[class*=\"Footer\"]{margin-left:0!important;padding-left:0!important}@media (min-width: 768px){footer,[class*=\"footer\"],[class*=\"Footer\"]{position:relative!important;z-index:1!important}footer>div,[class*=\"footer\"]>div,[class*=\"Footer\"]>div{margin-left:260px!important;padding-left:2rem!important}}.cta-banner{background:linear-gradient(135deg, #642DFF 0%, #8B5CF6 100%);border-radius:16px;padding:28px 32px;margin:40px 0 8px;display:flex;align-items:center;justify-content:space-between;gap:20px}.cta-banner-text h3{color:#ffffff;font-size:18px;font-weight:700;margin:0 0 6px!important;line-height:1.3}.cta-banner-text p{color:rgba(255, 255, 255, 0.82);font-size:14px;margin:0!important;line-height:1.5}.cta-banner-button{display:inline-flex;align-items:center;gap:6px;background:#ffffff;color:#642DFF!important;font-weight:700;font-size:14px;padding:11px 22px;border-radius:8px;text-decoration:none!important;white-space:nowrap;flex-shrink:0;transition:opacity 0.15s, transform 0.15s}.cta-banner-button:hover{opacity:0.92;transform:translateY(-1px)}@media (max-width: 640px){.cta-banner{flex-direction:column;text-align:center;padding:24px 20px}.cta-banner-button{width:100%;justify-content:center}}a[href*=\"mintlify.com\"][href*=\"poweredBy\"]{display:none!important}"}],"page":{"pagePath":"configuration/terraform","slug":"/configuration/terraform","pageMetadata":{"title":"Terraform","description":"Deploy and manage Terraform modules natively on Qovery","href":"/configuration/terraform"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Deploy and manage Terraform modules natively on Qovery\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,hr:`hr`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Accordion,AccordionGroup,Card,CardGroup,CodeBlock,Frame,Heading,Info,OptimizedImage,Step,Steps,Tab,Tabs,Tip,Warning}=_components;if(!Accordion)_missingMdxReference(`Accordion`,true);if(!AccordionGroup)_missingMdxReference(`AccordionGroup`,true);if(!Card)_missingMdxReference(`Card`,true);if(!CardGroup)_missingMdxReference(`CardGroup`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Frame)_missingMdxReference(`Frame`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Info)_missingMdxReference(`Info`,true);if(!OptimizedImage)_missingMdxReference(`OptimizedImage`,true);if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);if(!Tab)_missingMdxReference(`Tab`,true);if(!Tabs)_missingMdxReference(`Tabs`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`introduction`,children:`Introduction`}),`\n`,_jsx(_components.p,{children:`Terraform Native Service enables you to deploy and manage Terraform or OpenTofu infrastructure code directly within Qovery. This service type allows you to provision cloud resources, configure external services, and manage infrastructure as code (IaC) using the same environment structure as your applications. Terraform executes within Kubernetes pods on your cluster, with automatic state management, variable injection, and integrated deployment workflows.`}),`\n`,_jsx(Info,{children:_jsxs(_components.p,{children:[`This page describes the Terraform service in the Console. To manage a Terraform service with the Qovery Terraform provider, use the `,_jsx(_components.a,{href:`https://registry.terraform.io/providers/qovery/qovery/latest/docs/resources/terraform_service`,children:_jsx(_components.code,{children:`qovery_terraform_service`})}),` resource.`]})}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`demo-deploy-s3-and-connect-to-qovery-services`,children:`Demo: Deploy S3 and Connect to Qovery Services`}),`\n`,_jsx(_components.p,{children:`Watch this interactive demo to see how to deploy S3 infrastructure using Terraform and connect it to services deployed with Qovery:`}),`\n`,_jsx(`video`,{src:`https://mintcdn.com/qovery/vCq_OBXVLhOatlD8/videos/Deploy_S3_Infrastructure_using_Terraform_with_Qovery.mp4?fit=max\u0026auto=format\u0026n=vCq_OBXVLhOatlD8\u0026q=85\u0026s=a700a4b86a9c2c3b504e7390cc750456`,controls:true,\"data-path\":`videos/Deploy_S3_Infrastructure_using_Terraform_with_Qovery.mp4`}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`creating-a-terraform-service`,children:`Creating a Terraform Service`}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Open Environment Overview`,children:_jsx(_components.p,{children:`Navigate to the environment where you want to deploy your Terraform infrastructure.`})}),_jsx(Step,{title:`Create New Service`,children:_jsxs(_components.p,{children:[`Click `,_jsx(_components.strong,{children:`New Service`}),` and select `,_jsx(_components.strong,{children:`Terraform`}),` from the service type options.`]})}),_jsx(Step,{title:`Configure Service Name`,children:_jsxs(_components.p,{children:[`Provide a `,_jsx(_components.strong,{children:`service name`}),` that identifies this Terraform service (e.g., `,_jsx(_components.code,{children:`aws-infrastructure`}),`, `,_jsx(_components.code,{children:`cloudflare-config`}),`).`]})}),_jsxs(Step,{title:`Select Git Repository`,children:[_jsxs(_components.p,{children:[`Choose the `,_jsx(_components.strong,{children:`Git repository`}),` containing your Terraform code. This repository must include your `,_jsx(_components.code,{children:`.tf`}),` configuration files.`]}),_jsxs(_components.p,{children:[`Specify the `,_jsx(_components.strong,{children:`branch`}),` and `,_jsx(_components.strong,{children:`root path`}),` if your Terraform code is in a subdirectory.`]})]}),_jsxs(Step,{title:`Select Engine`,children:[_jsx(_components.p,{children:`Choose the execution engine:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Terraform`}),` - Official HashiCorp Terraform`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`OpenTofu`}),` - Open-source Terraform fork`]}),`\n`]})]}),_jsx(Step,{title:`Select Terraform Version`,children:_jsxs(_components.p,{children:[`Choose the `,_jsx(_components.strong,{children:`Terraform version`}),` to use for execution. Supported versions depend on your selected engine.`]})}),_jsxs(Step,{title:`State Management`,children:[_jsx(_components.p,{children:`Configure how Terraform stores and manages state files. Qovery supports two state management modes.`}),_jsxs(Tabs,{children:[_jsxs(Tab,{title:`Default (Cluster-Managed)`,id:`default-cluster-managed`,children:[_jsxs(_components.p,{children:[`By default, Terraform `,_jsx(_components.strong,{children:`state is managed inside the Kubernetes cluster`}),`. State files are stored securely within the cluster and managed automatically by Qovery.`]}),_jsx(_components.p,{children:`This default configuration requires no additional setup and is ideal for getting started quickly.`}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Benefits:`})}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Zero configuration required`}),`\n`,_jsx(_components.li,{children:`Automatic state management`}),`\n`,_jsx(_components.li,{children:`Secure storage within your cluster`}),`\n`,_jsx(_components.li,{children:`No external dependencies`}),`\n`]})]}),_jsxs(Tab,{title:`Custom Backend (AWS S3)`,id:`custom-backend-aws-s3`,children:[_jsxs(_components.p,{children:[`If you prefer to manage your Terraform state in your own backend, you can configure a custom backend. `,_jsx(_components.strong,{children:`The standard for AWS is to use an S3 backend.`})]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Prerequisites`})}),_jsx(_components.p,{children:`Before configuring your S3 backend, you need to:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Create an S3 bucket`}),` in your AWS account to store the Terraform state`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Enable bucket versioning`}),` on your S3 bucket to allow state recovery in case of accidental deletions`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Configure S3 state locking`}),` using the `,_jsx(_components.code,{children:`use_lockfile`}),` option (this avoids the need for a DynamoDB table)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Prepare AWS credentials`}),` with appropriate permissions to access the S3 bucket`]}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Backend Configuration`})}),_jsxs(_components.p,{children:[`Add a backend configuration block to your `,_jsx(_components.code,{children:`main.tf`}),` file in your Git repository:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`hcl`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`hcl`,children:_jsxs(_components.code,{language:`hcl`,numberOfLines:`9`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:`terraform`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` backend`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` \"s3\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` bucket`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"my-terraform-backend\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` key`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"terraform.tfstate\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` region`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"eu-west-3\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` use_lockfile`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` true`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` encrypt`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` true`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Configuration parameters:`})}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`bucket`}),` - Name of your S3 bucket for storing state files`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`key`}),` - Path to the state file within the bucket (typically `,_jsx(_components.code,{children:`terraform.tfstate`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`region`}),` - AWS region where your S3 bucket is located`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`use_lockfile`}),` - Set to `,_jsx(_components.code,{children:`true`}),` to use S3’s native locking mechanism instead of DynamoDB (recommended)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`encrypt`}),` - Set to `,_jsx(_components.code,{children:`true`}),` to enable server-side encryption for the state file (recommended)`]}),`\n`]}),_jsx(Info,{children:_jsxs(_components.p,{children:[`Using `,_jsx(_components.code,{children:`use_lockfile = true`}),` eliminates the need to set up a DynamoDB table for state locking, simplifying your infrastructure. This is the recommended approach as DynamoDB-based locking is deprecated and will be removed in a future version of Terraform.`]})}),_jsxs(Tip,{children:[_jsx(_components.p,{children:_jsx(_components.strong,{children:`Best Practices:`})}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Enable `,_jsx(_components.strong,{children:`bucket versioning`}),` on your S3 bucket to allow state recovery in case of accidental deletions or corruption`]}),`\n`,_jsxs(_components.li,{children:[`Use `,_jsx(_components.code,{children:`encrypt = true`}),` to enable server-side encryption for your state files`]}),`\n`,_jsx(_components.li,{children:`Never hardcode sensitive values in your backend configuration`}),`\n`]})]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Configuring AWS Credentials`})}),_jsxs(_components.p,{children:[`To allow Terraform to access your S3 backend, you must provide AWS credentials as `,_jsx(_components.strong,{children:`environment variables`}),` in the service configuration:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`AWS_ACCESS_KEY_ID=AKIA...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`AWS_DEFAULT_REGION=eu-west-3`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(Tip,{children:_jsxs(_components.p,{children:[`Store these credentials as `,_jsx(_components.strong,{children:`Secrets`}),` in Qovery to ensure they are encrypted and never exposed in logs.`]})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Required IAM Permissions`})}),_jsx(_components.p,{children:`The AWS credentials must have the following IAM permissions on your S3 bucket:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`21`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`21`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Version\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"2012-10-17\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Statement\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Effect\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Allow\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"s3:ListBucket\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ],`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Resource\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"arn:aws:s3:::my-terraform-backend\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Effect\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Allow\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"s3:GetObject\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"s3:PutObject\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"s3:DeleteObject\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ],`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Resource\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"arn:aws:s3:::my-terraform-backend/*\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),_jsx(Info,{children:_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`s3:DeleteObject`}),` permission is required for managing the lock file when using `,_jsx(_components.code,{children:`use_lockfile = true`}),`.`]})}),_jsxs(Warning,{children:[_jsx(_components.p,{children:_jsx(_components.strong,{children:`Using Cluster Credentials with Custom Backend`})}),_jsxs(_components.p,{children:[`If you choose to use the default cluster credentials (instead of providing custom AWS credentials), be aware that the cluster’s IAM policy `,_jsxs(_components.strong,{children:[`only allows access to S3 buckets with names prefixed with `,_jsx(_components.code,{children:`qovery-`})]}),`.`]}),_jsx(_components.p,{children:`You have two options:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[`Name your bucket with the `,_jsx(_components.code,{children:`qovery-`}),` prefix`]}),` (e.g., `,_jsx(_components.code,{children:`qovery-my-terraform-backend`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Provide custom AWS credentials`}),` (recommended) with appropriate permissions for your bucket name`]}),`\n`]}),_jsx(_components.p,{children:`This restriction exists to prevent accidental access to unrelated S3 buckets in your AWS account.`})]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Migration from Default State`})}),_jsx(_components.p,{children:`If you’re migrating from the default cluster-managed state to a custom S3 backend:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Add the backend configuration to your `,_jsx(_components.code,{children:`main.tf`})]}),`\n`,_jsx(_components.li,{children:`Configure the AWS credentials as environment variables`}),`\n`,_jsxs(_components.li,{children:[`Use the `,_jsx(_components.strong,{children:`Migrate State`}),` action from the service’s Action Toolbar to transfer the existing state to your S3 bucket`]}),`\n`]})]})]})]}),_jsx(Step,{title:`Execution Timeout (Default)`,children:_jsxs(_components.p,{children:[`The default `,_jsx(_components.strong,{children:`timeout is set to 1 hour`}),`. This can be customized if your Terraform operations require more time.`]})}),_jsxs(Step,{title:`Cloud Credentials (Default Behavior)`,children:[_jsxs(_components.p,{children:[`By default, Terraform uses `,_jsx(_components.strong,{children:`cluster credentials`}),` when provisioning resources on the same cloud provider as your cluster.`]}),_jsxs(_components.p,{children:[`If you need to use `,_jsx(_components.strong,{children:`custom credentials`}),` (e.g., a different AWS account, GCP project, or Azure subscription), you will configure them in the Environment Variables step.`]})]}),_jsxs(Step,{title:`Compute Resources (Default)`,children:[_jsx(_components.p,{children:`Terraform execution uses the following default compute resources:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`CPU`}),`: 500 millicores (500 mCPU or 0.5 vCPU)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Memory`}),`: 256 MiB`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Storage`}),`: 5 GiB`]}),`\n`]}),_jsxs(_components.p,{children:[`These resources can be updated later in the `,_jsx(_components.strong,{children:`Service Settings`}),` if your Terraform operations require more capacity.`]}),_jsxs(_components.p,{children:[`These defaults, and the 1 hour timeout, apply to services created from the Console. The Terraform provider has its own defaults, listed on the `,_jsx(_components.a,{href:`https://registry.terraform.io/providers/qovery/qovery/latest/docs/resources/terraform_service`,children:_jsx(_components.code,{children:`qovery_terraform_service`})}),` resource page.`]})]}),_jsxs(Step,{title:`Configure Terraform Variables`,children:[_jsx(_components.p,{children:`Qovery provides comprehensive variable management for Terraform, automatically detecting variables from your code and allowing flexible configuration.`}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Automatic Variable Detection`})}),_jsx(_components.p,{children:`Qovery automatically loads variables from:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`main.tf`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`variables.tf`})}),`\n`]}),_jsxs(_components.p,{children:[`Variables detected by Qovery will appear prefixed with `,_jsx(_components.code,{children:`tf_var_`}),`.`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),_jsxs(_components.p,{children:[`If your `,_jsx(_components.code,{children:`variables.tf`}),` contains:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`hcl`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`hcl`,children:_jsxs(_components.code,{language:`hcl`,numberOfLines:`8`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:`variable`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` \"bucket_name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` type`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` string`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:`variable`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` \"environment\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` type`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` string`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` default`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"production\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),_jsx(_components.p,{children:`Qovery will create:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`tf_var_bucket_name`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`tf_var_environment`})}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Importing TFVAR Files`})}),_jsxs(_components.p,{children:[`You can import `,_jsx(_components.code,{children:`.tfvars`}),` files to configure multiple variables at once:`]}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Import TFVAR`})]}),`\n`,_jsx(_components.li,{children:`Select the TFVAR file(s) to import`}),`\n`,_jsx(_components.li,{children:`Choose which TFVAR files to apply`}),`\n`,_jsx(_components.li,{children:`Reorder the TFVAR files as needed`}),`\n`]}),_jsx(Info,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`The last TFVAR file applied wins.`}),` If multiple TFVAR files define the same variable, the value from the last file in the order takes precedence.`]})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Referencing Qovery Variables Inside a TFVAR File`})}),_jsxs(_components.p,{children:[`You can reference Qovery environment, project, and built-in variables directly inside a `,_jsx(_components.code,{children:`.tfvars`}),` file using the `,_jsx(_components.code,{children:`\"{{ VARIABLE_NAME }}\"`}),` syntax. The file stays in your git repository, and Qovery substitutes the references at deploy time against the variables of the environment being deployed.`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`hcl`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`hcl`,children:_jsxs(_components.code,{language:`hcl`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# .tfvars file kept in your git repository`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`auth0_client_id`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"{{ AUTH0_CLIENT_ID }}\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`auth0_client_secret`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"{{ AUTH0_CLIENT_SECRET }}\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`postgresql_admin_password`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"{{ POSTGRESQL_ADMIN_PASSWORD }}\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`region`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"eu-west-3\"`})]}),`\n`]})})}),_jsx(Info,{children:_jsxs(_components.p,{children:[`Use this pattern to keep one `,_jsx(_components.code,{children:`.tfvars`}),` template in source control while injecting sensitive or generated values (database credentials, infrastructure outputs from another service) from the matching Qovery environment.`]})}),_jsx(Warning,{children:_jsxs(_components.p,{children:[`Only the `,_jsx(_components.code,{children:`{{ VARIABLE_NAME }}`}),` form is interpolated. Other forms such as `,_jsx(_components.code,{children:\"${VAR}\"}),`, `,_jsx(_components.code,{children:\"${{VAR}}\"}),`, or a bare identifier `,_jsx(_components.code,{children:`VAR`}),` are treated as literals and passed to Terraform unchanged.\nQovery variables of type `,_jsx(_components.strong,{children:`File`}),` or `,_jsx(_components.strong,{children:`File External Secret`}),` cannot be inlined as a Terraform variable value and are left as literals if referenced. A reference to an `,_jsx(_components.strong,{children:`External Secret`}),` is resolved inside your cluster when the Terraform job starts: see `,_jsx(_components.a,{href:`/configuration/integrations/secret-managers/secret-manager-access#using-external-secrets-with-terraform-services`,children:`Using external secrets with Terraform services`}),`.\nIf a referenced Qovery variable does not exist, the literal `,_jsx(_components.code,{children:`{{ NAME }}`}),` is passed through unchanged. Define the variable in your environment to have it substituted.`]})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Manual Variable Override`})}),_jsx(_components.p,{children:`You can manually override any variable value in two ways:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Direct Value Entry`}),` - Enter a value directly:`,`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`tf_var_bucket_name = \"my-custom-bucket\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Reference Environment Variable`}),` - Reference another environment variable:`,`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:\"tf_var_bucket_name = ${MY_BUCKET_NAME}\"})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`]}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Variables Not in main.tf or variables.tf`})}),_jsxs(_components.p,{children:[`If you have variables defined in other `,_jsx(_components.code,{children:`.tf`}),` files that are not in `,_jsx(_components.code,{children:`main.tf`}),` or `,_jsx(_components.code,{children:`variables.tf`}),`, Qovery will not automatically detect them. You can create these variables manually using the `,_jsx(_components.code,{children:`tf_var_`}),` prefix:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`tf_var_my_custom_variable = \"value\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-variables-configuration.png?fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=f065ca14fdd7ce7dacbea987ea80817a`,alt:`Configure Terraform Variables`,\"data-og-width\":`3164`,width:`3164`,\"data-og-height\":`2070`,height:`2070`,\"data-path\":`images/configuration/terraform/terraform-variables-configuration.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-variables-configuration.png?w=280\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=fd0d6127d2e0f3a9fb1699092f415c5b 280w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-variables-configuration.png?w=560\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=16154ec86f7654063989394290cc5131 560w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-variables-configuration.png?w=840\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=e8a5a4628ec5777a92d844ee0b8371a4 840w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-variables-configuration.png?w=1100\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=0b7e2ddfdc4f80355eac4fdb9754b06b 1100w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-variables-configuration.png?w=1650\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=1dbd4d01df3433a64510bfa79b7c52f4 1650w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-variables-configuration.png?w=2500\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=1fe6d1543416e54cac40ea2b7760a036 2500w`})})]}),_jsxs(Step,{title:`Configure Environment Variables`,children:[_jsx(_components.p,{children:`Add standard environment variables that will be available during Terraform execution. This is where you configure custom cloud provider credentials, provider-specific settings, and other configuration.`}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Common use cases:`})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Custom Cloud Credentials`})}),_jsx(_components.p,{children:`Override the default cluster credentials with your own:`}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`AWS:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`AWS_ACCESS_KEY_ID=AKIA...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`AWS_SECRET_ACCESS_KEY=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`AWS_DEFAULT_REGION=us-east-1`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`GCP:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`GOOGLE_CREDENTIALS={\"type\":\"service_account\",...}`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`GOOGLE_PROJECT=my-project-id`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`GOOGLE_REGION=us-central1`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Azure:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`ARM_CLIENT_ID=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`ARM_CLIENT_SECRET=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`ARM_SUBSCRIPTION_ID=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`ARM_TENANT_ID=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Provider Configuration`})}),_jsx(_components.p,{children:`Add provider-specific environment variables:`}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Cloudflare:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`CLOUDFLARE_API_TOKEN=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`CLOUDFLARE_ZONE_ID=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Datadog:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`DATADOG_API_KEY=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`DATADOG_APP_KEY=...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(Tip,{children:_jsxs(_components.p,{children:[`Use Qovery `,_jsx(_components.strong,{children:`Secrets`}),` for sensitive credentials to ensure they are encrypted and never exposed in logs.`]})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Terraform Environment Variables`})}),_jsx(_components.p,{children:`You can also set Terraform-specific environment variables:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`TF_LOG=DEBUG`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`TF_WORKSPACE=production`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]}),_jsxs(Step,{title:`Review and Create`,children:[_jsxs(_components.p,{children:[`Review your configuration and click `,_jsx(_components.strong,{children:`Create`}),` to provision the Terraform service.`]}),_jsxs(_components.p,{children:[`Optionally, you can select `,_jsx(_components.strong,{children:`Create \u0026 Run Plan`}),` to execute `,_jsx(_components.code,{children:`terraform plan`}),` immediately and preview the execution plan before applying changes.`]})]})]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`running-terraform`,children:`Running Terraform`}),`\n`,_jsxs(_components.p,{children:[`After creating your Terraform service, you can execute Terraform commands using the `,_jsx(_components.strong,{children:`Action Toolbar`}),`.`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-action-menu.png?fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=6dd78ef769b3f60cf3e30bc36ea4eb5d`,alt:`Terraform Action Menu`,\"data-og-width\":`3164`,width:`3164`,\"data-og-height\":`2070`,height:`2070`,\"data-path\":`images/configuration/terraform/terraform-action-menu.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-action-menu.png?w=280\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=f5df6652b3f7e386593be64082caf990 280w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-action-menu.png?w=560\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=40c4e01a98471ae7515b9a27ac1de549 560w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-action-menu.png?w=840\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=64b343e72b8be993af866375124c65f3 840w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-action-menu.png?w=1100\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=35f3b9752965922297b223205af16300 1100w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-action-menu.png?w=1650\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=8a6ccf6b3e2a6c8a0895e4cb629959e2 1650w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-action-menu.png?w=2500\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=f4531e93508bb84063b5f0e7039beb5f 2500w`})}),`\n`,_jsx(Heading,{level:`3`,id:`available-actions`,children:`Available Actions`}),`\n`,_jsx(_components.p,{children:`The following Terraform operations are available from the service’s Action Toolbar:`}),`\n`,_jsxs(AccordionGroup,{children:[_jsxs(Accordion,{title:`Plan`,id:`plan`,children:[_jsxs(_components.p,{children:[`Executes `,_jsx(_components.code,{children:`terraform plan`}),` to preview infrastructure changes without applying them.`]}),_jsx(_components.p,{children:`Use this to:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Review what Terraform will create, modify, or destroy`}),`\n`,_jsx(_components.li,{children:`Validate your Terraform configuration`}),`\n`,_jsx(_components.li,{children:`Check for drift between your code and actual infrastructure`}),`\n`]})]}),_jsxs(Accordion,{title:`Plan \u0026 Apply`,id:`plan-and-apply`,children:[_jsxs(_components.p,{children:[`Executes `,_jsx(_components.code,{children:`terraform plan`}),` followed by `,_jsx(_components.code,{children:`terraform apply`}),` to provision or update infrastructure.`]}),_jsx(_components.p,{children:`This is the standard deployment action that:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Generates an execution plan`}),`\n`,_jsx(_components.li,{children:`Applies changes to your infrastructure`}),`\n`,_jsx(_components.li,{children:`Updates the Terraform state`}),`\n`]})]}),_jsxs(Accordion,{title:`Destroy`,id:`destroy`,children:[_jsxs(_components.p,{children:[`Executes `,_jsx(_components.code,{children:`terraform destroy`}),` to remove all resources managed by this Terraform service.`]}),_jsx(Warning,{children:_jsxs(_components.p,{children:[`This action is `,_jsx(_components.strong,{children:`irreversible`}),` and will delete all infrastructure resources defined in your Terraform code.`]})})]}),_jsxs(Accordion,{title:`Force Unlock`,id:`force-unlock`,children:[_jsx(_components.p,{children:`Releases a stuck Terraform state lock.`}),_jsx(_components.p,{children:`Use this if:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`A previous Terraform operation was interrupted`}),`\n`,_jsx(_components.li,{children:`State is locked and preventing new operations`}),`\n`,_jsx(_components.li,{children:`You see “state is locked” errors`}),`\n`]}),_jsx(Warning,{children:_jsx(_components.p,{children:`Only use Force Unlock if you’re certain no other Terraform operation is running.`})})]}),_jsxs(Accordion,{title:`Migrate State`,id:`migrate-state`,children:[_jsx(_components.p,{children:`Migrates Terraform state between storage backends or updates state schema.`}),_jsxs(_components.p,{children:[`This operation runs `,_jsx(_components.code,{children:`terraform init -migrate-state`}),` to:`]}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Move state to a new backend`}),`\n`,_jsx(_components.li,{children:`Upgrade state file format`}),`\n`,_jsx(_components.li,{children:`Reconfigure state storage`}),`\n`]})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`create-\u0026-run-plan`,children:`Create \u0026 Run Plan`}),`\n`,_jsxs(_components.p,{children:[`During service creation, you can select `,_jsx(_components.strong,{children:`Create \u0026 Run Plan`}),` to immediately execute `,_jsx(_components.code,{children:`terraform plan`}),` after the service is created.`]}),`\n`,_jsx(_components.p,{children:`This allows you to:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Preview infrastructure changes before deployment`}),`\n`,_jsx(_components.li,{children:`Validate your Terraform configuration`}),`\n`,_jsx(_components.li,{children:`Review the execution plan before committing to apply`}),`\n`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`terraform-service-settings`,children:`Terraform Service Settings`}),`\n`,_jsxs(_components.p,{children:[`After creating your Terraform service, you can update all configuration options in the `,_jsx(_components.strong,{children:`Service Settings`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`general-configuration`,children:`General Configuration`}),`\n`,_jsx(_components.p,{children:`All parameters from the creation flow can be modified:`}),`\n`,_jsxs(AccordionGroup,{children:[_jsx(Accordion,{title:`Git Repository`,id:`git-repository`,children:_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Change the Git repository source`}),`\n`,_jsx(_components.li,{children:`Update the branch to deploy from`}),`\n`,_jsx(_components.li,{children:`Modify the root path for Terraform code location`}),`\n`]})}),_jsx(Accordion,{title:`Engine`,id:`engine`,children:_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Switch between Terraform and OpenTofu`}),`\n`,_jsx(_components.li,{children:`This change will take effect on the next deployment`}),`\n`]})}),_jsx(Accordion,{title:`Version`,id:`version`,children:_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Update the Terraform or OpenTofu version`}),`\n`,_jsx(_components.li,{children:`Useful for testing new versions or maintaining compatibility`}),`\n`]})}),_jsx(Accordion,{title:`State Management`,id:`state-management`,children:_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Modify state storage configuration`}),`\n`,_jsx(_components.li,{children:`Update state backend settings if using custom backend`}),`\n`]})}),_jsx(Accordion,{title:`Timeout`,id:`timeout`,children:_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Adjust the execution timeout (default: 1 hour)`}),`\n`,_jsx(_components.li,{children:`Increase for long-running Terraform operations`}),`\n`,_jsx(_components.li,{children:`Decrease to fail faster for quick validations`}),`\n`]})}),_jsxs(Accordion,{title:`Execution Resources`,id:`execution-resources`,children:[_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Update CPU allocation (default: 500 mCPU)`}),`\n`,_jsx(_components.li,{children:`Modify memory allocation (default: 256 MiB)`}),`\n`,_jsx(_components.li,{children:`Adjust storage allocation (default: 5 GiB)`}),`\n`]}),_jsx(_components.p,{children:`Increase these resources if your Terraform operations:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Manage a large number of resources`}),`\n`,_jsx(_components.li,{children:`Require significant memory for state processing`}),`\n`,_jsx(_components.li,{children:`Need more CPU for provider operations`}),`\n`]})]}),_jsx(Accordion,{title:`Environment Variables`,id:`environment-variables`,children:_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Add or update cloud provider credentials`}),`\n`,_jsxs(_components.li,{children:[`Configure Terraform input variables (`,_jsx(_components.code,{children:`TF_VAR_*`}),`)`]}),`\n`,_jsx(_components.li,{children:`Set provider-specific environment variables`}),`\n`,_jsx(_components.li,{children:`Reference secrets for sensitive values`}),`\n`]})})]}),`\n`,_jsx(Heading,{level:`3`,id:`terraform-arguments`,children:`Terraform Arguments`}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.strong,{children:`Terraform Arguments`}),` section allows you to specify additional CLI arguments for each Terraform command. These arguments override default behaviors and enable advanced customization.`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-arguments.png?fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=48ec0c2ca46b8f421a5b616f3df22066`,alt:`Terraform Arguments Configuration`,\"data-og-width\":`3164`,width:`3164`,\"data-og-height\":`2070`,height:`2070`,\"data-path\":`images/configuration/terraform/terraform-arguments.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-arguments.png?w=280\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=ee9e5b3f7ba64ee66b208b0328243d03 280w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-arguments.png?w=560\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=a6f61038b6008d33fac35011886cf538 560w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-arguments.png?w=840\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=24c44e2fd221ec8c4593d20640c4a784 840w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-arguments.png?w=1100\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=f516f58402581745cc018e4f23772802 1100w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-arguments.png?w=1650\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=5598e7cee569d3a8eea21930f107ff99 1650w, https://mintcdn.com/qovery/ziWdn5St6rf4bcBc/images/configuration/terraform/terraform-arguments.png?w=2500\u0026fit=max\u0026auto=format\u0026n=ziWdn5St6rf4bcBc\u0026q=85\u0026s=4febe4ce48de55f49ef82f1f9a30664b 2500w`})}),`\n`,_jsx(Info,{children:_jsx(_components.p,{children:`Terraform Arguments provide fine-grained control over Terraform execution. Use these to customize init, validate, plan, apply, and destroy operations.`})}),`\n`,_jsxs(AccordionGroup,{children:[_jsxs(Accordion,{title:`Init Arguments`,id:`init-arguments`,children:[_jsxs(_components.p,{children:[`Customize `,_jsx(_components.code,{children:`terraform init`}),` behavior.`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Common arguments:`})}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-upgrade`}),` - Upgrade modules and providers to latest versions`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-reconfigure`}),` - Reconfigure backend ignoring existing configuration`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-backend-config=...`}),` - Override backend configuration`]}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`-upgrade -backend-config=\"bucket=my-state-bucket\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]}),_jsxs(Accordion,{title:`Validate Arguments`,id:`validate-arguments`,children:[_jsxs(_components.p,{children:[`Customize `,_jsx(_components.code,{children:`terraform validate`}),` behavior.`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Common arguments:`})}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-json`}),` - Output validation results in JSON format`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-no-color`}),` - Disable colored output`]}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`-json -no-color`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]}),_jsxs(Accordion,{title:`Plan Arguments`,id:`plan-arguments`,children:[_jsxs(_components.p,{children:[`Customize `,_jsx(_components.code,{children:`terraform plan`}),` behavior.`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Common arguments:`})}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-target=resource.name`}),` - Plan changes for specific resource only`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-var=\"key=value\"`}),` - Set a variable value`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-var-file=filename`}),` - Load variables from file`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-out=filename`}),` - Save plan to a file`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-refresh=false`}),` - Skip state refresh`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-parallelism=n`}),` - Limit concurrent operations`]}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`-target=aws_s3_bucket.main -parallelism=5`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]}),_jsxs(Accordion,{title:`Apply Arguments`,id:`apply-arguments`,children:[_jsxs(_components.p,{children:[`Customize `,_jsx(_components.code,{children:`terraform apply`}),` behavior.`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Common arguments:`})}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-target=resource.name`}),` - Apply changes to specific resource only`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-var=\"key=value\"`}),` - Set a variable value`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-var-file=filename`}),` - Load variables from file`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-parallelism=n`}),` - Limit concurrent operations`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-refresh=false`}),` - Skip state refresh`]}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`-parallelism=10 -refresh=false`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]}),_jsxs(Accordion,{title:`Destroy Arguments`,id:`destroy-arguments`,children:[_jsxs(_components.p,{children:[`Customize `,_jsx(_components.code,{children:`terraform destroy`}),` behavior.`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Common arguments:`})}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-target=resource.name`}),` - Destroy specific resource only`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-var=\"key=value\"`}),` - Set a variable value`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-parallelism=n`}),` - Limit concurrent operations`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`-refresh=false`}),` - Skip state refresh`]}),`\n`]}),_jsx(Warning,{children:_jsx(_components.p,{children:`Use destroy arguments carefully. Targeting specific resources can lead to incomplete cleanup or resource dependencies issues.`})}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`-target=aws_s3_bucket.temp -parallelism=2`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]})]}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Argument Format:`})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Separate multiple arguments with spaces`}),`\n`,_jsxs(_components.li,{children:[`Quote values containing spaces: `,_jsx(_components.code,{children:`-var=\"name=my value\"`})]}),`\n`,_jsxs(_components.li,{children:[`Use multiple `,_jsx(_components.code,{children:`-var`}),` flags for multiple variables: `,_jsx(_components.code,{children:`-var=\"a=1\" -var=\"b=2\"`})]}),`\n`]}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example Full Configuration:`})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Init: -upgrade`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Plan: -parallelism=10 -var=\"environment=production\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Apply: -parallelism=10 -var=\"environment=production\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Destroy: -parallelism=5 -refresh=false`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`custom-build-image`,children:`Custom Build Image`}),`\n`,_jsxs(_components.p,{children:[`By default, Terraform services run using a base Docker image (Debian-based) containing Terraform (or OpenTofu), `,_jsx(_components.code,{children:`dumb-init`}),`, `,_jsx(_components.code,{children:`rsync`}),`, `,_jsx(_components.code,{children:`bash`}),`, and `,_jsx(_components.code,{children:`ca-certificates`}),`. If your Terraform code requires additional binaries or tools (e.g., AWS CLI, `,_jsx(_components.code,{children:`kubectl`}),`, `,_jsx(_components.code,{children:`jq`}),`, custom scripts), you can customize the build image using a `,_jsx(_components.strong,{children:`Dockerfile fragment`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`configuring-a-dockerfile-fragment`,children:`Configuring a Dockerfile Fragment`}),`\n`,_jsx(_components.p,{children:`Qovery provides two ways to inject custom Dockerfile commands during the build:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`File-based`}),`: Reference a Dockerfile fragment file stored in your Git repository`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Inline`}),`: Provide Dockerfile commands directly in the service configuration`]}),`\n`]}),`\n`,_jsxs(Tabs,{children:[_jsxs(Tab,{title:`File-based Fragment`,id:`file-based-fragment`,children:[_jsx(_components.p,{children:`Reference a Dockerfile fragment file from your repository.`}),_jsxs(Steps,{children:[_jsxs(Step,{title:`Create Fragment File`,children:[_jsx(_components.p,{children:`In your Git repository, create a Dockerfile fragment file in your Terraform code directory or a custom location.`}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example directory structure:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`7`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`7`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`my-repo/`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`├── terraform/`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ ├── main.tf`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ ├── variables.tf`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ └── custom-build.dockerfile # Your fragment file`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`└── README.md`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]}),_jsxs(Step,{title:`Add Dockerfile Instructions`,children:[_jsxs(_components.p,{children:[`Add valid Dockerfile instructions to install the tools you need. The fragment is injected into the build `,_jsx(_components.strong,{children:`after`}),` your Terraform files are copied and `,_jsx(_components.strong,{children:`before`}),` the final user switch.`]}),_jsxs(_components.p,{children:[`See the `,_jsx(_components.strong,{children:`Fragment Examples`}),` section below for common use cases.`]})]}),_jsxs(Step,{title:`Configure Service`,children:[_jsx(_components.p,{children:`In the Terraform service settings, configure the Dockerfile fragment:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Navigate to `,_jsx(_components.strong,{children:`Service Settings`}),` → `,_jsx(_components.strong,{children:`Dockerfile Fragment`})]}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.strong,{children:`Custom file path`})]}),`\n`,_jsxs(_components.li,{children:[`Enter the absolute path to your fragment file (e.g., `,_jsx(_components.code,{children:`/terraform/custom-build.dockerfile`}),`)`]}),`\n`]}),_jsx(Info,{children:_jsxs(_components.p,{children:[`The path must be absolute (starting with `,_jsx(_components.code,{children:`/`}),`) and located within your service’s `,_jsx(_components.code,{children:`root_path`}),`.`]})})]}),_jsx(Step,{title:`Deploy`,children:_jsx(_components.p,{children:`Save your changes and deploy. Qovery will inject the fragment contents during the Docker build.`})})]})]}),_jsxs(Tab,{title:`Inline Fragment`,id:`inline-fragment`,children:[_jsx(_components.p,{children:`Define Dockerfile commands directly in the service configuration without creating a file in your repository.`}),_jsxs(Steps,{children:[_jsxs(Step,{title:`Configure Service`,children:[_jsx(_components.p,{children:`In the Terraform service settings:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Navigate to `,_jsx(_components.strong,{children:`Service Settings`}),` → `,_jsx(_components.strong,{children:`Dockerfile Fragment`})]}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.strong,{children:`Inline content`})]}),`\n`,_jsx(_components.li,{children:`Enter your Dockerfile commands in the text area`}),`\n`]}),_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`docker`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`docker`,children:_jsxs(_components.code,{language:`docker`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Install AWS CLI and common utilities`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`RUN`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` apt-get update \u0026\u0026 \\\\`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` apt-get install -y --no-install-recommends awscli jq curl \u0026\u0026 \\\\`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` rm -rf /var/lib/apt/lists/*`})}),`\n`]})})})]}),_jsx(Step,{title:`Deploy`,children:_jsx(_components.p,{children:`Save your changes and deploy. Qovery will inject the inline content during the Docker build.`})})]}),_jsx(Info,{children:_jsx(_components.p,{children:`Inline fragments are limited to 8KB of content. For larger customizations, use a file-based fragment.`})})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`fragment-examples`,children:`Fragment Examples`}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Installing AWS CLI and common tools:`})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`docker`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`docker`,children:_jsxs(_components.code,{language:`docker`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Install AWS CLI and common utilities`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`RUN`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` apt-get update \u0026\u0026 \\\\`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` apt-get install -y --no-install-recommends awscli jq curl \u0026\u0026 \\\\`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` rm -rf /var/lib/apt/lists/*`})}),`\n`]})})}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Installing kubectl:`})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`docker`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`docker`,children:_jsxs(_components.code,{language:`docker`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Install kubectl (curl is already available in the base image)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`RUN`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` curl -LO `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` \u0026\u0026 \\\\`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` chmod +x kubectl \u0026\u0026 \\\\`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` mv kubectl /usr/local/bin/`})}),`\n`]})})}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Installing a custom binary from your repository:`})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`docker`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`docker`,children:_jsxs(_components.code,{language:`docker`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Install a custom tool already present in the repository`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# (repository files are already copied to /data)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`RUN`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` cp /data/bin/my-custom-tool /usr/local/bin/my-custom-tool \u0026\u0026 \\\\`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` chmod +x /usr/local/bin/my-custom-tool`})}),`\n`]})})}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Downloading and extracting a remote archive:`})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`docker`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`docker`,children:_jsxs(_components.code,{language:`docker`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Download and extract a tool from the internet`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`ADD`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` https://releases.example.com/tool-v1.2.3.tar.gz /tmp/tool.tar.gz`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`RUN`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` tar -xzf /tmp/tool.tar.gz -C /usr/local/bin/ \u0026\u0026 \\\\`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` rm /tmp/tool.tar.gz`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`supported-dockerfile-instructions`,children:`Supported Dockerfile Instructions`}),`\n`,_jsx(_components.p,{children:`The fragment supports the following Dockerfile instructions:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`RUN`}),` - Execute commands during build (install packages, configure tools, etc.)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`ADD`}),` - Add files with URL/archive support (download and extract remote archives)`]}),`\n`]}),`\n`,_jsx(Info,{children:_jsxs(_components.p,{children:[`Repository files are already present in `,_jsx(_components.code,{children:`/data`}),` before the fragment executes, so you can reference them in `,_jsx(_components.code,{children:`RUN`}),` commands without needing `,_jsx(_components.code,{children:`COPY`}),`.`]})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`The fragment runs as `,_jsx(_components.code,{children:`root`}),` during the build. The container switches to a non-root user (`,_jsx(_components.code,{children:`app`}),`) after your fragment executes. Make sure any binaries you install are accessible to all users.`]})}),`\n`,_jsx(Info,{children:_jsx(_components.p,{children:`This feature is specific to Terraform and OpenTofu services. Applications and Jobs use different build mechanisms.`})}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`clone-service`,children:`Clone Service`}),`\n`,_jsx(_components.p,{children:`You can create a clone of the service via the clone feature. A new service with the same configuration will be created into the target environment.`}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Select Service`,children:_jsx(_components.p,{children:`Go to the Terraform service you want to clone`})}),_jsx(Step,{title:`Clone Service`,children:_jsxs(_components.p,{children:[`Click on the `,_jsx(_components.strong,{children:`three dots button`}),` and select `,_jsx(_components.strong,{children:`Clone`})]})}),_jsx(Step,{title:`Select Target Environment`,children:_jsx(_components.p,{children:`Choose the target environment where you want to clone the service`})})]}),`\n`,_jsx(Info,{children:_jsx(_components.p,{children:`The target environment can be the same as the current environment or a different one in a completely different project.`})}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`next-steps`,children:`Next Steps`}),`\n`,_jsxs(CardGroup,{cols:2,children:[_jsx(Card,{title:`Environment Variables`,icon:`key`,href:`/configuration/environment-variables`,children:_jsx(_components.p,{children:`Learn how to manage variables and secrets`})}),_jsx(Card,{title:`Terraform Provider`,icon:`code`,href:`/terraform-provider/overview`,children:_jsx(_components.p,{children:`Use Qovery Terraform Provider to manage Qovery resources`})}),_jsx(Card,{title:`Lifecycle Jobs`,icon:`clock`,href:`/configuration/lifecycle-job`,children:_jsx(_components.p,{children:`Run scripts during deployment lifecycle`})}),_jsx(Card,{title:`Deployment Overview`,icon:`rocket`,href:`/configuration/deployment/overview`,children:_jsx(_components.p,{children:`Understand deployment workflows`})})]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Terraform","description":"Deploy and manage Terraform modules natively on Qovery","href":"/configuration/terraform"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Introduction","slug":"introduction","depth":2,"children":[]},{"title":"Demo: Deploy S3 and Connect to Qovery Services","slug":"demo-deploy-s3-and-connect-to-qovery-services","depth":2,"children":[]},{"title":"Creating a Terraform Service","slug":"creating-a-terraform-service","depth":2,"children":[]},{"title":"Running Terraform","slug":"running-terraform","depth":2,"children":[{"title":"Available Actions","slug":"available-actions","depth":3,"children":[]},{"title":"Create \u0026 Run Plan","slug":"create-\u0026-run-plan","depth":3,"children":[]}]},{"title":"Terraform Service Settings","slug":"terraform-service-settings","depth":2,"children":[{"title":"General Configuration","slug":"general-configuration","depth":3,"children":[]},{"title":"Terraform Arguments","slug":"terraform-arguments","depth":3,"children":[]}]},{"title":"Custom Build Image","slug":"custom-build-image","depth":2,"children":[{"title":"Configuring a Dockerfile Fragment","slug":"configuring-a-dockerfile-fragment","depth":3,"children":[]},{"title":"Fragment Examples","slug":"fragment-examples","depth":3,"children":[]},{"title":"Supported Dockerfile Instructions","slug":"supported-dockerfile-instructions","depth":3,"children":[]}]},{"title":"Clone Service","slug":"clone-service","depth":2,"children":[]},{"title":"Next Steps","slug":"next-steps","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/docs/_mintlify/custom/qovery/0bf2b14fb00c53b9/custom.js","/docs/_mintlify/custom/qovery/a066ee21572976bb/reo.js"],"subdomain":"qovery","siteName":"Qovery","title":"Terraform - Qovery","relatedPagesConfig":{"enabled":true,"limit":5,"mode":"automatic"},"navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-08T14:59:27.400Z","originalFileLocation":"configuration/terraform.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Deploy and manage Terraform modules natively on Qovery\">\u003cmeta data-mint-head name=\"application-name\" content=\"Qovery\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Terraform - Qovery\">\u003cmeta data-mint-head property=\"og:description\" content=\"Deploy and manage Terraform modules natively on Qovery\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Qovery\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://www.qovery.com/docs/configuration/terraform\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://qovery.mintlify.site/docs/_mintlify/api/og/v2?division=Data+%26+Infrastructure\u0026amp;title=Terraform\u0026amp;description=Deploy+and+manage+Terraform+modules+natively+on+Qovery\u0026amp;theme=c6d6a14f46d32f5b235bce1e\u0026amp;signature=ebeaf1cdab3ff030f1599a453faeae966c6c23abceadc1538d6c7eaa5ab449f5\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Terraform - Qovery\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Deploy and manage Terraform modules natively on Qovery\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://qovery.mintlify.site/docs/_mintlify/api/og/v2?division=Data+%26+Infrastructure\u0026amp;title=Terraform\u0026amp;description=Deploy+and+manage+Terraform+modules+natively+on+Qovery\u0026amp;theme=c6d6a14f46d32f5b235bce1e\u0026amp;signature=ebeaf1cdab3ff030f1599a453faeae966c6c23abceadc1538d6c7eaa5ab449f5\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/docs/mintlify-assets/_mintlify/favicons/qovery/ujffYmd-5c8eNJut/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Qovery\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#642DFF\">\u003clink data-mint-head rel=\"canonical\" href=\"https://www.qovery.com/docs/configuration/terraform\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/docs/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/configuration/terraform.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://www.qovery.com/#organization\",\"name\":\"Qovery\",\"url\":\"https://www.qovery.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/qovery/Nvnl0g5BHzA0XQmy/images/logos/qovery-logo-black.svg?fit=max\u0026auto=format\u0026n=Nvnl0g5BHzA0XQmy\u0026q=85\u0026s=fd1a292f8293eb3cf8763f75af6ee9d4\"}},{\"@type\":\"WebSite\",\"@id\":\"https://www.qovery.com/docs#website\",\"name\":\"Qovery\",\"url\":\"https://www.qovery.com/docs\",\"publisher\":{\"@id\":\"https://www.qovery.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://www.qovery.com/docs/configuration/terraform#webpage\",\"url\":\"https://www.qovery.com/docs/configuration/terraform\",\"name\":\"Terraform\",\"description\":\"Deploy and manage Terraform modules natively on Qovery\",\"dateModified\":\"2026-10-08T14:59:27.400Z\",\"isPartOf\":{\"@id\":\"https://www.qovery.com/docs#website\"},\"breadcrumb\":{\"@id\":\"https://www.qovery.com/docs/configuration/terraform#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://www.qovery.com/docs/configuration/terraform#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Services\",\"item\":\"https://www.qovery.com/docs/configuration/application\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Data \u0026 Infrastructure\",\"item\":\"https://www.qovery.com/docs/configuration/database\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Terraform\",\"item\":\"https://www.qovery.com/docs/configuration/terraform\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://www.qovery.com/docs/configuration/terraform#article\",\"headline\":\"Terraform\",\"name\":\"Terraform\",\"description\":\"Deploy and manage Terraform modules natively on Qovery\",\"url\":\"https://www.qovery.com/docs/configuration/terraform\",\"mainEntityOfPage\":{\"@id\":\"https://www.qovery.com/docs/configuration/terraform#webpage\"},\"dateModified\":\"2026-10-08T14:59:27.400Z\",\"publisher\":{\"@id\":\"https://www.qovery.com/#organization\"},\"isPartOf\":{\"@id\":\"https://www.qovery.com/docs#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Qovery\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Qovery","nav":{"global":null,"tabs":[{"tab":"Getting Started","icon":"rocket","pages":[{"title":"Getting Started","href":"/getting-started/introduction"}]},{"tab":"Configuration","icon":"sliders","groups":[{"group":"Overview","pages":[{"title":"Configuration Overview","href":"/configuration/overview"}]},{"group":"Account \u0026 Organization","pages":[{"title":"User Account","href":"/configuration/user-account"},{"title":"Organization","href":"/configuration/organization"},{"group":"Access \u0026 Security","pages":[{"title":"Members \u0026 RBAC","href":"/configuration/organization/members-rbac"},{"title":"SSO (SAML/OIDC)","href":"/configuration/organization/sso"},{"title":"API Token","href":"/configuration/organization/api-token"},{"title":"API Policy Token (Preview)","href":"/configuration/organization/api-policy-token"}]}]},{"group":"Clusters \u0026 Cloud","pages":[{"title":"Clusters","href":"/configuration/clusters"},{"title":"Cluster Advanced Settings","href":"/configuration/cluster-advanced-settings"},{"title":"Connect to Your Cluster","href":"/configuration/connect-to-cluster"},{"title":"Cloud Credentials","href":"/configuration/organization/cloud-credentials"},{"title":"Cloud Provider Resource Tags","href":"/configuration/cloud-provider-resource-tags"},{"group":"AWS EKS","pages":[{"title":"AWS EKS Integration","href":"/configuration/integrations/kubernetes/eks/overview"},{"title":"AWS EKS","href":"/configuration/integrations/kubernetes/eks/managed"},{"title":"AWS Cluster Preflight Checks","href":"/configuration/integrations/kubernetes/eks/preflight-checks"},{"title":"AWS EKS Anywhere","href":"/configuration/integrations/kubernetes/eks/eks-anywhere"}]},{"group":"Google GKE","pages":[{"title":"Google GKE Integration","href":"/configuration/integrations/kubernetes/gke/overview"},{"title":"Qovery-Managed GKE","href":"/configuration/integrations/kubernetes/gke/managed"}]},{"group":"Azure AKS","pages":[{"title":"Azure AKS Integration","href":"/configuration/integrations/kubernetes/aks/overview"},{"title":"Qovery-Managed AKS","href":"/configuration/integrations/kubernetes/aks/managed"}]},{"group":"Scaleway Kapsule","pages":[{"title":"Scaleway Kapsule Integration","href":"/configuration/integrations/kubernetes/scaleway/overview"},{"title":"Qovery-Managed Scaleway Kapsule","href":"/configuration/integrations/kubernetes/scaleway/managed"}]},{"group":"Other Kubernetes","pages":[{"title":"Bring Your Own Kubernetes (BYOK)","tag":"PREVIEW","href":"/configuration/integrations/kubernetes/byok"},{"title":"Local Cluster for Development","href":"/configuration/integrations/kubernetes/docker"}]}]},{"group":"Source Control","pages":[{"title":"Git Repository Access","href":"/configuration/organization/git-repository-access"},{"group":"Container Registries","pages":[{"title":"Container Registry","href":"/configuration/organization/container-registry"},{"title":"Docker Hub","href":"/configuration/integrations/container-registries/docker-hub"},{"group":"Cloud Registries","pages":[{"title":"AWS ECR","href":"/configuration/integrations/container-registries/aws-ecr"},{"title":"GCP Artifact Registry","href":"/configuration/integrations/container-registries/gcp-artifact-registry"},{"title":"Azure Container Registry","href":"/configuration/integrations/container-registries/azure-acr"},{"title":"Scaleway Container Registry","href":"/configuration/integrations/container-registries/scaleway-cr"}]},{"group":"Git-based Registries","pages":[{"title":"GitHub Container Registry","href":"/configuration/integrations/container-registries/github-cr"},{"title":"GitLab Container Registry","href":"/configuration/integrations/container-registries/gitlab-cr"}]},{"title":"Generic Container Registry","href":"/configuration/integrations/container-registries/generic"}]},{"group":"Helm Repositories","pages":[{"title":"Helm Repository","href":"/configuration/organization/helm-repository"}]}]},{"group":"Projects \u0026 Environments","pages":[{"title":"Project","href":"/configuration/project"},{"title":"Environment","href":"/configuration/environment"}]},{"group":"Services","pages":[{"group":"Workloads","pages":[{"title":"Application","href":"/configuration/application"},{"title":"Helm Charts","href":"/configuration/helm"}]},{"group":"Jobs","pages":[{"title":"Cron Jobs","href":"/configuration/cronjob"},{"title":"Lifecycle Jobs","href":"/configuration/lifecycle-job"}]},{"group":"Agent Tasks","tag":"NEW","pages":[{"title":"Agent Tasks","tag":"NEW","href":"/configuration/agent-tasks/overview"},{"group":"Examples","pages":[{"title":"Incident Analyzer with incident.io","href":"/configuration/agent-tasks/incident-analyser"},{"title":"Incident Analyzer with Honeybadger","href":"/configuration/agent-tasks/incident-analyser-honeybadger"},{"title":"Build \u0026 Deployment Optimizer","href":"/configuration/agent-tasks/build-deployment-optimizer"},{"title":"Jira Coding Agent","href":"/configuration/agent-tasks/jira-coding-agent"},{"title":"Linear Coding Agent","href":"/configuration/agent-tasks/linear-coding-agent"}]}]},{"group":"Data \u0026 Infrastructure","pages":[{"title":"Databases","href":"/configuration/database"},{"title":"Object Storage","description":"Use cloud object storage for persistent data in your applications","href":"/configuration/object-storage"},{"title":"Terraform","href":"/configuration/terraform"}]},{"title":"Blueprints","description":"Provision managed cloud infrastructure, Kubernetes add-ons, and third-party SaaS resources from Qovery's catalog, no Terraform or Helm required","href":"/configuration/blueprints"},{"title":"Service Health Checks","href":"/configuration/service-health-checks"},{"title":"Service Advanced Settings","href":"/configuration/service-advanced-settings"}]},{"group":"Deployment \u0026 CI/CD","pages":[{"title":"Deployment","href":"/configuration/deployment/overview"},{"title":"Deployment Pipeline","href":"/configuration/deployment/pipeline"},{"title":"Auto-Deploy","href":"/configuration/deployment/auto-deploy"},{"group":"Deployment Configuration","pages":[{"title":"Deployment Actions","href":"/configuration/deployment/actions"},{"title":"Deployment Strategies","href":"/configuration/deployment/strategies"},{"title":"Image Mirroring","href":"/configuration/deployment/image-mirroring"},{"title":"Deployment Rules","href":"/configuration/deployment-rule"}]},{"group":"Monitoring Deployments","pages":[{"title":"Running and Deployment Statuses","href":"/configuration/deployment/statuses"},{"title":"Logs","href":"/configuration/deployment/logs"},{"title":"Deployment History","href":"/configuration/deployment/history"}]},{"group":"CI/CD Integrations","pages":[{"title":"GitHub Actions","href":"/configuration/integrations/ci-cd/github-actions"},{"title":"GitLab CI","href":"/configuration/integrations/ci-cd/gitlab-ci"},{"title":"CircleCI","href":"/configuration/integrations/ci-cd/circleci"},{"title":"Jenkins","href":"/configuration/integrations/ci-cd/jenkins"},{"title":"ArgoCD Integration","href":"/configuration/integrations/argocd"}]}]},{"group":"Environment Variables \u0026 Secrets","pages":[{"title":"Environment Variables","href":"/configuration/environment-variables"},{"title":"Doppler","href":"/configuration/integrations/secret-managers/doppler"},{"group":"Secret Manager Integration","tag":"NEW","pages":[{"title":"Overview","tag":"NEW","href":"/configuration/integrations/secret-managers/secret-manager-access"},{"title":"AWS Secrets Manager","href":"/configuration/integrations/secret-managers/aws-secrets-manager"},{"title":"AWS Parameter Store","href":"/configuration/integrations/secret-managers/aws-parameter-store"},{"title":"GCP Secret Manager","href":"/configuration/integrations/secret-managers/gcp-secret-manager"}]}]},{"group":"Observability","pages":[{"title":"Qovery Observe","href":"/configuration/integrations/observability/qovery-observe"},{"title":"Datadog Integration","href":"/configuration/integrations/observability/datadog"},{"title":"Kubecost","href":"/configuration/integrations/observability/kubecost"}]},{"group":"Notifications","pages":[{"title":"Webhooks","href":"/configuration/integrations/webhooks"},{"title":"Slack Integration","href":"/configuration/integrations/slack"},{"title":"Email Integration","href":"/configuration/integrations/email"}]},{"group":"Networking \u0026 Advanced","pages":[{"group":"Networking","pages":[{"title":"VPC Peering","href":"/configuration/integrations/aws/vpc-peering"},{"title":"Use the ECR Pull Through Cache on Your Existing VPC","href":"/configuration/integrations/aws/ecr-pull-through-cache-existing-vpc"},{"title":"API Gateway with NGINX","href":"/configuration/integrations/api-gateway-nginx"}]},{"group":"Advanced Configuration","pages":[{"title":"Labels \u0026 Annotations","href":"/configuration/organization/labels-annotations"},{"title":"Disaster Recovery","href":"/configuration/disaster-recovery"}]},{"group":"Infrastructure as Code","pages":[{"title":"Infrastructure as Code","href":"/configuration/integrations/iac/overview"},{"title":"Terraform","href":"/configuration/integrations/iac/terraform"},{"title":"CloudFormation","href":"/configuration/integrations/iac/cloudformation"}]}]}]},{"tab":"AI","icon":"robot","pages":[{"title":"AI","href":"/copilot/ai-overview"}]},{"tab":"Terraform Provider","icon":"code","pages":[{"title":"Terraform Provider","href":"/terraform-provider/overview"}]},{"tab":"CLI","icon":"terminal","pages":[{"title":"CLI","href":"/cli/overview"}]},{"tab":"API Reference","icon":"brackets-curly","pages":[{"title":"API Reference","href":"/api-reference/introduction"}]}]},"basePath":"","title":"Terraform - Qovery","buildId":"dpl_BSPUBxEoKhhK7HzXVDPxdPvWx4xc","deploymentId":"dpl_BSPUBxEoKhhK7HzXVDPxdPvWx4xc","dynamics":["07c022d89b","a74be98ba7"],"chunks":["Frame-DRxXE_WT.js","DynamicMarkdown-AlxJK8VR.js","zoom-image-lightbox-B_-GSaTf.js","lightbox-handle-r17bVUz3.js"]}