Skip to main content

!include

The !include function lets you load files — either local or remote — and insert their contents or specific values directly into sections of your stack manifests.

The YAML standard provides anchors and aliases, that allow you to reuse and reference pieces of your YAML file, making it more efficient and reducing duplication.

Atmos supports YAML anchors and aliases, but the biggest limitation is that they are only available within the file in which they are defined. You cannot reuse anchors across different files.

The !include Atmos YAML function overcomes this limitation by allowing you to include the content or specific values from different local and remote sources. The !include function also provides the following features:

  • Supports local files with absolute and relative paths.

  • Supports the remote protocols provided by the go-getter library.

  • Allows you to use YQ expressions to query and filter the content of the files to retrieve individual values.

  • Determines the format based on file extensions. It supports files in JSON (.json), YAML (.yaml, .yml), and HCL (.hcl, .tf, .tfvars) formats, and automatically converts them into correct YAML structures (simple and complex types like maps and lists are supported). All other file extensions (including .txt or files without extensions) are returned as raw strings, allowing you to include text and Markdown files as strings in Atmos manifests.

Atmos resolves the !include functions during the initial loading of YAML files from the local filesystem or remote sources, injecting the contents of the referenced files directly into the current location. Files are parsed based on their extension: JSON (.json), YAML (.yaml, .yml), HCL (.hcl, .tf, .tfvars) are converted into the appropriate type (boolean, map, list, etc.), while other extensions return raw strings.

Supported File Formats​

With !include it's possible to import multiple different file formats into Atmos configurations. File parsing is determined by the file extension:

  • JSON - Files with .json extension are parsed as JSON
  • YAML - Files with .yaml or .yml extensions are parsed as YAML
  • HCL - Files with .hcl, .tf, or .tfvars extensions are parsed as HCL
  • Text - All other extensions (including .txt or no extension) are loaded as plain text
NOTE:

File type detection is based on the file extension, not the content. For example, a .txt file containing JSON will be returned as a raw string. To force any file to be included as raw text regardless of extension, use the !include.raw function.

Important for URLs: URLs that lack a file extension (like https://api.github.com/meta) will be treated as plain text. If you need to parse such URLs as JSON or YAML, ensure the URL ends with the appropriate extension (e.g., .json) or save the content to a local file with the correct extension first.

URL Query Strings and Fragments​

When including files from URLs with query strings or fragments, the extension detection ignores these URL components:

# Extension is detected as .json (query string ignored)
vars: !include https://api.example.com/config.json?version=2&format=raw

# Extension is detected as .yaml (fragment ignored)
settings: !include https://example.com/settings.yaml#section1

# Extension is detected from the path (query/fragment ignored)
config: !include https://example.com/data.json?v=1#field

Supported Sources​

Local Sources​

The !include function supports the following local file sources:

  • Absolute paths

    vars: !include /Users/me/Documents/vars.yaml
  • Paths relative to the current Atmos manifest (where the !include function is executed)

    vars: !include ../config/vars.yaml
  • Paths relative to the base_path defined in atmos.yaml CLI config file

    vars: !include stacks/catalog/vpc/vars.yaml

Remote Sources​

To download remote files, Atmos uses go-getter (used by Terraform for downloading modules) and supports the following protocols to download a single file:

  • http/https - the file must be publicly accessible (not inside a private repository)

    vars: !include https://raw.githubusercontent.com/org/repo/main/path/to/vars.yaml
  • s3 (Amazon S3) - requires the correct AWS permissions and credentials configured

    vars: !include s3::https://my-bucket.s3.amazonaws.com/path/to/vars.yaml
  • gcs (Google Cloud Storage) - requires valid Google Cloud credentials

    vars: !include gcs::gs://my-bucket/path/to/vars.yaml
  • scp/sftp (SSH-based File Transfer) - requires SSH access to the remote server

    vars: !include scp://user@remote-server:/path/to/vars.yaml
    settings: !include sftp://user@remote-server:/path/to/settings.yaml
  • oci (Open Container Initiative)

    vars: !include oci://ghcr.io/my-org/my-image:path/to/vars.yaml
    • The file must be exposed as part of the OCI image and exist as a layer in the image (not hidden inside layers)
    • The registry must support OCI artifact downloads (e.g., AWS ECR, Docker Hub, GHCR, GCR)

Key Benefits of !include​

The !include directive enables modular, reusable configuration patterns across all Atmos YAML files. This has several important implications:

  • Modularization & Reuse !include supports a DRY approach by allowing shared configuration fragments to be stored in local or remote files and reused across multiple stacks or components. You can use it in place of YAML anchors, which don't work across files.

  • Preprocessing for Inheritance Includes are resolved before Atmos processes stacks and components, enabling powerful inheritance and deep-merging behaviors using fully expanded configuration data.

  • Adopting Existing Terraform/OpenTofu Root Modules as Atmos Components If you're already managing your root modules using .tfvars files — for example, separate files for dev, staging, and prod — you can reference them directly in Atmos using !include. This makes it easy to adopt Atmos without having to translate all variables into Atmos stacks.

Example: Referencing Different TFVAR Files Per Environment​

For example, instead of rewriting existing .tfvars varfiles into inline YAML, Atmos lets you bring them in as-is into your Stacks. You can continue managing your root modules as you always have, while gaining Atmos features like stack inheritance, environment promotion, and deep-merging.

Let's say you already have environment-specific .tfvars files like:

  • config/dev.tfvars
  • config/staging.tfvars
  • config/prod.tfvars

You can keep using these files in Atmos by referencing them in your stack configurations:

stacks/org/dev/app.yaml

components:
terraform:
app:
vars: !include config/dev.tfvars

stacks/org/staging/app.yaml

components:
terraform:
app:
vars: !include config/staging.tfvars

stacks/org/prod/app.yaml

components:
terraform:
app:
vars: !include config/prod.tfvars

This pattern allows you to plug Atmos into your existing Terraform/OpenTofu root modules with minimal changes — no need to duplicate or reformat your varfiles. You also unlock additional capabilities like listing all your stacks and components, leveraging layered configurations, stack inheritance with imports, and consistent promotion of settings across environments.

Usage​

The !include function can be called with either one or two parameters:

  # Download the file and inject the content directly into the current location in the YAML
!include <file-path>

# Download the file, filter the content using the YQ expression,
# and inject the result directly into the current location in the YAML
!include <file-path> <yq-expression>

Arguments​

file-path

Path to a local or remote file

yq-expression
(Optional) YQ expression to retrieve individual values from the file

Using YQ Expressions to retrieve individual values from files​

To retrieve individual values from complex types such as maps and lists, or do any kind of filtering or querying, you can utilize YQ expressions.

For example:

  • Retrieve the first item from a list
subnet_id1: !include <file-path> .private_subnet_ids[0]
  • Read a key from a map
username: !include <file-path> .config_map.username

For more details, review the following docs:

Handling file paths and YQ expressions with spaces​

If you have spaces in the file names or YQ expressions, enclose the file paths and YQ expressions in double quotes and use single quotes around the whole expression.

For example, on Windows:

  vars:
values: !include '"~/My Documents/dev/values.yaml"'
config: !include '"~/My Documents/dev/config.json" "<yq-expression-with-spaces>"'

On macOS and Linux:

  vars:
values: !include './values.yaml "<yq-expression-with-spaces>"'
description: !include '"component description.md"'

Examples​

stack.yaml

components:
terraform:
my-component:
vars:
# Include a local file with the path relative to the current Atmos manifest
values: !include ./values.yaml
# Include a local file with the path relative to the current Atmos manifest and query the `vars.ipv4_primary_cidr_block` value from the file using YQ
ipv4_primary_cidr_block: !include ./vpc_config.yaml .vars.ipv4_primary_cidr_block
# Include a local file relative to the `base_path` setting in `atmos.yaml`
vpc_defaults: !include stacks/catalog/vpc/defaults.yaml
# Include a local file in HCL format
hcl_values: !include ./values.hcl
# Include a local varfile in HCL format
tfvars_values: !include ../components/terraform/vpc/vpc.tfvars
# Include a local Markdown file
description: !include ./description.md
# Include a local text file
text: !include a.txt
# Include a local text file with spaces in the file name
text2: !include '"my config.txt"'
# Include a local text file on Windows with spaces in the file name, and get the `config.tests` value from the file
tests: !include '"~/My Documents/dev/tests.yaml" .config.tests'
# Download and include a remote YAML file using HTTPS protocol, and query the `vars` section from the file
region_values: !include https://raw.githubusercontent.com/cloudposse/atmos/refs/heads/main/examples/quick-start-advanced/stacks/mixins/region/us-east-2.yaml .vars
# Download and include a remote JSON file from a URL with .json extension
# Note: For URLs without extensions, save locally first or use a URL with .json extension
github_config: !include ./github-meta.json .api

stack.yaml

# The `config` folder is relative to the `base_path` setting in `atmos.yaml`
import: !include config/import.yaml

# Download the remote file using `go-getter` and assign the `components.terraform.component-1.settings` section
# from the file to the `settings` section in the current stack
settings: !include https://raw.githubusercontent.com/cloudposse/atmos/main/tests/fixtures/scenarios/stack-templates-2/stacks/deploy/nonprod.yaml .components.terraform.component-1.settings

components:
terraform:
component-1:
vars:
# The `config` folder is relative to the `base_path` setting in `atmos.yaml`
string_var: !include config/vars.json .string_var
boolean_var: !include config/vars.yaml .boolean_var
list_var: !include config/vars.tfvars .list_var
map_var: !include config/vars.tfvars .map_var

component-2:
vars: !include config/vars.tfvars

component-3:
vars: !include config/vars.json

component-4:
vars: !include config/vars.yaml