Skip to main content

Configure Environment Variables

The env section defines environment variables that are set when executing your components. Environment variables can be configured at the global level, component-type level, or component level, and are deep-merged across the inheritance chain.

Use Cases

  • Cloud Provider Configuration: Set AWS_PROFILE, AWS_REGION, or other provider-specific environment variables.
  • Terraform Debugging: Enable TF_LOG for debugging or TF_CLI_CONFIG_FILE for custom CLI configuration.
  • Tool Configuration: Configure paths and settings for external tools used by your components.
  • Secrets Injection: Pass secrets from environment to components (though consider using auth for credentials).

Configuration Scopes

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

Global Level

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

# stacks/orgs/acme/plat/prod/us-east-1.yaml
env:
AWS_PROFILE: acme-prod
AWS_REGION: us-east-1

Component-Type Level

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

# stacks/orgs/acme/plat/prod/_defaults.yaml
terraform:
env:
TF_CLI_CONFIG_FILE: /path/to/terraformrc
TF_PLUGIN_CACHE_DIR: /path/to/plugin-cache

helmfile:
env:
HELM_CACHE_HOME: /path/to/helm-cache

ansible:
env:
ANSIBLE_HOST_KEY_CHECKING: "false"

Component Level

Environment variables defined within a component override all higher-level settings:

# stacks/orgs/acme/plat/prod/us-east-1.yaml
components:
terraform:
vpc:
env:
TF_LOG: DEBUG
TF_LOG_PATH: /tmp/vpc-terraform.log

Including Dotenv Files

Use !include to load a dotenv file directly into a stack env section:

stacks/orgs/acme/plat/dev/us-east-1.yaml
env: !include .env

Use YAML merge keys when you want to include dotenv values and also define inline overrides. The << key is YAML's merge-key syntax, the same YAML mechanism commonly used with anchors and aliases:

stacks/orgs/acme/plat/dev/us-east-1.yaml
env:
<<: !include .env
AWS_REGION: us-east-2

Atmos parses .env, .env.*, and *.env files as dotenv key/value files when they are included with !include. The included values become a map, so standard YAML merge behavior applies: keys written directly under env override keys loaded from the dotenv file.

Dotenv includes can be used at any stack env scope:

terraform:
env:
<<: !include ./terraform.env
TF_IN_AUTOMATION: "true"

components:
terraform:
vpc:
env:
<<: !include ./vpc.env
TF_LOG: DEBUG

You can layer multiple dotenv files with a YAML merge sequence:

env:
<<:
- !include .env.local
- !include .env
AWS_REGION: us-east-2

YAML merge sequence precedence is earlier item wins. In the example above, .env.local has higher precedence than .env, so .env.local overrides .env. Keys written directly under env, such as AWS_REGION, override all merged dotenv values.

Local dotenv paths follow the existing !include resolution rules. Use ./ or ../ for paths relative to the YAML file containing the include; bare local paths such as .env follow Atmos' normal current/base-path lookup for includes. Absolute paths are honored.

Use !include.raw when you need the raw file contents instead of parsed dotenv values. Atmos does not automatically load dotenv files, and it does not load or execute .envrc files.

Merge Behavior

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

  1. Global env: (applies to all components)
  2. Component-type terraform.env: / helmfile.env: / packer.env: / ansible.env: (applies to all components of that type)
  3. Component components.terraform.<name>.env (applies to a specific component)

Unlike vars, environment variables are simple key-value pairs and are merged shallowly—more specific values replace less specific ones for the same key.

Example

stacks/catalog/defaults.yaml
# Global defaults
env:
AWS_SDK_LOAD_CONFIG: "true"
stacks/orgs/acme/plat/prod/_defaults.yaml
# Production defaults
env:
AWS_PROFILE: acme-prod
TF_IN_AUTOMATION: "true"
stacks/orgs/acme/plat/prod/us-east-1.yaml
import:
- catalog/defaults
- orgs/acme/plat/prod/_defaults

env:
AWS_REGION: us-east-1

components:
terraform:
vpc:
env:
TF_LOG: TRACE

The resulting env for the vpc component would be:

env:
AWS_SDK_LOAD_CONFIG: "true" # From catalog/defaults
AWS_PROFILE: acme-prod # From prod/_defaults
TF_IN_AUTOMATION: "true" # From prod/_defaults
AWS_REGION: us-east-1 # From stack file
TF_LOG: TRACE # From component

Common Environment Variables

Terraform

TF_LOG
Set log level (TRACE, DEBUG, INFO, WARN, ERROR).
TF_LOG_PATH
Path to write Terraform logs.
TF_CLI_CONFIG_FILE
Path to Terraform CLI configuration file.
TF_PLUGIN_CACHE_DIR
Directory to cache provider plugins.
TF_IN_AUTOMATION
Suppress prompts when running in automation.
TF_INPUT
Set to false to disable interactive prompts.

AWS

AWS_PROFILE
AWS CLI profile to use.
AWS_REGION
Default AWS region.
AWS_DEFAULT_REGION
Fallback AWS region.
AWS_SDK_LOAD_CONFIG
Load settings from ~/.aws/config.

Helmfile

HELM_CACHE_HOME
Directory for Helm cache.
HELM_CONFIG_HOME
Directory for Helm configuration.
HELM_DATA_HOME
Directory for Helm data.

Ansible

ANSIBLE_HOST_KEY_CHECKING
Disable SSH host key checking (set to false).
ANSIBLE_FORCE_COLOR
Force colored output (set to true).
ANSIBLE_CONFIG
Path to Ansible configuration file.
ANSIBLE_VAULT_PASSWORD_FILE
Path to Ansible Vault password file.

Using Templates in Environment Variables

Environment variables support Go templates for dynamic values:

env:
TF_LOG_PATH: "/tmp/{{ .namespace }}-{{ .environment }}-{{ .stage }}.log"
KUBECONFIG: "{{ env \"HOME\" }}/.kube/{{ .stage }}-config"

YAML Functions for Dynamic Values

Atmos provides YAML functions that can dynamically set environment variable values at runtime.

!env - Read from Environment

The !env function reads values from the current environment:

env:
# Pass through an existing environment variable
AWS_PROFILE: !env AWS_PROFILE

# Use a default if the variable is not set
TF_LOG: !env TF_LOG, INFO

This is useful for:

  • Passing through environment variables from CI/CD systems
  • Inheriting local developer settings
  • Providing sensible defaults

!exec - Execute Commands

The !exec function executes shell commands and uses their output as values. This is powerful for integrating with secret managers and credential tools:

env:
# GitHub CLI - get authentication token
GITHUB_TOKEN: !exec gh auth token

# 1Password CLI - retrieve secrets
DATABASE_PASSWORD: !exec op read "op://vault/database/password"
API_KEY: !exec op read "op://vault/api/key"

# AWS Secrets Manager via CLI
DB_CONNECTION_STRING: !exec aws secretsmanager get-secret-value --secret-id prod/db --query SecretString --output text

# HashiCorp Vault
VAULT_SECRET: !exec vault kv get -field=value secret/myapp/config

Combining Functions with Templates

You can combine YAML functions with Go templates for powerful dynamic configuration:

env:
# Dynamic secret path based on environment
DB_PASSWORD: !exec op read "op://{{ .stage }}/database/password"

# GitHub token for the current environment
GITHUB_TOKEN: !exec gh auth token

# AWS profile from environment with fallback
AWS_PROFILE: !env AWS_PROFILE, {{ .namespace }}-{{ .stage }}

Common CLI Integrations

GitHub CLI (gh)

env:
GITHUB_TOKEN: !exec gh auth token
GH_REPO: !exec gh repo view --json nameWithOwner -q .nameWithOwner

1Password CLI (op)

env:
# Read individual fields
API_KEY: !exec op read "op://Private/API Credentials/api_key"
API_SECRET: !exec op read "op://Private/API Credentials/api_secret"

# Read from specific vault
DB_PASSWORD: !exec op read "op://Production/Database/password"

AWS CLI

env:
# Get secret from Secrets Manager
SECRET_VALUE: !exec aws secretsmanager get-secret-value --secret-id my-secret --query SecretString --output text

# Get parameter from SSM
CONFIG_VALUE: !exec aws ssm get-parameter --name /app/config --with-decryption --query Parameter.Value --output text

HashiCorp Vault

env:
VAULT_TOKEN: !exec vault token lookup -format=json | jq -r .data.id
APP_SECRET: !exec vault kv get -field=secret secret/data/myapp

Best Practices

  1. Use Profiles Over Credentials: Set AWS_PROFILE rather than embedding AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

  2. Enable Automation Mode: Set TF_IN_AUTOMATION=true in CI/CD environments to suppress interactive prompts.

  3. Centralize Common Settings: Define shared environment variables in catalog defaults and import them.

  4. Use Component-Level Sparingly: Only override environment variables at the component level when that component has unique requirements.

  5. Consider Auth for Credentials: For complex credential management, use the auth section instead of environment variables.