Skip to main content

Ansible Components

Ansible components run Ansible playbooks for configuration management and infrastructure automation. They allow you to manage playbook execution with the same stack-based configuration approach used for Terraform, Helmfile, and Packer.

Available Configuration Sections

Ansible components support the common configuration sections:

vars
Variables passed to ansible via --extra-vars.
env
Environment variables during execution.
settings
Integrations, metadata, and Ansible-specific settings like playbook and inventory.
metadata
Component behavior and inheritance.
command
Override ansible binary.
hooks
Lifecycle event handlers.

Component Structure

A typical Ansible component configuration:

components:
ansible:
webserver:
vars:
app_name: myapp
app_port: 8080
app_version: "1.0.0"
env:
ANSIBLE_HOST_KEY_CHECKING: "false"
settings:
ansible:
playbook: site.yml
inventory: inventory/production

Ansible Directory Structure

Ansible components are located in the path configured in atmos.yaml:

# atmos.yaml
components:
ansible:
base_path: components/ansible

Example structure:

components/ansible/
├── hello-world/
│ ├── site.yml
│ └── inventory.ini
├── webserver/
│ ├── site.yml
│ ├── roles/
│ │ └── nginx/
│ └── inventory/
│ ├── production
│ └── staging
└── database/
├── deploy.yml
└── inventory.ini

Playbook Configuration

Each Ansible component contains playbooks that use variables passed from Atmos:

components/ansible/hello-world/site.yml
---
- name: Hello World
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Say hello
ansible.builtin.debug:
msg: "Hello from {{ app_name }} (version {{ app_version }}) on port {{ app_port }}"

Playbook and Inventory Resolution

The playbook and inventory can be specified in two ways, with command line flags taking precedence:

  1. Stack manifest settings — Define settings.ansible.playbook and settings.ansible.inventory
  2. Command line flags — Use --playbook / -p and --inventory / -i
components:
ansible:
webserver:
settings:
ansible:
playbook: site.yml # Default playbook
inventory: inventory/production # Default inventory

Component-Type Defaults

Define defaults for all Ansible components:

# Apply to all Ansible components
ansible:
vars:
managed_by: Atmos
env:
ANSIBLE_HOST_KEY_CHECKING: "false"
ANSIBLE_FORCE_COLOR: "true"

# Individual components
components:
ansible:
webserver:
vars:
app_port: 8080

Complete Example

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

vars:
region: us-east-1
stage: prod

ansible:
vars:
managed_by: Atmos
env:
ANSIBLE_HOST_KEY_CHECKING: "false"

components:
ansible:
webserver:
vars:
app_name: myapp
app_port: 8080
app_version: "2.0.0"
settings:
ansible:
playbook: site.yml
inventory: inventory/production

database:
metadata:
component: database
vars:
db_name: acme-prod
db_port: 5432
settings:
ansible:
playbook: deploy.yml
inventory: inventory/production
depends_on:
- component: webserver

Variable Handling

Atmos automatically generates a YAML variables file containing all variables from the component's vars section. This file is passed to Ansible using --extra-vars @<filename>.

The generated file follows the naming convention: <context>-<component>.ansible.vars.yaml

Here, <context> is the full Atmos context prefix (e.g., tenant-account-stage-region), not just the stack name. For example, for a component webserver with context prefix acme-plat-prod-us-east-1, the file would be: acme-plat-prod-us-east-1-webserver.ansible.vars.yaml

The file is automatically cleaned up after playbook execution completes.

Running Ansible Commands

Atmos provides commands that wrap Ansible operations:

# Run a playbook
atmos ansible playbook webserver -s prod

# Run with explicit playbook and inventory
atmos ansible playbook webserver -s prod -p site.yml -i inventory/production

# Dry run (shows command without executing)
atmos ansible playbook webserver -s prod --dry-run

# Pass options directly to ansible-playbook
atmos ansible playbook webserver -s prod -- --check -vvv

# Check Ansible version
atmos ansible version

Environment Variables

Common environment variables for Ansible components:

ANSIBLE_HOST_KEY_CHECKING
Disable SSH host key checking (set to false).
ANSIBLE_FORCE_COLOR
Force colored output (set to true).
ANSIBLE_CONFIG
Path to Ansible configuration file.
ANSIBLE_VAULT_PASSWORD_FILE
Path to Ansible Vault password file.
ANSIBLE_ROLES_PATH
Additional paths to search for roles.
ANSIBLE_COLLECTIONS_PATH
Paths to search for collections.

Passing Secrets Securely

The generated variables file is written to disk in plaintext (world‑readable, 0644) so Ansible can read it via --extra-vars. Unlike Terraform — which keeps secret‑bearing vars off disk — Ansible performs no off‑disk partitioning. Never put secrets in an Ansible component's vars section.

Secrets belong in env, not vars

Values in the env section are injected only into the Ansible subprocess environment and are never written to the variables file. Declare secrets under secrets.vars, reference them with !secret in env, and read them in your playbook with Ansible's env lookup.

stacks/deploy/prod.yaml
components:
ansible:
webserver:
secrets:
vars:
DB_PASSWORD:
description: "Application database password"
store: ssm-secrets # a `secret: true` store; or use `sops: <provider>`
required: true
env:
# Injected ONLY into the Ansible subprocess environment — never written to the
# variables file on disk.
DB_PASSWORD: !secret DB_PASSWORD
vars:
http_port: 8080 # non-secret values only

Read the secret from the environment in your playbook — not from the on‑disk extra‑vars file:

components/ansible/webserver/site.yml
- hosts: all
vars:
# `lookup('env', ...)` reads the secret from the environment exported by the `env` section.
db_password: "{{ lookup('env', 'DB_PASSWORD') }}"
tasks:
- name: Configure the application
ansible.builtin.template:
src: app.conf.j2
dest: /etc/app/app.conf
no_log: true # avoid echoing the secret in task output

Try It

See the demo-ansible example for a minimal hello-world setup demonstrating variable passing:

cd examples/demo-ansible
atmos ansible playbook hello-world -s dev

Best Practices

  1. Use Settings for Playbook Config: Define settings.ansible.playbook and settings.ansible.inventory in stack manifests rather than passing flags every time.

  2. Centralize Defaults: Define common settings in catalog defaults and override only when necessary.

  3. Use Dependencies: Define depends_on when playbooks need to run after infrastructure is provisioned.

  4. Keep Playbooks Small: Create focused playbooks for specific tasks rather than monolithic automation.

  5. Use Environment Variables: Configure Ansible behavior through env rather than ansible.cfg for consistency across environments.

  6. Leverage Inheritance: Use abstract components and inheritance for shared playbook configurations across environments.