Configuring Components in Stacks
Stacks are used to compose multiple components together and provide their configuration. The schema is the same for all stacks, but the configuration can be different. Use a combination of imports, inheritance, and catalogs for a template-free way to reuse configuration and override values when needed.
Component Schema
A Component consists of the infrastructure as code business logic (e.g. a Terraform "root" module) as well as the configuration of that component. The configuration of a component is stored in a Stack configuration.
To configure a Component in a Stack, you define the component in the components section of the Stack configuration.
-
Terraform Component is a simply a Terraform Root Module that consists of the resources defined in the
.tffiles in a working directory (e.g. components/terraform/infra/vpc) -
Component Configuration provides configuration (variables and other settings) for a type of component (e.g. a Terraform component) and is defined in one or more YAML stack config files (which are called Atmos stacks)
Terraform Schema
The schema of an Atmos Terraform Component in an Atmos Stack is as follows:
components:
terraform:
# the slug of the component
example:
# configuration specific to atmos
metadata:
# Components can be of type "real" (default) or "abstract"
type: real
# This is the directory path of the component.
# In this example, we're referencing a component in the `components/terraform/stable/example` folder.
component: stable/example
# We can leverage multiple inheritance to sequentially deep merge multiple configurations
inherits:
- example-defaults
# Settings are where we store configuration related to integrations.
# It's a freeform map; anything can be placed here.
settings:
spacelift: {}
# Define the terraform variables, which will get deep-merged and exported to a `.tfvars` file by atmos.
vars:
enabled: true
name: superduper
nodes: 10
Terraform Attributes
vars(optional)- The
varssection is a free-form map. Use component validation to enforce policies. vars.namespace(optional)This is an optional
terraform-null-labelconvention.The namespace of all stacks. Typically, there will be one namespace for the organization.
Example:
vars:
namespace: acmevars.tenant(optional)This is an optional
terraform-null-labelconvention.In a multi-tenant configuration, the tenant represents a single
tenant. By convention, we typically recommend that every tenant have its own Organizational Unit (OU).Example:
vars:
tenant: platformvars.stage(optional)This is an optional
terraform-null-labelconvention.The
stageis where workloads run. See our glossary for disambiguation.Example:
vars:
# Production stage
stage: prodvars.environment(optional)This is an optional
terraform-null-labelconvention.The
environmentis used for location where things run. See our glossary for disambiguation.Example:
vars:
# us-east-1
environment: ue1metadata(optional)- The
metadatasection extends functionality of the component. settings- The
settingsblock is a free-form map used to pass configuration information to integrations.
Helmfile Schema
The schema of an Atmos Helmfile Component in an Atmos Stack is as follows:
components:
helmfile:
# the slug of the component
example:
# configuration specific to atmos
metadata:
# Components can be of type "real" (default) or "abstract"
type: real
# This is the directory path of the component.
# In this example, we're referencing a component in the `components/terraform/stable/example` folder.
component: stable/example
# We can leverage multiple inheritance to sequentially deep merge multiple configurations
inherits:
- example-defaults
# Define the Helmfile variables, which will get deep-merged into the Helmfile configuration.
vars:
enabled: true
release_name: my-release
chart_version: "1.2.3"
Helmfile Attributes
vars(optional)- The
varssection is a free-form map. Use component validation to enforce policies. vars.namespace(optional)This is an optional
terraform-null-labelconvention.The namespace of all stacks. Typically, there will be one namespace for the organization.
Example:
vars:
namespace: acmemetadata(optional)- The
metadatasection extends functionality of the component. settings- The
settingsblock is a free-form map used to pass configuration information to integrations.
Types of Components
In Atmos, each component configuration defines its type through the metadata.type parameter. This defines how the component behaves—whether it can be used directly to provision resources or serves as a base configuration for other components.
The type of component is expressed in the metadata.type parameter of a given component configuration.
There are two types of components:
real- Think of a
realcomponent as one that can be deployed. It’s fully configured and ready to be provisioned, similar to a "concrete" class in programming. Once defined, you can use it to create resources or services directly in your infrastructure. abstract- An
abstractcomponent is more like a blueprint. It can’t be deployed on its own. Instead, it’s a base configuration that needs to be extended or inherited by other components. This is similar to an "abstract base classes" in programming—it defines reusable configurations, but it’s not complete enough to be deployed directly.
Disabling Components with metadata.enabled
The metadata.enabled parameter controls whether a component is included in deployment. By default, components are enabled. Setting metadata.enabled to false skips the component entirely—no workspace is created, and no Terraform commands are executed. Disabling a component does not cause deletion. It just signals that it's no longer managed by Atmos.
This should not be confused with Cloud Posse's conventions and best practices of
having modules and components define a Terraform input named enabled.
This is a general convention and vars.enabled is not a special variable. Atmos does not treat it differently from any other variable.
Example:
# Disable a component in a specific environment
components:
terraform:
vpc:
metadata:
type: real
enabled: false
vars:
name: primary-vpc
Using the metadata.enabled flag makes it easy to ensure that only the intended components are active in each environment.
Locking Components with metadata.locked
The metadata.locked parameter prevents changes to a component while still allowing read operations. When a component is locked, operations that would modify infrastructure (like terraform apply) are blocked, while read-only operations (like terraform plan) remain available. By default, components are unlocked. Setting metadata.locked to true prevents any change operations.
Locking a component does not affect the Terraform state. It's intended as a way to communicate intention and prevent accidental changes to sensitive or critical infrastructure.
Example:
# Lock a production database component to prevent accidental changes
components:
terraform:
rds:
metadata:
locked: true
vars:
name: production-database
Using the metadata.locked flag helps protect critical infrastructure from unintended modifications while still allowing teams to inspect and review the configuration.
Versioning Components with metadata.component
The metadata.component parameter specifies which component implementation to use when provisioning infrastructure. This is how you manage component versions in Atmos—by pointing to different component folders organized by version.
By default, if metadata.component is not specified, Atmos uses the component's name as the path. However, you can explicitly reference different versions or implementations by setting this parameter to point to versioned component folders.
Continuous Version Deployment
All environments point to the same component folder and converge to the same version. Versions are rolled out to each environment with release controls like approval gates in your deployment pipeline, decoupling release from deployment. This is the recommended default approach.
- Development
- Staging
- Production
Release Control: Automatically deployed when changes merge to main. No approval required.
# stacks/dev/us-east-1.yaml
components:
terraform:
vpc:
# Points to components/terraform/vpc/
vars:
name: dev-vpc
Release Control: Deployment approved after successful validation in development environment.
# stacks/staging/us-east-1.yaml
components:
terraform:
vpc:
# Points to components/terraform/vpc/ (same component as dev)
vars:
name: staging-vpc
Release Control: Deployment approved after successful validation in staging environment. Manual approval gate enforced by deployment pipeline.
# stacks/prod/us-east-1.yaml
components:
terraform:
vpc:
# Points to components/terraform/vpc/ (same component as dev and staging)
vars:
name: prod-vpc
Release Tracks/Channels
Environments subscribe to named release channels. Versions are rolled out to each environment by promoting them through channels (alpha → beta → prod) as they're validated.
- Development
- Staging
- Production
# stacks/dev/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: alpha/vpc # Subscribe to alpha track
vars:
name: dev-vpc
# stacks/staging/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: beta/vpc # Subscribe to beta track
vars:
name: staging-vpc
# stacks/prod/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: prod/vpc # Subscribe to production track
vars:
name: prod-vpc
Environment-Specific Versions
Each environment has its own component folder. Versions are rolled out to each environment independently, allowing complete divergence when needed.
- Development
- Staging
- Production
# stacks/dev/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: dev/vpc # Development-specific folder
vars:
name: dev-vpc
# stacks/staging/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: staging/vpc # Staging-specific folder
vars:
name: staging-vpc
# stacks/prod/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: prod/vpc # Production-specific folder
vars:
name: prod-vpc
Strict Version Pinning
Each environment pins to an explicit version folder (typically using major.minor versioning). Versions are rolled out to each environment by manually updating version pins with release controls in place.
- Development
- Staging
- Production
Release Control: Manually update version pin in stack configuration, then deploy (with automation).
# stacks/dev/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: vpc/1.3 # Latest version in dev
vars:
name: dev-vpc
Release Control: Manually update version pin in stack configuration, then deploy (with automation).
# stacks/staging/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: vpc/1.2 # Validated version in staging
vars:
name: staging-vpc
Release Control: Manually update version pin in stack configuration, then deploy (with automation).
# stacks/prod/us-east-1.yaml
components:
terraform:
vpc:
metadata:
component: vpc/1.2 # Stable version in production
vars:
name: prod-vpc
The metadata.component parameter is the foundation of Version Management Patterns in Atmos. By organizing components into folders and using metadata.component to reference them, you can implement various versioning strategies:
- Continuous Version Deployment - All environments converge to same component (recommended)
- Release Tracks/Channels - Named channels for progressive rollout
- Folder-Based Versioning - Environment-specific folders
- Strict Version Pinning - SemVer-based explicit versions
See Version Management Patterns to learn how to choose and implement the right versioning strategy for your organization.