# Atmos Components

> Component architecture: Terraform root modules, remote source provisioning, abstract components, component inheritance, versioning, mixins, catalog patterns

- Skill: `cloudposse/atmos-components` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add cloudposse/atmos-components`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cloudposse/atmos-components/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: cloudposse (https://skillmd.com/u/cloudposse)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cloudposse/atmos-components

---


# Atmos Component Architecture

Components are the building blocks of infrastructure in Atmos. Each component is an opinionated, reusable unit of infrastructure-as-code -- typically a Terraform root module -- that solves a specific problem. Atmos separates the component implementation (code) from its configuration (stack manifests), enabling one implementation to be deployed many times with different settings.

## What Components Are

In Atmos, a component consists of two parts:

1. **Implementation** -- The infrastructure code itself (a Terraform root module, Helmfile, or Packer template) stored in the `components/` directory.
2. **Configuration** -- The settings that customize how the component is deployed, defined in stack manifests under the `components` section.

This separation is fundamental: you write the Terraform module once, then configure it differently for each environment, region, and account through stack YAML files.

## Component Types

Atmos natively supports three component types:

| Type | Implementation Location | Purpose |
|------|------------------------|---------|
| Terraform / OpenTofu | `components/terraform/<name>/` | Provision cloud infrastructure resources |
| Helmfile | `components/helmfile/<name>/` | Deploy Helm charts to Kubernetes clusters |
| Packer | `components/packer/<name>/` | Build machine images (AMIs, VM images) |

Terraform is by far the most common type. Custom commands can extend Atmos to support any tooling.

## Directory Structure

Components are stored in your project's `components/` directory, organized by type:

```text
components/
  terraform/
    vpc/
      main.tf
      variables.tf
      outputs.tf
      versions.tf
    eks/
      cluster/
        main.tf
        variables.tf
        outputs.tf
    s3-bucket/
      main.tf
      variables.tf
      outputs.tf
    iam-role/
      main.tf
      variables.tf
      outputs.tf
  helmfile/
    nginx-ingress/
      helmfile.yaml
    cert-manager/
      helmfile.yaml
  packer/
    ubuntu-base/
      template.pkr.hcl
```

The base path for Terraform components is configured in `atmos.yaml`:

```yaml
components:
  terraform:
    base_path: "components/terraform"
```

Nested directories are supported. A component at `components/terraform/eks/cluster/` is referenced as `eks/cluster` in stack configurations.

## Component Configuration in Stacks

Components are configured in the `components` section of stack manifests:

```yaml
components:
  terraform:
    vpc:
      metadata:
        component: vpc           # Points to components/terraform/vpc/
      vars:
        cidr_block: "10.0.0.0/16"
        availability_zones:
          - us-east-1a
          - us-east-1b
      settings:
        validation:
          check-cidr:
            schema_type: jsonschema
            schema_path: schemas/vpc.json

    eks-cluster:
      metadata:
        component: eks/cluster   # Points to components/terraform/eks/cluster/
      vars:
        cluster_name: prod-eks
        kubernetes_version: "1.28"
```

Each component configuration can include these sections:

| Section | Purpose |
|---------|---------|
| `metadata` | Component location, inheritance, type, and Atmos behavior |
| `vars` | Input variables passed to Terraform/Helmfile/Packer |
| `env` | Environment variables set during execution |
| `settings` | Integration metadata such as Atlantis, validation, and custom settings |
| `dependencies` | Component, file, folder, and tool dependencies |
| `hooks` | Lifecycle event handlers |
| `backend` / `backend_type` | Terraform state backend configuration |
| `providers` | Terraform provider configuration |
| `command` | Override the executable (e.g., `tofu` instead of `terraform`) |
| `auth` | Authentication identity reference |

## Dependencies

Use `dependencies.components` for component ordering and affected/dependent analysis:

```yaml
components:
  terraform:
    app:
      dependencies:
        components:
          - component: vpc
          - component: database
            stack: plat-ue2-prod
          - kind: file
            path: configs/app.yaml
          - kind: folder
            path: src/lambda
```

Use `dependencies.tools` for runtime CLIs at global, component-type, or per-component scope; Atmos auto-installs and injects them, so do not add a separate install step.

Do not add new `settings.depends_on` examples. If a repository already uses that legacy field,
recommend migrating it to `dependencies.components`.

## Source Provisioning and Workdirs

Components can declare `source` in stack config for just-in-time provisioning from Git, OCI, S3,
HTTP, or local paths. Treat source provisioning as part of component configuration: it controls
how the component implementation is fetched, while `vars`, `env`, `backend`, and other sections
control how that implementation is run.

Use component source provisioning when different stacks need different remote component versions,
or when the repository should not commit the fetched implementation. When source provisioning is
used, prefer `provision.workdir.enabled: true` so each component-stack instance gets an isolated
execution directory.

```yaml
components:
  terraform:
    vpc:
      source: "github.com/cloudposse-terraform-components/aws-vpc.git?ref=1.450.0"
      provision:
        workdir:
          enabled: true
```

Atmos provisions sources automatically before Terraform commands when needed. Use explicit source
commands when an agent needs to inspect, refresh, or clean the fetched implementation:

```shell
atmos terraform source pull vpc --stack dev
atmos terraform source describe vpc --stack dev
atmos terraform source list --stack dev
atmos terraform source delete vpc --stack dev
atmos list sources
```

For protected sources, route identity and provider details to `atmos-auth`. For checked-in copies
of remote components, route to `atmos-vendoring`; vendoring and source provisioning are alternatives
for obtaining component implementation code.

## Abstract vs Real Components

### Abstract Components

Mark a component as `metadata.type: abstract` to create a blueprint that cannot be deployed directly:

```yaml
components:
  terraform:
    vpc/defaults:
      metadata:
        type: abstract
        component: vpc
      vars:
        enabled: true
        nat_gateway_enabled: true
        max_subnet_count: 3
        vpc_flow_logs_enabled: true
```

Abstract components:
- Cannot be provisioned with `atmos terraform apply` (Atmos returns an error).
- Do not appear in `atmos describe stacks` output by default.
- Serve as base configurations for real components to inherit from.

### Real Components (Default)

If `metadata.type` is not specified, the component is `real` and can be deployed:

```yaml
components:
  terraform:
    vpc:
      metadata:
        inherits:
          - vpc/defaults
      vars:
        vpc_cidr: "10.0.0.0/16"
```

## Component Inheritance

### Single Inheritance

Use `metadata.inherits` to inherit configuration from a base component:

```yaml
components:
  terraform:
    vpc/defaults:
      metadata:
        type: abstract
        component: vpc
      vars:
        enabled: true
        nat_gateway_enabled: true

    vpc:
      metadata:
        inherits:
          - vpc/defaults
      vars:
        nat_gateway_enabled: false   # Override inherited value
```

The derived component receives all `vars`, `env`, `settings`, `hooks`, `backend`, `providers`, and `command` from the base, then its own values are deep-merged on top.

### Multiple Inheritance

A component can inherit from multiple bases. Entries are processed in order with later entries having higher precedence:

```yaml
components:
  terraform:
    rds:
      metadata:
        component: rds
        inherits:
          - base/defaults       # Applied first
          - base/logging        # Applied second
          - base/production     # Applied last (highest base precedence)
      vars:
        name: my-database       # Inline has highest precedence
```

This enables composing "traits" -- reusable abstract components that represent independent configuration concerns (logging, security, sizing, environment settings).

### metadata.component

The `metadata.component` field maps an Atmos component name to its Terraform root module directory:

```yaml
components:
  terraform:
    vpc-main:
      metadata:
        component: vpc          # Uses components/terraform/vpc/
      vars:
        name: main-vpc

    vpc-isolated:
      metadata:
        component: vpc          # Same Terraform module
      vars:
        name: isolated-vpc
        enable_internet_gateway: false
```

Both components use the same Terraform code but maintain separate state files and configurations. This is the **multiple component instances** pattern.

## Multiple Component Instances

Deploy the same Terraform module multiple times in the same stack by giving each instance a unique Atmos component name:

```yaml
components:
  terraform:
    vpc/1:
      metadata:
        component: vpc
        inherits:
          - vpc/defaults
      vars:
        name: vpc-1
        ipv4_primary_cidr_block: 10.9.0.0/18

    vpc/2:
      metadata:
        component: vpc
        inherits:
          - vpc/defaults
      vars:
        name: vpc-2
        ipv4_primary_cidr_block: 10.10.0.0/18
```

Each instance has its own Terraform state and is independently deployable:

```bash
atmos terraform apply vpc/1 -s plat-ue2-prod
atmos terraform apply vpc/2 -s plat-ue2-prod
```

## metadata Section Fields

All fields available in the `metadata` section:

| Field | Type | Description |
|-------|------|-------------|
| `component` | string | Path to Terraform root module relative to components base path |
| `inherits` | list | List of component names to inherit configuration from |
| `type` | string | `abstract` (non-deployable) or `real` (default, deployable) |
| `name` | string | Stable logical identity for workspace key prefix |
| `enabled` | boolean | Enable or disable the component (default: true) |
| `locked` | boolean | Prevent modifications to the component |
| `terraform_workspace` | string | Explicit workspace name override |
| `terraform_workspace_pattern` | string | Workspace name pattern with tokens |
| `custom` | map | User-defined metadata (preserved, not interpreted by Atmos) |

## Catalog Patterns

The `stacks/catalog/` directory is the conventional location for reusable component configurations:

```text
stacks/
  catalog/
    vpc/
      _defaults.yaml          # Abstract base for all VPC instances
    eks/
      _defaults.yaml
      cluster.yaml
    s3-bucket/
      _defaults.yaml
    iam-role/
      _defaults.yaml
```

Catalog files define abstract components with sensible defaults. Top-level stacks import from the catalog and override only what differs:

```yaml
# stacks/catalog/vpc/_defaults.yaml
components:
  terraform:
    vpc/defaults:
      metadata:
        type: abstract
        component: vpc
      vars:
        enabled: true
        nat_gateway_enabled: true
        max_subnet_count: 3
```

```yaml
# stacks/orgs/acme/plat/prod/us-east-1.yaml
import:
  - catalog/vpc/_defaults

components:
  terraform:
    vpc:
      metadata:
        inherits:
          - vpc/defaults
      vars:
        vpc_cidr: "10.0.0.0/16"
```

## Mixins for Reusable Configuration

Mixins are small, focused configuration snippets that alter component behavior. They are typically stored in `stacks/mixins/` and imported into stacks:

```text
stacks/
  mixins/
    region/
      us-east-1.yaml
      us-east-2.yaml
      us-west-2.yaml
    stage/
      dev.yaml
      staging.yaml
      prod.yaml
    tenant/
      plat.yaml
```

```yaml
# stacks/mixins/region/us-east-2.yaml
vars:
  region: us-east-2
  environment: ue2
```

```yaml
# stacks/orgs/acme/plat/prod/us-east-2.yaml
import:
  - mixins/region/us-east-2
  - mixins/stage/prod
  - catalog/vpc/_defaults
```

## Remote State Access Between Components

Components can access outputs from other components using the `remote-state` module or YAML functions:

```yaml
# Using YAML functions (state access is the fastest option)
components:
  terraform:
    eks-cluster:
      vars:
        vpc_id: !terraform.state vpc vpc_id
        subnet_ids: !terraform.state vpc private_subnet_ids
```

For a cold `terraform plan --all`, upstream state may not exist yet even though component
dependencies establish deployment order. Put a provider-valid fallback in the YQ expression; the
real state value supersedes it after the upstream component deploys:

```yaml
components:
  terraform:
    eks-cluster:
      vars:
        vpc_id: !terraform.state vpc '.vpc_id // "vpc-mock"'
```

For the Terraform-side approach, use the `remote-state` module:

```hcl
# In components/terraform/eks/cluster/remote-state.tf
module "vpc" {
  source  = "cloudposse/stack-config/yaml//modules/remote-state"
  version = "1.5.0"

  component = "vpc"
}
```

This reads the VPC component's Terraform outputs from the same or a different stack.

## Best Practices

1. **One concern per component**: Each component should provision a single logical piece of infrastructure (VPC, EKS cluster, database). Do not combine resources with different lifecycles.
2. **Use abstract base components**: Define catalog defaults as `abstract` components and inherit from them.
3. **Keep inheritance chains shallow**: Limit to 2-3 levels for readability and debuggability.
4. **Use metadata.component for instances**: When deploying the same module multiple times, use `metadata.component` to share the implementation.
5. **Use metadata.name for versioning**: Set `metadata.name` to maintain stable Terraform workspace key prefixes across version upgrades.
6. **Design for reuse**: Components should accept configuration through variables, not hard-coded values. Use the catalog pattern to define sensible defaults.
7. **Use `atmos describe component`**: Always verify the resolved configuration before applying changes.

```bash
atmos describe component vpc -s plat-ue2-prod
```

## References

- [references/component-types.md](references/component-types.md) -- Detailed reference on component types, metadata fields, abstract components, inheritance chains, and versioning
- [references/examples.md](references/examples.md) -- Concrete configuration examples for VPC, EKS, S3, IAM patterns

