CloudFormation Components
Define CloudFormation stacks in stack manifests when you want Atmos to
deploy them alongside Terraform, Helm, Kubernetes, Helmfile, Packer, and
Ansible components. A CloudFormation component describes which template to
deploy, which parameters and capabilities to pass, and how the stack should
behave for each environment — all deployed directly through the AWS SDK for
Go v2, with no aws CLI or cfn/sam/Rain binary dependency.
Available Configuration Sections
CloudFormation components use the same stack sections as other Atmos components, so the stack can inherit values, run hooks, use Auth, declare dependencies, and be included in affected runs.
metadata- Component behavior, inheritance, and base component selection.
vars- Variables available to stack template rendering.
env- Environment variables applied before CloudFormation operations run.
settingsIntegration metadata and legacy dependency settings, including
settings.aws_cloudformation.region(see Region Resolution).hooksLifecycle event handlers.
diff/plan,apply/deploy,delete,drift detect, anddrift describefirebefore/afterevents (before.aws/cloudformation.diff,after.aws/cloudformation.apply, and so on) — every other verb, includingrender,validate,output,fmt,tree,logs,watch,changeset *,get *,stackset *,list,backend *, andsource *, does not fire hook events.sourceJIT provisioning of a remote template before operations run — see Source Provisioning below.
provisionDelivery targets: the account/region direct-deploy default,
kind: aws/s3(template packaging), orkind: git(a Git deployment repository) — all selectable viaapply --target. A fourth kind,kind: aws/stackset, is not selected throughapply --target; it's used exclusively by thestacksetverb group. See Delivery Targets below for the full picture, includingprovision.backend.enabledauto-provisioning.auth- Component-level Atmos Auth providers, identities, and integrations.
dependencies- Cross-component ordering for
--alland--affectedruns.
CloudFormation components do not support a generate: section — there is
no codegen-artifact output the way Terraform generates backend/provider files.
They also do not support a plugins: section — there is no chart-style plugin
system, unlike native Helm.
CloudFormation-Specific Sections
template/path(one required)The CloudFormation template, provided one of two mutually exclusive ways:
template— an inline template body, either a literal string (a|block scalar, YAML or JSON) or a structured YAML map. Because it's inline stack config, it flows through Atmos's own{{ }}templating pipeline before being sent to CloudFormation — file-based templates (path:) do not get this.path— a file reference: the path to a template file, relative to the component directory under the base path.
Setting both is an error.
stack_name- The explicit CloudFormation stack name. There is no legacy name-pattern interpolation — set the name you want directly (Go templates are supported, like any other stack field).
parametersCloudFormation template parameters, as either a YAML map of name to value or a list of
ParameterKey/ParameterValueentries (the AWS CLI and Rain parameter-file format, which also works through!include). Values are normalized at the API boundary: scalars are stringified, and list values are comma-joined to match CloudFormation'sList<Type>/CommaDelimitedListwire format (the API only accepts strings). Any other shape, or a malformed list entry, is an error that names the problem; Atmos never falls back to the template defaults. Atmos config is the source of truth for every parameter on every deploy, the same declarative stance the Terraform component takes toward variables, soUsePreviousValueis not needed in the map form. The list form acceptsUsePreviousValue: true(without aParameterValue) for the rare update that must keep a stack's current value. To use only theParameterssection of a Rain config file, select it with!include rain-config.yaml .Parameters.capabilitiesAcknowledged IAM capabilities:
CAPABILITY_IAM,CAPABILITY_NAMED_IAM, orCAPABILITY_AUTO_EXPAND. Atmos checks each value locally, and an unknown value fails before any AWS call, naming the value and the valid set.tags- A map of
key: valuetags applied to the CloudFormation stack (not to be confused with Atmos's own componenttags/--tagsselection, which is separate). stack_policyProtects specific resources from update during
UpdateStack. Setstack_policy.fileto a stack policy JSON document path, relative to the component directory under the base path. Applied after a successfulapply.role_arn- IAM role ARN that CloudFormation assumes to deploy the stack.
notification_arns- SNS topic ARNs that CloudFormation publishes stack events to.
disable_rollback- Prevents automatic rollback on stack creation failure.
termination_protectionPrevents the stack from being deleted.
atmos aws cloudformation deleterespects this and fails with an actionable hint instead of silently disabling it — pass--disable-termination-protectionto delete anyway. Setting this tofalseand re-applying does not disable protection: apply only ever turns protection on, never off.timeout_in_minutesAccepted for compatibility, but ignored with a warning: the CloudFormation changeset APIs do not support a stack timeout. Atmos stops watching after 60 minutes; this does not cancel the AWS operation.
Example
Inline templates skip the on-disk file entirely and support two forms — a literal string body, or a structured map:
Component Directory Structure
CloudFormation components are located under
components."aws/cloudformation".base_path from atmos.yaml (defaults to
components/cloudformation):
components/cloudformation/
└── vpc/
├── template.yaml
└── stack-policy.json
Source Provisioning
Point a component at a remote template through the top-level source:
section — the same JIT vendoring used by other component types — instead of
committing the template to your infrastructure repository. Two shapes are
supported:
- Directory/subdirectory source
Any go-getter URI (Git, HTTP archive, S3, OCI) pointing at a directory. The component directory (template, stack policy, and any local assets) is vendored, and
path:resolves relative to it, exactly like other component types'source:behavior.components:"aws/cloudformation":vpc:source:uri: github.com/acme/cfn-templates.git//vpc?ref={{ .Version }}version: 1.2.0path: template.yaml- Single-file source
When the
source.uriresolves to exactly one file — a bare template URI, with no surrounding directory structure — Atmos fetches it directly as the component'spath:file. A CloudFormation component is often exactly one file, and demanding a directory structure around it would be ceremony.components:"aws/cloudformation":dns:stack_name: dns-devsource:uri: https://raw.githubusercontent.com/acme/cfn-templates/v1.2.0/dns.yamlpath:does not need to be set in the single-file case — Atmos names the vendored file after the source URI's basename and inspects the provisioned result. Exactly one regular root file is inferred; ambiguous or nested contents require an explicitpath. Provisioner metadata files are ignored. Deployed reads and deletion do not fetch the source; dry-run defers inference.
aws/cloudformation components cannot be vendored through a vendor.yaml
manifest (atmos vendor pull) — only the source:-based JIT provisioning
described above, the same restriction native Helm and Kubernetes components
have. Use source: for every CloudFormation component that isn't authored
directly in your infrastructure repository.
Delivery Targets
By default, apply/deploy deploy directly to the account/region resolved
for the component (see
Region Resolution)
via CreateChangeSet/ExecuteChangeSet — this is the implicit behavior when
--target is omitted and no provision.default is set. A component can
declare additional named targets under provision.targets, selected with
--target:
kind: aws/cloudformationThe direct-deploy target. It is implicit — named
default, with no configuration — whenever nothing else is selected, so most components never declare it. Declare it explicitly when it needs configuration, which today means thepackaging:field described in Choosing the Packaging Bucket, or when you want a name to select with--targetorprovision.default.components:"aws/cloudformation":vpc:provision:default: directtargets:direct:kind: aws/cloudformationpackaging: artifactsartifacts:kind: aws/s3bucket: my-cfn-artifactsregion: us-east-1The
provision.defaultfield names the target used when--targetis omitted, and--targetoverrides it for one run.kind: aws/s3Uploads the template to S3 without deploying a stack. Selecting the
packagedtarget below with--target packagedonly uploads the template, for example for a review step.During a direct deployment, Atmos uses the S3 target as a packaging destination when the template exceeds CloudFormation's 51,200-byte inline size limit, then deploys the uploaded template. To deploy, omit
--targetwhen noprovision.defaultis set, or select a directkind: aws/cloudformationtarget.bucketandregionare both required:regionbuilds thehttps://S3 URL passed asCreateChangeSet'sTemplateURL(AWS rejects a bares3://URI there), so it can't be left to be inferred later.components:"aws/cloudformation":vpc:provision:targets:packaged:kind: aws/s3bucket: my-cfn-artifactsprefix: templatesregion: us-east-1Atmos uploads each template to a content-addressed key,
<prefix>/<stack>/<component>/template-<digest>.yaml, next to a.metadata.jsonsidecar. Leading and trailing slashes onprefixare trimmed, soprefix: /templates/andprefix: templatesproduce the same keys. When an object with the same key and digest already exists, Atmos reuses it instead of uploading again, so repeated runs on a versioned bucket do not accumulate object versions. A publish-onlyapply --target <name>reports the uploaded location as ans3://URI and anhttps://URL.The bucket must exist before
apply/deployuploads to it — either provision it explicitly withatmos aws cloudformation backend create, or setprovision.backend.enabled: true(a sibling oftargets, not nested under a target) to haveapply/deploycreate it automatically the first time it's missing. Auto-provisioning only runs the existence check up front — it never reconciles a bucket that already exists, unlikebackend create/updaterun explicitly, which always re-applies the secure defaults (versioning, encryption, public access blocking, tags).components:"aws/cloudformation":vpc:provision:backend:enabled: truetargets:packaged:kind: aws/s3bucket: my-cfn-artifactsregion: us-east-1Only
applyanddeploycreate the bucket. Thevalidate,diff, andchangeset createverbs also upload an oversized template, but they never create infrastructure: when the bucket is missing they fail with a hint to runbackend createorapply.kind: gitCommits the template YAML to a Git repository (declared in
git.repositories) instead of deploying it — for example, a review or GitOps-style pipeline that applies from the committed template separately. Follows the sameprovision.targetsshape used by native Helm and Kubernetes components.kind: aws/stacksetDelivers to a multi-account/multi-region CloudFormation StackSet instead of a single-account/region stack. Unlike
kind: aws/s3andkind: git, anaws/stacksettarget is not selected throughapply --target— it is used exclusively by theatmos aws cloudformation stacksetverb group, and only bycreate/update, which resolve it to learn the target accounts/regions/permission model.deleteandinstancesact directly onstack_name(the StackSet's own name) and don't resolve or require aprovision.targetsentry.components:"aws/cloudformation":vpc:provision:targets:multi-account:kind: aws/stacksetaccounts:- "111111111111"- "222222222222"regions:- us-east-1- us-west-2permission_model: SELF_MANAGEDadministration_role_arn: arn:aws:iam::111111111111:role/AWSCloudFormationStackSetAdministrationRoleexecution_role_name: AWSCloudFormationStackSetExecutionRoleaccounts- Target AWS account IDs for stack instances.
regions- Target AWS regions for stack instances.
permission_modelSELF_MANAGED(default) orSERVICE_MANAGED. Atmos supports instance targeting only withSELF_MANAGED. ASERVICE_MANAGEDtarget with bothaccountsandregionsis rejected before the StackSet is created. Empty service-managed StackSets can be created and deleted; manage their instances with AWS CloudFormation.administration_role_arn- IAM role ARN CloudFormation assumes to create/manage the StackSet (self-managed permissions).
execution_role_name- IAM role name CloudFormation assumes in each target account (self-managed permissions).
stackset createcreates the StackSet's initial stack instances only when bothaccountsandregionsare set;stackset updateupdates the template/parameters/capabilities and propagates the change to every existing instance, without changing which accounts/regions have one.
Choosing the Packaging Bucket
Packaging uploads an oversized template through a kind: aws/s3 target. Atmos
picks that target as follows:
- When the selected target is itself
kind: aws/s3, that target is used. - When the component declares exactly one
kind: aws/s3target, it is used automatically. - When the component declares two or more, the selected deploy target must name
one with
packaging: <target-name>. Atmos never guesses.
The implicit direct-deploy target has no configuration, so it cannot carry
packaging:. With two or more kind: aws/s3 targets, declare the deploy target
explicitly and make it the default:
components:
"aws/cloudformation":
vpc:
provision:
default: direct
targets:
direct:
kind: aws/cloudformation
packaging: artifacts
artifacts:
kind: aws/s3
bucket: my-cfn-artifacts
region: us-east-1
archive:
kind: aws/s3
bucket: my-cfn-archive
region: us-east-1
Naming the explicit target default works too and replaces the implicit one,
so provision.default is not needed. A kind: git deploy target takes the same
packaging: field.
Dry Run
A dry run (--dry-run) validates the configuration statically and makes no AWS
calls. It applies the same rules the real run enforces before it changes anything: an
unknown --target, a kind: aws/s3 target without bucket or region, a
template over the 51,200-byte inline limit with no packaging target, and for
StackSets an unknown permission_model or a SERVICE_MANAGED target that sets
both accounts and regions. Values that come from templates or YAML functions
are not evaluated, so they are not judged. The output names the verb, component,
and stack, for example Dry run: apply vpc in plat-ue2-dev: configuration validated; no AWS calls made.
Related
atmos aws cloudformationcommand referenceatmos aws cloudformation stacksetcommand reference- CloudFormation
atmos.yamlconfiguration - Component dependencies