Skip to main content

Configure Variables

The vars section defines variables that are passed to your components. Variables can be set at the global level, component-type level, or component level, and are deep-merged across the inheritance chain.

Use Cases

  • Component Configuration: Pass input variables to Terraform root modules, Helmfile releases, Packer templates, or Ansible playbooks.
  • Environment-Specific Values: Define different values for dev, staging, and production environments.
  • Shared Defaults: Set common variables at higher levels and override them at lower levels as needed.

Configuration Scopes

The vars section can be defined at multiple levels. Atmos deep-merges variables from all levels, with more specific levels taking precedence.

Global Level

Variables defined at the root level apply to all components in the stack:

# stacks/orgs/acme/plat/prod/us-east-1.yaml
vars:
environment: prod
region: us-east-1
tags:
Environment: Production
ManagedBy: Atmos

Component-Type Level

Variables defined under terraform, helmfile, packer, or ansible apply to all components of that type:

# stacks/orgs/acme/plat/prod/_defaults.yaml
terraform:
vars:
terraform_version: "1.5"

helmfile:
vars:
helm_timeout: 300

ansible:
vars:
managed_by: Atmos

Component Level

Variables defined within a component override all higher-level settings:

# stacks/orgs/acme/plat/prod/us-east-1.yaml
components:
terraform:
vpc:
vars:
vpc_cidr: "10.0.0.0/16"
enable_dns_hostnames: true
availability_zones:
- us-east-1a
- us-east-1b
- us-east-1c

Merge Behavior

Variables are deep-merged from the most general to the most specific level:

  1. Global vars: (applies to all components)
  2. Component-type terraform.vars: / helmfile.vars: / packer.vars: / ansible.vars: (applies to all components of that type)
  3. Base component vars (inherited via metadata.inherits)
  4. Component components.terraform.<name>.vars (applies to a specific component)
  5. Override overrides.vars (file-scoped — applies only to components in the current manifest and its imports)

Maps are recursively merged, and lists are replaced (not appended). More specific values override less specific ones.

info

Import order determines who wins at the same scope level. Scope level determines who wins across levels. Use atmos describe component <component> -s <stack> --provenance to see exactly where each value came from.

Example

stacks/catalog/vpc/_defaults.yaml

# Global defaults for VPC components
vars:
tags:
Team: Platform

stacks/orgs/acme/plat/prod/_defaults.yaml

# Production defaults
vars:
tags:
Environment: Production

stacks/orgs/acme/plat/prod/us-east-1.yaml

import:
- catalog/vpc/_defaults
- orgs/acme/plat/prod/_defaults

components:
terraform:
vpc:
vars:
vpc_cidr: "10.0.0.0/16"
tags:
Name: prod-vpc

The resulting vars for the vpc component would be:

vars:
vpc_cidr: "10.0.0.0/16"
tags:
Team: Platform # From catalog/_defaults
Environment: Production # From prod/_defaults
Name: prod-vpc # From component

Context Variables

Atmos automatically provides context variables based on your stack naming convention. These are available in templates and can be used in your Terraform code:

namespace
Organization or company identifier.
tenant
Tenant identifier (for multi-tenant setups).
environment
Environment identifier (e.g., ue1 for us-east-1).
stage
Stage identifier (e.g., dev, staging, prod).

These context variables are typically configured in your atmos.yaml using the name_pattern setting.

Using Templates in Variables

Variables support Go templates for dynamic values:

vars:
cluster_name: "{{ .namespace }}-{{ .environment }}-{{ .stage }}-eks"
bucket_name: "{{ .namespace }}-{{ .tenant }}-{{ .stage }}-assets"

You can also reference other component outputs using YAML functions:

vars:
vpc_id: !terraform.output vpc/vpc_id
subnet_ids: !terraform.output vpc/private_subnet_ids

YAML Functions for Variables

Atmos provides YAML functions that can dynamically set variable values. These functions are evaluated at runtime when processing stack configurations.

!include - Load External Files

The !include function loads content from external files, making it ideal for reusing existing .tfvars files or large variable definitions:

vars:
# Include an entire tfvars file
!include path/to/variables.tfvars

# Or include specific variable files
network_config: !include config/network.yaml
tags: !include config/common-tags.yaml

This is particularly useful when:

  • Migrating from native Terraform with existing .tfvars files
  • Sharing variable definitions across multiple components
  • Keeping large configuration blocks in separate files

!terraform.output - Reference Component Outputs

Read outputs from other Terraform components:

vars:
vpc_id: !terraform.output vpc/vpc_id
subnet_ids: !terraform.output vpc/private_subnet_ids

!terraform.state - Access Remote State

Access values from Terraform state with more control:

vars:
# From same stack
vpc_id: !terraform.state vpc vpc_id

# From different stack
shared_vpc_id: !terraform.state shared-services/network vpc vpc_id

!store - Read from External Stores

Read values from external key-value stores:

vars:
api_key: !store ssm/prod app api_key
db_password: !store vault/secrets database password

!env - Read Environment Variables

Pass through environment variables:

vars:
aws_region: !env AWS_REGION
deploy_env: !env DEPLOY_ENV, development # With default

!exec - Execute Commands

Execute shell commands and use their output:

vars:
git_commit: !exec git rev-parse HEAD
current_user: !exec whoami

For the complete list of YAML functions, see YAML Functions.

Best Practices

  1. Use Catalog Defaults: Define common variable patterns in stacks/catalog/ and import them.

  2. Keep Variables DRY: Set shared values at higher levels and only override what's different at lower levels.

  3. Use Meaningful Names: Variable names should match your Terraform variable names for clarity.

  4. Document Required Variables: Use abstract components to enforce required variables through inheritance.

  5. Avoid Duplication: If you find yourself repeating the same variables, consider using imports or inheritance.