CI/CD with Other Platforms
The TF_TOKEN_* pattern works on any platform that can set environment variables. See the CI/CD overview for prerequisites and how authentication works.
Spacelift
Based on Spacelift's environment configuration documentation, compliance.tf tokens are configured as follows.
Store the Token
Per stack:
- Open your stack in Spacelift
- Go to Environment
- Click Add Variable
- Key:
TF_TOKEN_soc2_compliance_tf - Value: paste your token
- Check Secret
Organization-wide (recommended):
- Go to Contexts in your Spacelift account
- Create a new context (e.g., "compliance-tf-credentials")
- Add the environment variable
TF_TOKEN_soc2_compliance_tfas a secret - Attach the context to all relevant stacks
No Pipeline File Needed
Spacelift handles terraform init, plan, and apply automatically. Once the environment variable is available to the stack, module downloads from the compliance.tf registry work without further configuration.
Reference: Spacelift Contexts
Atlantis
Based on Atlantis server configuration documentation, compliance.tf tokens are configured at the server level.
Store the Token
Atlantis runs Terraform server-side, so the token is configured once on the Atlantis server, not per repository.
Set the environment variable in your Atlantis deployment:
services:
atlantis:
image: ghcr.io/runatlantis/atlantis:latest
environment:
# compliance.tf registry authentication
TF_TOKEN_soc2_compliance_tf: "${CTF_TOKEN}"
# ... other configurationapiVersion: v1
kind: Secret
metadata:
name: atlantis-ctf-token
type: Opaque
stringData:
TF_TOKEN_soc2_compliance_tf: "ctf_YOUR_TOKEN_HERE"Do not commit this manifest with a real token. Create the secret directly (kubectl create secret generic atlantis-ctf-token --from-literal=...) or use your cluster's secret management (Sealed Secrets, External Secrets). Reference the secret in your Atlantis deployment's envFrom or env configuration.
Add TF_TOKEN_soc2_compliance_tf to your task definition's secrets block, referencing an AWS Secrets Manager or SSM Parameter Store value.
Optional: Custom Workflow
If you want to save the plan JSON for evidence archiving, define a custom workflow in repos.yaml:
repos:
- id: /.*/
workflow: compliance
workflows:
compliance:
plan:
steps:
- init
- plan
# Save the plan JSON for evidence archiving
- run: terraform show -json $PLANFILE > plan.json
apply:
steps:
- applyReference: Atlantis custom workflows
env0
Based on env0's variable documentation, compliance.tf tokens are configured as follows.
Store the Token
- Go to Organization Settings > Variables (for organization-wide) or your project/environment variables
- Click Add Variable
- Type: Environment
- Key:
TF_TOKEN_soc2_compliance_tf - Value: paste your token
- Mark as Sensitive
Optional: Custom Flow
If you want to save the plan JSON for evidence archiving, use a Custom Flow:
deploy:
steps:
planCommand:
after:
- name: Save Plan Output
command: terraform show -json tfplan > plan.jsonAdjust the plan file name if your env0 template uses a different -out= value.
Reference: env0 Custom Flows
Jenkins
Store the Token
- Go to Manage Jenkins > Credentials
- Select the appropriate scope (global or folder)
- Click Add Credentials
- Kind: Secret text
- Secret: paste your token
- ID:
ctf-token
Configure Your Pipeline
pipeline {
agent any
// Requires the Jenkins Terraform plugin, with a tool named "terraform-1.12"
// configured under Manage Jenkins > Tools
tools {
terraform 'terraform-1.12'
}
stages {
stage('Init') {
steps {
withCredentials([string(credentialsId: 'ctf-token', variable: 'CTF_TOKEN')]) {
withEnv(["TF_TOKEN_soc2_compliance_tf=${CTF_TOKEN}"]) {
sh 'terraform init'
}
}
}
}
stage('Plan') {
steps {
withCredentials([string(credentialsId: 'ctf-token', variable: 'CTF_TOKEN')]) {
withEnv(["TF_TOKEN_soc2_compliance_tf=${CTF_TOKEN}"]) {
sh 'terraform plan -out=tfplan'
}
}
}
}
stage('Apply') {
when {
branch 'main'
}
steps {
withCredentials([string(credentialsId: 'ctf-token', variable: 'CTF_TOKEN')]) {
withEnv(["TF_TOKEN_soc2_compliance_tf=${CTF_TOKEN}"]) {
sh 'terraform apply -auto-approve tfplan'
}
}
}
}
}
}Reference: Jenkins credentials handling
CircleCI
Store the Token
Add CTF_TOKEN as an environment variable in your CircleCI project or in a shared context:
- Open your project in CircleCI
- Go to Project Settings > Environment Variables
- Click Add Environment Variable
- Name:
CTF_TOKEN - Value: paste your token
- Go to Organization Settings > Contexts
- Create a new context (e.g.,
compliance-tf) - Add the environment variable
CTF_TOKEN - Reference the context in your workflow jobs
Configure Your Pipeline
version: 2.1
jobs:
terraform-plan:
docker:
- image: hashicorp/terraform:1.12
steps:
- checkout
- run:
name: Terraform Init
command: |
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform init
- run:
name: Terraform Validate
command: terraform validate
- run:
name: Terraform Plan
command: |
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform plan -out=tfplan
- persist_to_workspace:
root: .
paths:
- .
terraform-apply:
docker:
- image: hashicorp/terraform:1.12
steps:
- attach_workspace:
at: .
- run:
name: Terraform Apply
command: |
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform apply -auto-approve tfplan
workflows:
infrastructure:
jobs:
- terraform-plan:
context: compliance-tf
- hold-apply:
type: approval
requires:
- terraform-plan
filters:
branches:
only: main
- terraform-apply:
context: compliance-tf
requires:
- hold-apply
filters:
branches:
only: mainThe hold-apply job is a built-in approval gate — the apply step will not run until a team member manually approves it in the CircleCI dashboard.
Reference: CircleCI contexts, CircleCI environment variables
Azure DevOps
Store the Token
Add CTF_TOKEN as a secret pipeline variable or in a shared variable group:
- Open your pipeline in Azure DevOps
- Click Edit > Variables
- Click New Variable
- Name:
CTF_TOKEN - Value: paste your token
- Check Keep this value secret
- Go to Pipelines > Library
- Click + Variable group
- Name the group (e.g.,
compliance-tf-credentials) - Add
CTF_TOKENand mark it as secret - Reference the group in any pipeline that needs registry access
Configure Your Pipeline
trigger:
branches:
include:
- main
- feature/*
pool:
vmImage: ubuntu-latest
variables:
- group: compliance-tf-credentials
stages:
- stage: Plan
displayName: Terraform Plan
jobs:
- job: TerraformPlan
steps:
- task: TerraformInstaller@1
displayName: Install Terraform
inputs:
terraformVersion: "1.12.0"
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform init
displayName: Terraform Init
- script: terraform validate
displayName: Terraform Validate
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform plan -out=tfplan
displayName: Terraform Plan
- publish: $(System.DefaultWorkingDirectory)/tfplan
artifact: tfplan
displayName: Publish Plan Artifact
- stage: Apply
displayName: Terraform Apply
dependsOn: Plan
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: TerraformApply
environment: production
strategy:
runOnce:
deploy:
steps:
# deployment jobs do not check out source by default —
# without this, init/apply run in an empty working directory
- checkout: self
- download: current
artifact: tfplan
- task: TerraformInstaller@1
displayName: Install Terraform
inputs:
terraformVersion: "1.12.0"
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform init
displayName: Terraform Init
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform apply -auto-approve $(Pipeline.Workspace)/tfplan/tfplan
displayName: Terraform ApplyThe Apply stage uses a deployment job targeting the production environment. Configure Approvals and checks on that environment to require manual approval before apply runs.
Reference: Azure DevOps variable groups, Azure DevOps environments
Generic / Other
The TF_TOKEN_* environment variable pattern works on any CI/CD platform that can set environment variables and run shell commands. This includes AWS CodeBuild, Buildkite, Drone, Harness, and Codefresh.
The Pattern
- Store your compliance.tf token as a secret in your CI/CD platform
- Expose it as an environment variable named
TF_TOKEN_soc2_compliance_tf - Run
terraform init— Terraform picks up the token automatically
# The CI/CD platform injects CTF_TOKEN from its secret store
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform init
terraform validate
terraform plan -out=tfplanAlternative: Dynamic .terraformrc
If you prefer a credentials file over environment variables, you can write one dynamically:
# Always clean up, even if a command fails mid-script
trap 'rm -f ~/.terraformrc' EXIT
# Write credentials file (token comes from CI secret store)
cat > ~/.terraformrc <<EOF
credentials "soc2.compliance.tf" {
token = "${CTF_TOKEN}"
}
EOF
terraform init
terraform plan -out=tfplanClean up credentials files
If you write a .terraformrc file dynamically, delete it at the end of the pipeline run (the trap above handles this). Do not leave credentials on shared build agents.
Next steps
- CI/CD overview — multi-environment setup, retention guidance, and troubleshooting
- Audit evidence guide — archive the plan artifacts these pipelines produce