원클릭으로
developing-stacks
// Use when deploying components via Atmos stacks, configuring stack YAML, or understanding inheritance patterns. Covers catalog defaults, abstract components, stack imports, and how to wire components into target stacks.
// Use when deploying components via Atmos stacks, configuring stack YAML, or understanding inheritance patterns. Covers catalog defaults, abstract components, stack imports, and how to wire components into target stacks.
Use when creating new Terraform/OpenTofu components or modifying existing ones. Covers required files, catalog defaults, stack configuration, and naming conventions.
Use when authenticating with AWS via Atmos. Covers ATMOS_PROFILE setup, SSO login, and how Atmos automatically assumes the correct identity per stack. Use for authentication setup, SSO login issues, and permission errors.
Building, rendering library docs, and deploying docs.cloudposse.com. Use when working with the Docusaurus build process or regenerating auto-generated content.
Writing standards, React components, and MDX patterns for docs.cloudposse.com. Use when creating or editing documentation content.
CSS styles, color themes, and visual conventions for docs.cloudposse.com. Use when styling components, mermaid diagrams, or working with site theming.
Use when fixing legacy account-map component references or creating new components. Covers migration from dynamic account-map lookups to static account_map variable. Use when you see account-map remote-state references or need to set up provider configuration for a new component.
| name | developing-stacks |
| description | Use when deploying components via Atmos stacks, configuring stack YAML, or understanding inheritance patterns. Covers catalog defaults, abstract components, stack imports, and how to wire components into target stacks. |
Scope: This skill is specific to the acme infrastructure repository. It documents the stack structure, naming conventions, and deployment patterns used here. For generic component development, see
developing-components.
Guide for configuring Atmos stacks to deploy Terraform components across environments.
This repository uses a multi-tenant, multi-stage stack structure:
stacks/
├── orgs/acme/ # Organization root (namespace: acme)
│ ├── _defaults.yaml # Org-wide defaults (namespace, backend, account_map)
│ ├── core/ # Core tenant (shared infrastructure)
│ │ ├── _defaults.yaml # Tenant defaults (tenant: core)
│ │ ├── root/ # Root account stage
│ │ │ ├── _defaults.yaml # Stage defaults + auth identity
│ │ │ └── global-region/ # Global region (us-east-1)
│ │ │ └── foundation.yaml
│ │ ├── auto/ # Automation account
│ │ ├── artifacts/ # Artifacts account (ECR, S3)
│ │ ├── audit/ # Audit/logging account
│ │ ├── network/ # Network account (TGW, VPN, DNS)
│ │ └── security/ # Security account
│ └── plat/ # Platform tenant (workloads)
│ ├── _defaults.yaml # Tenant defaults (tenant: plat)
│ ├── dev/ # Dev stage
│ │ ├── _defaults.yaml # Stage defaults + auth identity
│ │ ├── global-region/ # Global resources (IAM)
│ │ │ └── foundation.yaml
│ │ └── us-east-1/ # Primary region
│ │ ├── foundation.yaml # VPC, networking
│ │ ├── platform.yaml # ECS/EKS, databases
│ │ └── app.yaml # Application resources
│ ├── staging/ # Staging stage
│ ├── prod/ # Production stage
│ └── sandbox/ # Sandbox stage
├── catalog/ # Component defaults library
│ ├── vpc/defaults.yaml
│ ├── ecs/defaults.yaml
│ ├── eks/cluster/defaults.yaml
│ └── ...
└── mixins/ # Reusable fragments
├── region/us-east-1.yaml
└── stage/dev.yaml
Stack name format: {namespace}-{tenant}-{region_short}-{stage}
Examples for this repository:
acme-core-use1-root - Core root account in us-east-1acme-plat-use1-dev - Platform dev in us-east-1acme-plat-use1-prod - Platform prod in us-east-1Define component defaults in stacks/catalog/<component>/defaults.yaml. These are imported into target stacks.
# stacks/catalog/vpc/defaults.yaml
components:
terraform:
vpc/defaults:
metadata:
type: abstract # Prevents direct deployment
vars:
name: vpc
availability_zones: ["a", "b", "c"]
public_subnets_enabled: true
nat_gateway_enabled: true
max_subnet_count: 3
Key points:
type: abstract to prevent accidental deployment of the base configuration/defaults suffix (e.g., vpc/defaults) to indicate it's a baseImport the catalog and inherit from the abstract component in your target stack:
# stacks/orgs/acme/plat/dev/us-east-1/foundation.yaml
import:
- orgs/acme/plat/dev/_defaults
- mixins/region/us-east-1
- catalog/vpc/defaults
components:
terraform:
vpc:
metadata:
component: vpc # Points to components/terraform/vpc
inherits:
- vpc/defaults # Inherits from the abstract component
vars:
ipv4_primary_cidr_block: 10.2.0.0/16 # Dev environment CIDR
Inheritance merging:
vars, settings, env, backend are deep-mergedvars override inherited varsAbstract components (type: abstract) serve as base configurations that cannot be deployed directly.
# Abstract - cannot be deployed
vpc/defaults:
metadata:
type: abstract
vars:
nat_gateway_enabled: true
# Real - can be deployed (inherits from abstract)
vpc:
metadata:
component: vpc
inherits:
- vpc/defaults
vars:
ipv4_primary_cidr_block: 10.0.0.0/16
Use abstract components when:
s3-bucket/logging, s3-bucket/public)Components can inherit from multiple bases. Order matters - later items override earlier ones.
components:
terraform:
my-ecs-service:
metadata:
component: ecs-service
inherits:
- ecs-service/defaults # Base defaults
- ecs-service/web # Web-specific settings (overrides defaults)
vars:
service_name: my-app # Final override
The _defaults.yaml files create an inheritance chain:
# stacks/orgs/acme/_defaults.yaml (org level)
vars:
namespace: acme
terraform:
backend_type: s3
backend:
s3:
bucket: acme-core-use1-root-tfstate
# ...
# stacks/orgs/acme/plat/_defaults.yaml (tenant level)
import:
- orgs/acme/_defaults
vars:
tenant: plat
# stacks/orgs/acme/plat/dev/_defaults.yaml (stage level)
import:
- orgs/acme/plat/_defaults
- mixins/stage/dev
auth:
identities:
plat-dev/terraform:
default: true
ls stacks/catalog/<component>/
If defaults exist, skip to Step 3.
# stacks/catalog/<component>/defaults.yaml
components:
terraform:
<component>/defaults:
metadata:
type: abstract
vars:
enabled: true
# Add sensible defaults
Edit the appropriate stack file (foundation.yaml, platform.yaml, app.yaml, etc.):
import:
# ... existing imports
- catalog/<component>/defaults # Add this
components:
terraform:
<component>:
metadata:
component: <component>
inherits:
- <component>/defaults
vars:
# Environment-specific overrides only
# Validate the stack configuration
atmos validate stacks
# See the resolved configuration (example for dev)
atmos describe component <component> -s acme-plat-use1-dev
# Plan the deployment
atmos terraform plan <component> -s acme-plat-use1-dev
Stack files are organized by layer:
| File | Purpose | Examples |
|---|---|---|
foundation.yaml | Core infrastructure (VPC, DNS, TGW) | vpc, dns-delegated, bastion |
platform.yaml | Platform services (ECS, RDS, monitoring) | ecs, aurora-postgres, alb |
app.yaml | Application-specific resources | ecs-service, s3-bucket |
network.yaml | Network-specific (routes, peering) | vpc-routes, tgw-attachment |
monitor.yaml | Observability (CloudWatch, Grafana) | managed-grafana, alarms |
When deploying multiple instances of the same component for different purposes, organize the catalog with abstract defaults and purpose-specific files that inherit from them:
stacks/catalog/
└── <component>/
├── defaults.yaml # Abstract base component (not deployed directly)
└── <purpose>.yaml # Purpose-specific configuration
Abstract defaults file (stacks/catalog/<component>/defaults.yaml):
components:
terraform:
<component>/defaults:
metadata:
type: abstract # Not deployed directly
component: <component> # Points to Terraform component
vars:
enabled: true
# Organization-wide defaults for this component
Purpose-specific catalog file (stacks/catalog/<component>/<purpose>.yaml):
import:
- catalog/<component>/defaults
components:
terraform:
<component>/<purpose>:
metadata:
component: <component> # Points to Terraform component
inherits:
- <component>/defaults # Inherits from abstract component
vars:
# Only include values that differ from defaults (keep it DRY)
name: <purpose>-specific-name
some_setting: override-value # Overrides default
Import in target stack:
import:
- catalog/<component>/<purpose>
Deploy:
atmos terraform plan <component>/<purpose> -s acme-plat-use1-dev
# stacks/catalog/vpc/defaults.yaml
components:
terraform:
vpc/defaults:
metadata:
type: abstract
vars:
# No CIDR here - must be specified per environment
# stacks/orgs/acme/plat/dev/us-east-1/foundation.yaml
components:
terraform:
vpc:
metadata:
inherits: [vpc/defaults]
vars:
ipv4_primary_cidr_block: 10.2.0.0/16
# stacks/orgs/acme/plat/prod/us-east-1/foundation.yaml
components:
terraform:
vpc:
metadata:
inherits: [vpc/defaults]
vars:
ipv4_primary_cidr_block: 10.0.0.0/16
Use !terraform.state to wire outputs between components:
# stacks/catalog/ecs/defaults.yaml
components:
terraform:
ecs/defaults:
metadata:
type: abstract
vars:
vpc_id: !terraform.state vpc vpc_id
subnet_ids: !terraform.state vpc private_subnet_ids
See the atmos-functions skill for more details.
Deploy multiple instances by using different component names:
components:
terraform:
# Primary VPC
vpc:
metadata:
component: vpc
inherits: [vpc/defaults]
vars:
ipv4_primary_cidr_block: 10.0.0.0/16
# Secondary VPC for isolation
vpc/isolated:
metadata:
component: vpc
inherits: [vpc/defaults]
vars:
name: vpc-isolated
ipv4_primary_cidr_block: 10.100.0.0/16
# See fully resolved configuration
atmos describe component <component> -s acme-plat-use1-dev
# See all components in a stack
atmos describe stacks -s acme-plat-use1-dev
# Validate all stacks
atmos validate stacks
For more debugging techniques, see the debugging-atmos skill.