Ansible Concepts Cheat Sheet
Core Components
- Control Node: The machine where you install Ansible and from which you execute all commands and playbooks.
- Managed Nodes: The devices (servers, network devices, etc.) that Ansible manages. These are often called hosts.
- Inventory: A file that contains a list of the managed nodes. It can be a simple static file or a dynamic one generated by a script.
- Modules: The specific units of code that Ansible executes on the managed nodes. Each module is designed to perform a specific task, like installing a package or copying a file.
- Tasks: A single action that a module performs. Playbooks are made up of a list of tasks.
- Playbooks: YAML files that contain a series of plays, which in turn contain a list of tasks to be executed on a group of managed nodes. Playbooks define the desired state of your systems.
- Roles: A way to group related content, such as tasks, handlers, and variables, into a reusable and shareable structure. Roles help to organize complex playbooks.
Key Terminology
- Facts: Information gathered about the managed node by Ansible’s setup module. This includes details like the operating system, network configuration, and hardware specifications.
- Variables: Key-value pairs used to store and reuse data within playbooks. They can be defined in a variety of places, including inventory files, playbooks, or separate variable files.
- Handlers: Special tasks that are only run when notified by another task. They are typically used for service restart actions.
- Loops: A way to repeat a task multiple times with different values. This is used to avoid repeating the same task definition for each item.
- Conditional Statements: Used to run tasks only if a certain condition is met. This allows for flexible and intelligent playbooks that can adapt to different situations.
- Templates: Files that contain variables and control structures and are processed by the Jinja2 templating engine. They are often used to create configuration files on managed nodes.
- Ad-hoc Commands: Single-line commands executed from the control node to perform quick, one-off tasks without writing a full playbook.
- Vault: A feature for encrypting sensitive data, like passwords and API keys, within Ansible.
- Collections: A standard way to package, share, and distribute Ansible content, including playbooks, roles, modules, and plugins.
- Plugins: Extend Ansible’s core functionality. Examples include inventory plugins (to gather hosts from a dynamic source) or connection plugins (to connect to managed nodes via different protocols).
- Tags: A mechanism to label tasks and plays, allowing you to run only specific parts of a playbook.
- Play: A grouping of tasks that target a specific set of hosts. A playbook can contain one or more plays.
Advanced Concepts
- Idempotence: A fundamental concept in Ansible. It means that an operation can be applied multiple times without changing the result beyond the initial application. Ansible modules are designed to be idempotent, ensuring that running a playbook repeatedly won’t cause unintended side effects.
- YAML: The human-readable data serialization language used for writing playbooks, inventory files, and configuration files. It stands for “YAML Ain’t Markup Language” and is known for its simple syntax.
- Jinja2: The templating engine used by Ansible. It’s used to create dynamic configuration files and other documents by embedding variables, expressions, and control structures within text files.
- Delegation: The process of running a task on a different host than the one being targeted in the play. This is often used for tasks like managing a load balancer or a database.
- Connection Plugins: These plugins define how Ansible connects to managed nodes. The default is SSH, but there are others for Windows (winrm), network devices, and more.
- Lookup Plugins: Used to retrieve data from external sources, such as files, environment variables, or other systems, and use that data in playbooks.
- Callbacks: Plugins that interact with Ansible’s execution, such as printing custom output or sending notifications to a logging service.
- Filters: A way to transform data within a playbook. They can be used to manipulate strings, lists, or other variables. A common filter is
to_jsonto convert a variable into JSON format. - Facts Cache: A method to save facts gathered from managed nodes to avoid having to re-run the
setupmodule on every execution, which can speed up large-scale playbook runs. - Ansible Tower / AWX: A web-based solution that provides a user interface for Ansible. It includes features for role-based access control, scheduling, and centralized logging. AWX is the open-source version of Ansible Tower.
- Configuration Management: The broader IT discipline that Ansible belongs to. It involves managing the state of a system’s configuration to ensure it is consistent and compliant.
Ansible Directory Structure
/my_ansible_project/
├── playbook.yml # Main playbook file
├── ansible.cfg # Optional, but recommended configuration file
├── inventory/
│ ├── production # Inventory for production environment
│ └── staging # Inventory for staging environment
├── group_vars/
│ ├── all.yml # Variables for all hosts
│ ├── web_servers.yml # Variables for the 'web_servers' group
│ └── database.yml # Variables for the 'database' group
├── host_vars/
│ ├── server1.yml # Variables for 'server1' host
│ └── server2.yml # Variables for 'server2' host
└── roles/
├── web_server/ # 'web_server' role
│ ├── defaults/ # Default variables for the role
│ │ └── main.yml
│ ├── handlers/ # Handlers for the role
│ │ └── main.yml
│ ├── tasks/ # Main tasks for the role
│ │ └── main.yml
│ ├── templates/ # Jinja2 templates for the role
│ ├── files/ # Static files to copy
│ └── meta/ # Metadata for the role
│ └── main.yml
└── database_server/ # 'database_server' role
├── defaults/
│ └── main.yml
└── tasks/
└── main.yml
Explanation of Components
playbook.yml: The main entry point for your automation. It calls the roles and defines the high-level logic for your infrastructure.ansible.cfg: A configuration file that can specify the location of your inventory, roles, and other settings.inventory/: A directory to store separate inventory files for different environments (e.g.,production,staging).group_vars/andhost_vars/: Directories to store variables specific to host groups or individual hosts. This is a best practice for managing environment-specific configurations.roles/: This directory contains all your reusable roles. Each role is a self-contained unit of automation.- Role Directories: A standard role directory has a specific structure:
tasks/: Contains the tasks that the role will execute.main.ymlis the default file that is run when the role is called.handlers/: Contains handlers, which are tasks that are only triggered when notified.defaults/: Contains default variables for the role. These variables can be overridden by other variables.files/: Contains static files that can be copied to managed hosts.templates/: Contains Jinja2 templates that can be rendered with variables and copied to managed hosts.meta/: Contains metadata about the role, such as its dependencies.
Nodes
What are Ansible Nodes?
Ansible uses the term nodes to refer to the machines it manages. There are two types of nodes in an Ansible setup:
- Control Node: The machine where Ansible is installed and from which you run all commands and playbooks. It’s the “master” machine that orchestrates the automation.
- Managed Nodes: The target machines that the control node manages. These are the servers, network devices, or other devices where Ansible performs tasks. They are also commonly called hosts.
Key Characteristics & Workflow
- Agentless: Unlike other configuration management tools, Ansible doesn’t require any special agent software to be installed on the managed nodes. This simplifies deployment and management.
- Communication: Communication between the control node and managed nodes is typically done over SSH (Secure Shell) for Linux/Unix systems. For Windows, it uses WinRM (Windows Remote Management).
- Python Requirement: Managed nodes only need Python (version 2.6+ or 3.5+) to run Ansible modules.
- Inventory: Managed nodes are defined in an inventory file, which is a list of hosts organized by groups. This file tells Ansible which machines to target.
How it Works
- You execute an Ansible command or playbook from the control node.
- Ansible connects to the specified managed nodes using SSH or WinRM.
- It temporarily copies the necessary modules to the managed node.
- The modules execute on the managed node, performing the desired task.
- After the task is completed, the modules are removed from the managed node.
- Ansible returns the output and status of the task to the control node.
This process is what makes Ansible agentless and a simple and powerful automation tool.
Inventory
An Ansible Inventory is a file or set of files that defines the managed nodes (hosts) that Ansible will interact with. It serves as the primary source of truth for all machines, groups of machines, and associated variables you are managing.
Inventory Types
- Static Inventory: A simple text file that you manually create and maintain. This is the most common type and is suitable for environments that don’t change frequently.
- Dynamic Inventory: A script or program that generates a list of hosts on the fly. This is useful for cloud environments (like AWS, Azure, GCP) where hosts are frequently created or destroyed. Ansible provides plugins for many cloud providers.
File Formats & Structure
The inventory can be written in either INI or YAML format.
INI Format (Common)
Hosts are listed under group headings. Host and group-level variables can also be defined.
[web_servers]
server1.example.com
server2.example.com
[database_servers]
db1.example.com
db2.example.com
[all:vars]
ansible_user=ubuntu
- Groups: Hosts are organized into logical groups, like
web_serversordatabase_servers. - Host Variables: Variables specific to a single host can be defined on the same line.
- Group Variables: Variables that apply to all hosts in a group can be defined under a
[group:vars]section.
YAML Format
This format is often preferred for its readability, especially for complex structures.
all:
hosts:
server1.example.com:
server2.example.com:
children:
web_servers:
hosts:
server1.example.com:
server2.example.com:
vars:
ansible_user: ubuntu
database_servers:
hosts:
db1.example.com:
db2.example.com:
Best Practices
- Version Control: Always keep your inventory file in a version control system like Git.
- Separate Environments: Use separate inventory files or directories for different environments (e.g.,
production,staging,development). - Use Variables: Define host and group variables within the inventory to keep playbooks more generic and reusable. This is a powerful feature for managing environment-specific settings.
Task
An Ansible task is a single, defined action to be executed on a managed node. It is the fundamental building block of a playbook. Each task has a specific goal, such as installing a package, copying a file, or starting a service. Tasks are always executed in the order they appear within a playbook.
Basic Syntax
A task is defined using a module and its arguments. The name is optional but highly recommended for readability and debugging.
- name: This is a descriptive name for the task
module_name:
argument1: value
argument2: value
Key Attributes and Directives
These are common attributes used to control a task’s behavior.
name: A human-readable description of the task. Essential for providing context in playbook output.become: A directive to escalate privileges on the managed node (e.g., to run a command asroot). Thebecome_usercan be specified as well.when: A conditional statement that allows a task to run only if a specific condition is met.with_items(orloop): A loop that iterates through a list of values, allowing the same task to be run multiple times with different input.register: A directive that saves the output of a task into a variable. This variable can then be used in subsequent tasks or conditional statements.notify: Used to notify a handler to run, typically after a task has made a change.
Common Task Examples
Here are some examples of tasks using popular modules.
1. Installing a Package
This task uses the apt module to ensure the nginx package is installed on a managed node.
- name: Install NGINX web server
apt:
name: nginx
state: present
2. Copying a File
This task uses the copy module to move a file from the control node to the managed node.
- name: Copy the NGINX configuration file
copy:
src: /path/to/local/nginx.conf
dest: /etc/nginx/nginx.conf
3. Running a Command with a Condition
This task runs the reboot command only if the reboot_required variable is set to true.
- name: Reboot the server if required
command: /sbin/reboot
when: reboot_required
Modules
Ansible modules are the specific units of code that perform a single task on a managed node. They are the core workhorses of Ansible, as they are the part that actually interacts with the system to achieve a desired state. Each module is designed to perform a specific function, such as managing packages, services, files, or users.
How They Work
- Execution: When a playbook runs, Ansible transfers the necessary module to the managed node (typically via SSH).
- Execution: The module runs on the managed node, using its logic to perform the specified task (e.g., installing a package).
- Result: The module returns a JSON-formatted response to the control node, indicating whether it made a change and providing other output details. This result is used to determine if a handler should be notified or if a task needs to be skipped on subsequent runs.
- Cleanup: The temporary module file is then removed from the managed node.
This process is what makes Ansible agentless and a simple and powerful automation tool.
Key Characteristics
- Idempotence: Most modules are designed to be idempotent. This means running a task multiple times will result in the same outcome as running it once. For example, running the
aptmodule to ensure a package is “present” will not reinstall it if it’s already there. - Module Library: Ansible ships with a vast library of over 1,000 modules for a wide range of tasks, from low-level system administration to cloud provisioning and network management.
- Declarative: Modules are designed to be declarative. You describe the state you want to achieve, and the module figures out the steps to get there. For instance, you declare that a file should
state: presentrather than writing a script to check for its existence first.
Common Module Examples
| Module | Description | Example Usage |
apt / yum | Manages packages on Debian/Ubuntu or Red Hat-based systems. | - name: Install NGINX <br> apt: name: nginx state: present |
service | Manages services. | - name: Start NGINX service <br> service: name: nginx state: started |
copy | Copies a file from the control node to the managed node. | - name: Copy config file <br> copy: src: my_config dest: /etc/config |
file | Manages files, directories, and symlinks. | - name: Create a directory <br> file: path: /data/ dir state: directory |
command | Executes a command on the managed node. | - name: Run a command <br> command: echo "hello world" |
Plugins
Ansible plugins are pieces of code that extend and enrich Ansible’s core functionality. They are a way to customize Ansible’s behavior without modifying the main source code. Plugins run on the control node and enable Ansible to connect to different systems, gather data from external sources, or process information in new ways.
Common Types of Plugins
| Plugin Type | Description | Example Use Case |
| Inventory | Extends Ansible to get host and group information from dynamic sources like cloud providers (AWS, Azure, GCP), CMDBs, or other external databases. | Automatically generate an inventory of all your EC2 instances in AWS. |
| Connection | Defines how Ansible connects to managed nodes. The default is SSH, but other plugins exist for different protocols. | Connect to Windows machines using WinRM or to network devices via a specific API. |
| Lookup | Fetches data from external sources and integrates it into a playbook. Sources can include files, environment variables, or other services. | Read a list of usernames from a local file to create users on a remote server. |
| Filter | Transforms data into a different format. They are often used with Jinja2 templates. | Convert a JSON string to a Python dictionary, or a list of items into a comma-separated string. |
| Callback | Controls the output and logging of a playbook run. They can send notifications to external systems like Slack or a logging service. | Send a message to a Slack channel when a playbook run fails. |
| Action | A special type of module that runs on the control node. Many core modules are actually action plugins. | Processes a file before sending it to a remote host, like the template or copy modules. |
Filter Plugin
Ansible filter plugins are a type of plugin that extends Ansible’s ability to transform and manipulate data. They run on the control node and are primarily used within Jinja2 templates and expressions to modify data before it is used. They are a powerful way to process variables, format output, and handle complex data structures without requiring external tools or complicated logic in your playbooks.
How They Work
A filter plugin takes data as input, applies a transformation, and returns the modified data. You use them by piping a variable or expression to the filter name.
Example: Basic String Transformation
- name: Convert a string to uppercase
ansible.builtin.debug:
msg: "{{ 'hello world' | upper }}"
In this simple example, the upper filter is a built-in filter plugin that converts a string to uppercase. The output would be HELLO WORLD.
Creating a Custom Filter Plugin
While Ansible includes many built-in filters, you can also write your own to perform custom data transformations.
- Create the Plugin File: Create a Python file inside a
filter_pluginsdirectory within your playbook project or a role. - Define the Filter: The Python file needs to contain a function that takes input and returns the transformed output. The function is then added to a dictionary named
FilterModule.
Example Plugin (filter_plugins/my_filters.py)
def my_custom_filter(data):
# This filter will simply reverse a string
return data[::-1]
class FilterModule(object):
def filters(self):
return {
'reverse_string': my_custom_filter,
}
Using the Custom Filter in a Playbook
Once the custom filter plugin is in place, you can use it in any playbook within the same project.
- name: Use the custom filter to reverse a string
ansible.builtin.debug:
msg: "{{ 'ansible' | reverse_string }}"
This would output elbisna.
Connection Plugin
A Connection Plugin in Ansible is a piece of code that defines how Ansible communicates with a managed node. It’s the mechanism responsible for transferring modules and commands to the remote host and retrieving the results. Connection plugins run on the control node and are essential for making Ansible a truly “agentless” tool.
How it Works
When you run a playbook or an ad-hoc command, Ansible uses a connection plugin to establish a link to the managed node. The most common connection plugins are:
ssh: The default and most widely used plugin. It connects to Linux/Unix machines over the standard SSH protocol. It is the most robust and secure option for these systems.winrm: This plugin is used to connect to Windows servers via the Windows Remote Management protocol.local: This plugin executes tasks on the control node itself, bypassing the need for a remote connection. It’s often used for tasks that don’t need to be run on remote hosts, such as managing local files or using lookup plugins.netconf: Used for managing network devices that support the NETCONF protocol.
Key Characteristics and Usage
- Agentless: Connection plugins do not require any persistent agent software on the managed nodes. They establish a connection, perform a task, and then disconnect.
- Configuration: You can specify the connection plugin to use either in your playbook or in the inventory file. For example, to use
winrm, you would setansible_connection: winrmin your inventory. - Customization: You can write your own connection plugins to support custom protocols or to interact with devices that don’t use standard SSH or WinRM.
Action Plugin
An Action Plugin is a type of plugin that executes on the control node before the module is called on the managed node. It’s a special kind of plugin that can run tasks that require logic or operations on the control node itself, and then pass the results to the remote module for execution. Many of Ansible’s core modules, like ansible.builtin.copy and ansible.builtin.template, are implemented as action plugins.
How it Works
Action plugins act as an intermediary between the Ansible core and the remote module. They perform several key functions:
- Local Operations: An action plugin can perform local tasks on the control node. For example, the
templateaction plugin will process a Jinja2 template file on the control node before sending the final, rendered file to the managed node. - Module Transfer: They handle the transfer of the actual module code to the managed node.
- Argument Handling: They can manipulate or validate the arguments passed to the module before execution.
Key Characteristics and Examples
- Runs on Control Node: Unlike a typical module that runs on the managed node, the action plugin itself runs on the control node.
- Complex Logic: They are used for tasks with complex logic that cannot be performed directly on the managed node.
- Built-in Plugins: Many of the most-used Ansible modules are actually action plugins.
| Plugin | What it Does |
ansible.builtin.copy | Action plugin that copies a file from the control node to the managed node. |
ansible.builtin.template | Processes a Jinja2 template file locally on the control node and then sends the rendered file to the managed node. |
ansible.builtin.shell | Takes a command from the playbook, formats it for the remote shell, and then executes it on the managed node. |
Callback Plugin
A Callback Plugin in Ansible is a piece of code that allows you to customize and extend how Ansible’s output is displayed and handled. These plugins run on the control node at key moments during a playbook execution, such as when a task starts, completes, or fails, or when a play finishes. They provide a way to hook into the Ansible process and perform actions like logging, sending notifications, or generating custom reports based on the playbook’s results.
How it Works
Callback plugins are often used for integrations with other systems. They can:
- Log Results: Send detailed results of a playbook run to a centralized logging system like Splunk or ELK.
- Send Notifications: Trigger notifications to a team chat service like Slack or to a ticketing system like Jira when a playbook fails or completes.
- Generate Reports: Create custom reports or summaries of the automation run, which can be useful for auditing and compliance.
Key Characteristics
- Runs on Control Node: Like other plugins, callback plugins run on the machine from which you are executing Ansible.
- Event-Driven: They are triggered by specific events during a playbook run.
- Customizable Output: The default output of Ansible is a callback plugin itself. You can enable or disable other plugins to change how output is displayed.
To use a callback plugin, you typically enable it in your ansible.cfg file by setting the stdout_callback option. You can also specify a plugin directory to use custom ones.
Example Use Case
A common use case is to get a notification in Slack when a production deployment finishes. You would configure a callback plugin to send a message to a specific Slack channel after the playbook completes, providing a summary of the successful deployment. This allows team members to stay informed about automation events without having to monitor the command line output.
Lookup Plugin
A Lookup Plugin is a type of plugin that runs on the control node to retrieve data from external sources.1 It’s a way to pull information into your playbooks from a variety of places, such as files, environment variables, databases, or even other command outputs.2 Lookup plugins are essential for creating dynamic playbooks that don’t rely on static data and can fetch information as needed during an automation run.
How It Works
A lookup plugin operates on the control node to find a value and then returns that value to the playbook. The most common use is to populate a variable. You use the lookup keyword, which takes the name of the plugin and its arguments.3
Example: Looking up a value from a file
The file lookup plugin reads the contents of a file on the control node.4
- name: Read a secret from a local file
vars:
my_secret: "{{ lookup('file', '/etc/ansible/secrets/api_key.txt') }}"
- name: Debug the secret variable
ansible.builtin.debug:
msg: "The API key is {{ my_secret }}"
In this example, the playbook will read the contents of api_key.txt and assign it to the my_secret variable.
Common Lookup Plugin Examples
| Plugin | Description | Example Use |
file | Reads the contents of a file. | Read a single line of text into a variable. |
env | Retrieves the value of an environment variable. | Get a value like HOME or a custom variable set in your shell. |
pipe | Executes a command and returns its standard output. | Run a local grep command to find a value. |
password | Generates or retrieves a password. | Create a random password for a new user or database. |
ini | Reads values from an INI file. | Get configuration settings from a local .ini file. |
Playbooks
Ansible playbooks are files written in YAML that define a set of instructions, or “plays,” to be executed on a group of managed nodes. They are the core of Ansible’s automation and are used to orchestrate a series of tasks to achieve a desired state on your systems. Playbooks are declarative, meaning you describe the end state you want, and Ansible figures out how to get there.
Core Components
A playbook is composed of several key elements:
- Plays: A playbook is a list of one or more plays. Each play is a block that targets a specific group of hosts from the inventory and defines the tasks to be run on them.
- Hosts: This directive specifies which hosts from your inventory the play will target. It can be a group name (e.g.,
web_servers), a host name, orall. - Tasks: A list of tasks to be executed in the order they are defined. Each task calls an Ansible module to perform a specific action, like installing a package or copying a file.
- Variables: Playbooks can use variables to store data, making them more flexible and reusable. Variables can be defined within the playbook, in separate files, or in the inventory.
- Roles: Playbooks often use roles to organize related tasks, handlers, variables, and files into a reusable structure. This is a best practice for managing complex automation projects.
Example Playbook Structure
This example shows a simple playbook that installs and starts the NGINX web server on a group of hosts.
---
- name: Install and configure a web server
hosts: web_servers
become: yes
vars:
nginx_port: 80
tasks:
- name: Ensure NGINX is installed
ansible.builtin.apt:
name: nginx
state: present
- name: Copy NGINX configuration file
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: Ensure NGINX service is running and enabled
ansible.builtin.service:
name: nginx
state: started
enabled: yes
handlers:
- name: restart nginx
ansible.builtin.service:
name: nginx
state: restarted
Play
An Ansible play is a grouping of tasks that are executed on a specific set of hosts from your inventory. It’s a single unit of work within a playbook and is used to define the high-level goal for a set of machines. A playbook can contain one or more plays, each targeting different hosts or performing different roles.
Anatomy of a Play
A play is defined by its target hosts, and all the tasks that follow apply to those hosts.
name: An optional but highly recommended descriptive name for the play.hosts: Specifies the group of hosts from your inventory that the play will run on. It can target a group name, a specific hostname, orall.tasks: The list of tasks to be executed on the targeted hosts. The tasks are run sequentially on each host.become: A directive to escalate privileges on the managed nodes within the play. Settingbecome: yesis the equivalent of usingsudoon the control node.vars: A section to define variables that are local to the current play.
Example Play
Here’s an example of a play within a playbook.
---
- name: "This is the first play: configure web servers"
hosts: web_servers
become: yes
vars:
web_server_port: 80
tasks:
- name: Ensure NGINX is installed
ansible.builtin.apt:
name: nginx
state: present
- name: Ensure the web service is running
ansible.builtin.service:
name: nginx
state: started
- name: "This is the second play: configure database servers"
hosts: database_servers
become: yes
tasks:
- name: Ensure PostgreSQL is installed
ansible.builtin.apt:
name: postgresql
state: present
- name: Ensure the database service is running
ansible.builtin.service:
name: postgresql
state: started
In this example, the playbook contains two plays. The first play targets the web_servers group and performs tasks to install and start a web service. The second play then targets the database_servers group to install and start a database service. This demonstrates how plays divide a playbook into logical, host-specific sections.
Tags
Ansible tags are a way to label tasks, plays, or even roles within your playbooks. They provide a mechanism for running only a specific subset of your automation, which is extremely useful for debugging, testing, or running a targeted part of a large playbook. Instead of running the entire playbook from start to finish, you can use tags to skip irrelevant steps and execute only what’s necessary.
How to Add Tags
You can add a tag to a task, a play, or a role using the tags keyword. You can assign a single tag or a list of tags to any of these elements.
1. Tagging a Task
- name: Install NGINX
ansible.builtin.apt:
name: nginx
state: present
tags:
- web
- install
2. Tagging a Play
---
- name: This is the web servers play
hosts: web_servers
tags:
- web_servers_play
tasks:
- name: Ensure NGINX is installed
ansible.builtin.apt:
name: nginx
state: present
How to Use Tags
You use the ansible-playbook command with specific command-line flags to control which tagged tasks are executed.
1. Running Only Specific Tags
To run only the tasks with a given tag, use the --tags or -t flag.
ansible-playbook my_playbook.yml --tags "web, install"
This command would only run tasks that have been tagged with either “web” or “install”.
2. Skipping Specific Tags
To run all tasks except those with a specific tag, use the --skip-tags or -s flag.
ansible-playbook my_playbook.yml --skip-tags "web"
This command would run every task in the playbook except for those tagged with “web”.
3. Special Tags
Ansible has two special tags:
always: A task with thealwaystag will run regardless of what other tags are specified via--tagsor--skip-tags. This is useful for cleanup or reporting tasks that should never be skipped.never: A task with thenevertag will not run unless you explicitly include it using the--tagsflag. This is helpful for tasks that you only want to run on rare occasions, like a full system backup.
Roles
Ansible Roles are a way to organize and reuse automation content. They are a core part of Ansible’s best practices, providing a structured, hierarchical directory of files for a specific function. By using roles, you can group related tasks, handlers, variables, files, and templates into a single, cohesive unit. This makes your playbooks more modular, easier to maintain, and shareable.
Why Use Roles?
- Reusability: Roles are self-contained, so you can easily use the same role in different playbooks or for different environments.
- Modularity: They break down complex automation tasks into smaller, manageable units. For example, you can have a role for “web_server,” a role for “database_server,” and a role for “monitoring_agent.”
- Standardization: They enforce a standard directory structure, which makes it easier for team members to understand and work with a project.
- Shareability: Roles can be easily shared with others via Ansible Galaxy, a public hub for community-contributed roles.
Standard Role Directory Structure
The structure for a role is strict and helps keep content organized. When you create a role, Ansible expects a specific set of subdirectories.
/roles/
└── my_role/
├── defaults/ # Default variables for the role
│ └── main.yml
├── handlers/ # Handlers (tasks that are notified)
│ └── main.yml
├── tasks/ # Main tasks for the role
│ └── main.yml
├── templates/ # Jinja2 templates
├── files/ # Static files to be copied
├── vars/ # Other variables
│ └── main.yml
└── meta/ # Metadata about the role (e.g., dependencies)
└── main.yml
How to Use a Role
You don’t run a role directly. Instead, you call it from within a playbook using the roles directive.
---
- name: Deploy a web server with a single role
hosts: web_servers
become: yes
roles:
- web_server
Variables
Ansible variables are key-value pairs used to store and reuse data within playbooks. They allow you to write generic playbooks that can be adapted for different environments or configurations without modifying the playbook code itself. This makes your automation more flexible, reusable, and maintainable.
Variable Scope and Precedence
Variables have a specific scope, which determines where they are accessible. Ansible resolves variables based on a set order of precedence. A variable defined with higher precedence will override a variable of the same name defined with a lower precedence.
Here is a simplified order from lowest to highest precedence:
- Inventory Variables: Defined in
inventoryfiles. group_varsandhost_vars: Files that store variables for specific groups or hosts.- Role Defaults: Defined in the
defaults/main.ymlfile of a role. These have the lowest precedence and are easily overridden. - Role Variables: Defined in the
vars/main.ymlfile of a role. - Playbook Variables: Defined in the
varssection of a playbook. - Extra Vars (
-e): Variables passed on the command line using the-eflag. These have the highest precedence and are often used to override specific values for a single run.
How to Define Variables
Variables can be defined in a variety of places, depending on their scope.
1. In Inventory
Variables can be defined directly in the inventory file (INI or YAML).
[web_servers]
server1.example.com http_port=8080
server2.example.com http_port=8080
2. In group_vars and host_vars
This is a recommended method for managing environment-specific variables.
File: group_vars/web_servers.yml
---
ansible_user: web_admin
db_host: db1.example.com
3. In a Playbook
Variables can be defined at the playbook level using the vars keyword.
---
- name: Deploy a web server
hosts: web_servers
vars:
ansible_user: deploy_user
tasks:
- name: Ensure website is running
ansible.builtin.command: "{{ ansible_user }} is logged in"
How to Use Variables
To use a variable, you enclose its name in double curly braces, like {{ variable_name }}.
- name: Use the user variable to create a directory
ansible.builtin.file:
path: "/home/{{ ansible_user }}/data"
state: directory
Facts
Ansible facts are pieces of information about the managed nodes that are automatically collected by Ansible during a playbook run. Think of them as a real-time snapshot of a system’s state. They provide a wealth of dynamic data, like the operating system, IP address, network configuration, available memory, and disk space. This information is crucial for writing intelligent and adaptable playbooks.
How They Work
Ansible uses a built-in module called setup to gather facts. By default, Ansible runs this module at the start of every play in a playbook. The collected facts are stored in a variable called ansible_facts. You can then access and use these variables just like any other variable within your tasks, conditionals, and templates.
Example: Accessing a Fact
To use a fact, you can reference it using the ansible_facts dictionary.
- To get the operating system family:
{{ ansible_facts['os_family'] }} - To get the default IPv4 address:
{{ ansible_facts['default_ipv4']['address'] }} - To get the hostname:
{{ ansible_facts['hostname'] }}
Key Use Cases
- Conditional Logic: Use facts to run tasks only when certain conditions are met. This is a powerful way to make playbooks smarter and more efficient. For example, you can install a package using
apton Debian-based systems andyumon Red Hat-based systems.YAML- name: Install a web server ansible.builtin.yum: name: httpd state: present when: ansible_facts['os_family'] == "RedHat" - name: Install a web server ansible.builtin.apt: name: apache2 state: present when: ansible_facts['os_family'] == "Debian" - Dynamic Configuration: Facts can populate templates to generate configuration files that are tailored to each specific host.
- Reporting and Debugging: You can use the
debugmodule to print out facts and help with troubleshooting.
Controlling Fact Gathering
Sometimes, gathering facts can add unnecessary time to a playbook run, especially in large environments. You can control this behavior:
- Disabling Facts: To disable fact gathering for a specific play, set
gather_facts: false.YAML- name: A play without fact gathering hosts: all gather_facts: false tasks: - name: A simple task that does not need facts ansible.builtin.ping: - Caching Facts: For a performance boost, especially in large environments, you can configure fact caching. This stores the collected facts so Ansible doesn’t need to re-gather them on every run.
Handlers & Notifier
Ansible handlers are special tasks that only run when they are explicitly notified by another task. They are designed to manage services or perform other actions that are only necessary when a change has been made. For example, if you modify a configuration file, you should restart the service it affects only after the file has been successfully written. Handlers provide a way to trigger such actions conditionally and at the end of a play, ensuring that services are only restarted once, even if multiple tasks have notified them.
How They Work
- A task in a playbook makes a change to the managed node (e.g., updates a file, installs a new package).
- The task then uses the
notifydirective to call a handler by name. - Ansible registers this notification but does not run the handler immediately.
- After all the tasks in the current play have been completed, Ansible checks for any registered notifications.
- If a handler was notified, it will run. Even if multiple tasks notify the same handler, it will only run once. This is a key feature that prevents unnecessary restarts and saves time.
Syntax and Example
Handlers are defined in their own section in a playbook or, more commonly, in a handlers/main.yml file within a role.
Defining a Handler
---
- name: restart webserver
ansible.builtin.service:
name: nginx
state: restarted
Notifying a Handler
You can call the handler by its name using the notify directive in a task.
---
- name: Ensure the NGINX configuration file is correct
ansible.builtin.template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart webserver
Loops
Ansible loops are a way to repeat a single task multiple times with different input values. They allow you to avoid writing redundant code in your playbooks by iterating over lists, dictionaries, or the results of other tasks. This makes your playbooks more concise, readable, and efficient. The most common loop construct is the loop keyword, which replaces the older with_items and other with_ directives.
Basic Loop Syntax
The loop keyword is added to a task and is followed by the list you want to iterate over. Within the task, you can access the current item in the loop using the item variable.
- name: Install a list of packages
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- nginx
- htop
- git
In this example, the task will run three times, with the item variable taking on the values nginx, htop, and git in each iteration.
Looping Over Dictionaries
You can also loop over a list of dictionaries. In this case, you can access the individual keys of the dictionary.
- name: Create multiple users with specific UIDs
ansible.builtin.user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
loop:
- { name: 'john', uid: '1001' }
- { name: 'jane', uid: '1002' }
- { name: 'sam', uid: '1003' }
Looping Over Registered Variables
A powerful use of loops is to iterate over the output of a previous task that has been registered into a variable.
- name: Get a list of running services
ansible.builtin.service_facts:
register: service_list
- name: Debug a list of services
debug:
var: item
loop: "{{ service_list.ansible_facts.services | dict2items }}"
In this case, the loop iterates over the output of the service_facts module, allowing you to process each service individually.
Common Loop Directives
loop: The standard and modern way to loop.loop_control: A directive that allows you to change the variable name from the defaultitemto something more descriptive, or to control batching behavior. For example,loop_control: loop_var: package_name.with_items: The legacy loop directive that is still functional but replaced by the more generalloop.with_subelements: A directive for looping over nested data structures.
Conditional Statements
Conditional statements in Ansible are used to control whether a task, play, or other action is executed. They allow you to define logic in your playbooks, ensuring that certain steps are performed only when specific conditions are met. This makes your automation smarter and more adaptable, as it can react dynamically to the state of the managed nodes. The primary keyword for a conditional statement is when.
Basic Syntax and Usage
The when clause is added to a task and is followed by an expression that evaluates to True or False. If the expression is True, the task runs; otherwise, it is skipped.
- name: Install a package only on CentOS servers
ansible.builtin.yum:
name: httpd
state: present
when: ansible_facts['distribution'] == "CentOS"
In this example, the task will only execute on hosts where the Ansible fact ansible_facts['distribution'] is equal to “CentOS”.
Common Conditional Expressions
You can use various tests and operators within the when clause.
Comparison Operators: Use operators like == (equal to), != (not equal to), > (greater than), and < (less than).
- name: Reboot if kernel version is less than 5.0
ansible.builtin.reboot:
when: ansible_facts['kernel'] < "5.0"
Logical Operators: Combine multiple conditions using and, or, and not.
- name: Start NGINX service on port 80 if host is not in production
ansible.builtin.service:
name: nginx
state: started
when: ansible_facts['default_ipv4']['address'] != '127.0.0.1' and inventory_hostname != 'prod_web_01'
Tests: Use special tests to check for conditions like a variable being defined (is defined), a string containing a substring (in), or a list being empty.
- name: Run a task only if a variable is defined
ansible.builtin.debug:
msg: "The user is {{ user_name }}"
when: user_name is defined
Conditional Statements with Loops
You can apply a conditional statement to a task that contains a loop. The when condition is evaluated once for the entire task.
- name: Install packages only if the OS is Debian
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- vim
- tmux
when: ansible_facts['os_family'] == 'Debian'
Templates
Ansible templates are files that contain variables and control structures, which are processed by the Jinja2 templating engine. They are a powerful way to generate custom configuration files, scripts, or any other text file on the managed nodes. Instead of creating a separate file for each host’s specific settings, you can use a single template and populate it dynamically with Ansible variables. This makes your automation more flexible and scalable.
How They Work
- Creation: You create a template file on the control node, typically with a
.j2extension (e.g.,nginx.conf.j2). - Processing: When a playbook runs, Ansible uses the
ansible.builtin.templatemodule to process the template file on the control node. It replaces any variables ({{ variable_name }}) and evaluates any control structures ({% for item in list %}) with the specific values for the target managed node. - Deployment: The processed, final file is then copied to the managed node, where it can be used by the application or service.
Jinja2 Syntax
Jinja2 uses a simple syntax with two main delimiters:
{{ variable_name }}: Used to print the value of a variable.{% control_structure %}: Used to define control structures like loops and conditionals.
Example Template (nginx.conf.j2)
This template will dynamically set the port and server names based on variables.
server {
listen {{ http_port }};
server_name {{ server_name }};
{% if redirect_to_https %}
return 301 https://$host$request_uri;
{% else %}
root /var/www/html;
index index.html index.htm;
{% endif %}
location / {
try_files $uri $uri/ =404;
}
}
Using the Template Module
To use the template in a playbook, you call the ansible.builtin.template module.
- name: Deploy an NGINX configuration from a template
ansible.builtin.template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
This task will take the nginx.conf.j2 file from the templates/ directory on the control node, process it, and save the final output to /etc/nginx/nginx.conf on the managed node. If the file content changes, it will notify the restart nginx handler.
Filters
Ansible filters are a way to transform or manipulate data within a playbook. They are a core component of the Jinja2 templating engine, which Ansible uses to process variables and templates. Filters allow you to perform various operations on data, such as converting data types, manipulating strings, sorting lists, or extracting specific information. They are used to make data suitable for a specific task or to present it in a desired format.
How to Use Filters
Filters are used with the pipe (|) character within a Jinja2 expression. The data on the left side of the pipe is passed as the first argument to the filter on the right.
Basic Syntax:
{{ some_variable | filter_name }}
Example: Converting a List to a Comma-Separated String
The join filter is a common example. It joins elements of a list into a single string.
- name: Create a variable from a list
vars:
my_list:
- 'item1'
- 'item2'
- 'item3'
- name: Display the joined list
ansible.builtin.debug:
msg: "The list is: {{ my_list | join(', ') }}"
This would output: The list is: item1, item2, item3.
Common Filter Examples
| Filter | Description | Example |
to_json | Converts a data structure (dictionary or list) into a JSON string. | `{{ my_dict |
from_json | Parses a JSON string and converts it into a data structure. | `{{ my_json_string |
default | Provides a default value if the variable is undefined or an empty string. | `{{ my_var |
unique | Returns a list with duplicate items removed. | `{{ my_list |
list | Ensures that a value is treated as a list. | `{{ single_value |
sort | Sorts a list in ascending order. | `{{ my_list |
Vault
Ansible Vault is a feature for encrypting sensitive data, such as passwords, API keys, and other secrets, within your Ansible playbooks and roles. It allows you to store this confidential information in files or variables in a secure, encrypted format that can be safely committed to a version control system like Git. This ensures that your sensitive data remains protected from unauthorized access while still being usable by Ansible during automation runs.
How It Works
Ansible Vault uses a single, shared password to encrypt and decrypt files. You can manage encrypted files using a command-line interface.
1. Encrypting a File
To encrypt a new file or an existing one, use the ansible-vault encrypt command. Ansible will prompt you to enter and confirm a password.
ansible-vault encrypt my_secrets.yml
2. Editing an Encrypted File
To edit an encrypted file, use the ansible-vault edit command. Ansible will prompt for the password, decrypt the file for editing, and then re-encrypt it when you save and exit.
ansible-vault edit my_secrets.yml
3. Viewing an Encrypted File
To view the decrypted contents of a file without editing, use the ansible-vault view command.
ansible-vault view my_secrets.yml
Using Vault Files in Playbooks
To use an encrypted file in a playbook, you simply reference it just like any other variable file. Ansible will automatically handle the decryption during the playbook run.
---
- name: Use a vaulted variable file
hosts: all
vars_files:
- secrets.yml
tasks:
- name: Access a vaulted variable
ansible.builtin.debug:
msg: "The user is {{ my_vaulted_user }}"
To run a playbook that uses encrypted files, you need to provide the vault password using the --ask-vault-pass or a password file (--vault-password-file).
ansible-playbook playbook.yml --ask-vault-pass
AWX
AWX is the open-source, upstream project from which Ansible Tower (now known as Red Hat Ansible Automation Platform) is built. It provides a web-based user interface, REST API, and task engine for managing your Ansible automation. AWX offers a centralized, visual way to control, schedule, and monitor Ansible jobs, making it an ideal choice for teams that want to adopt a more structured approach to their automation without a commercial license.
Key Features and Benefits
- Dashboard: A clean, web-based dashboard that provides a real-time overview of your hosts and job statuses.
- Centralized Control: It allows you to launch playbooks, manage inventories, and handle credentials from a single point, providing better visibility and control.
- Security and Access Control: You can define users and teams and grant them specific permissions, ensuring that only authorized personnel can run certain playbooks.
- Job Scheduling: AWX allows you to schedule automated tasks to run at a specific time or on a recurring basis, which is great for routine maintenance jobs.
- Credential Management: It provides a secure way to store credentials like passwords and SSH keys, so they aren’t exposed in plain text within your playbooks.
- REST API: It has a robust API that can be used to integrate your automation with other tools in your CI/CD pipeline.
Ansible Tower
Ansible Tower is a web-based, enterprise-grade solution that provides a centralized user interface for managing and controlling your Ansible automation. It sits on top of the core Ansible engine and offers features designed to make automation more scalable, secure, and easier to use for teams. While Ansible itself is a powerful command-line tool, Ansible Tower provides a visual dashboard, simplifying operations and providing a single pane of glass for all your automation activities.
Key Features and Benefits
- Dashboard: A web-based interface that provides a high-level overview of all your hosts, projects, jobs, and recent activity.
- Role-Based Access Control (RBAC): Allows you to define which users and teams have permission to run specific playbooks or manage certain resources. This is crucial for security and compliance in a team environment.
- Job Scheduling: Lets you schedule playbooks to run at specific times or intervals, automating routine tasks like nightly backups or weekly patch deployments.
- Centralized Logging: Provides a single place to view and search the output of all your Ansible job runs, making it easier to troubleshoot and audit automation tasks.
- REST API: Offers a powerful API that allows you to integrate Ansible Tower with other tools in your IT ecosystem, like monitoring systems or CI/CD pipelines.
- Credential Management: Securely stores sensitive credentials (e.g., passwords, SSH keys) in a vault, preventing them from being exposed in plain text.
Ansible Tower vs. AWX
AWX is the open-source upstream project that serves as the foundation for Ansible Tower. While they share the same core code, there are key differences:
- AWX: The open-source community version, managed by Red Hat and a community of contributors. It has a more rapid release cycle and is generally free to use.
- Ansible Tower: The commercially supported product from Red Hat. It offers official support, enterprise-grade features, and a more stable release cycle.
For most enterprise and production environments, Ansible Tower (or its successor, Red Hat Ansible Automation Platform) is the chosen solution due to its official support and security features.
Galaxy
Ansible Galaxy is a public hub for finding, sharing, and using community-contributed Ansible content. It is a repository where you can discover and download reusable automation components like roles and collections created by other users. Think of it as a central place for the Ansible community to share and collaborate on content.
How it Works
Ansible Galaxy is integrated with the ansible-galaxy command-line tool, which allows you to manage content directly from your terminal.
1. Finding Content
You can browse the web interface of Ansible Galaxy to search for roles and collections based on keywords, popularity, or use cases.
2. Installing Content
You use the ansible-galaxy command to install a role or collection from the Galaxy hub. The command downloads the content and places it in a standard directory structure on your system, ready to be used by your playbooks.
Installing a Role
ansible-galaxy install geerlingguy.nginx
Installing a Collection
ansible-galaxy collection install community.general
3. Creating and Sharing Content
If you want to share your own automation, you can create a role or collection, and then publish it to Ansible Galaxy using the ansible-galaxy command. This makes it available for others to use and collaborate on.
Key Takeaways
- Community Hub: It’s the central hub for the Ansible community.
- Reusable Content: It’s a source of reusable, pre-built roles and collections.
- Command-Line Tool: The
ansible-galaxyCLI tool is used to interact with the hub for installing, managing, and publishing content.
Collections
Ansible Collections are a standard way to package, distribute, and manage Ansible content. They are a significant advancement over the old method of distributing roles and modules individually. A collection can bundle together multiple types of content, including roles, plugins (like inventory, lookup, and filter plugins), and modules, all within a single, versioned package. This makes it easier to share, install, and use related automation content.
Key Components of a Collection
A collection is essentially a directory with a specific structure that includes all the relevant content. The core components are:
- Roles: Self-contained units of automation.
- Modules: The individual units of code that perform actions on managed nodes.
- Plugins: Extend Ansible’s core functionality, such as inventory plugins to gather dynamic host lists or filter plugins to transform data.
- Playbooks: Can also be included to show how to use the content within the collection.
The structure of a collection looks like this:
<namespace>.<collection_name>/
├── docs/
├── galaxy.yml # Collection metadata
├── playbooks/
├── plugins/
│ ├── modules/
│ ├── inventory/
│ └── filter/
├── roles/
└── tests/
How to Use Collections
1. Finding and Installing Collections
You can find collections on Ansible Galaxy, the official hub for community-contributed content. You install them using the ansible-galaxy command.
ansible-galaxy collection install <namespace>.<collection_name>
2. Referencing Content in Playbooks
Once a collection is installed, you reference its content using the Fully Qualified Collection Name (FQCN) format: <namespace>.<collection_name>.<content_name>.
- Calling a Module: To use a module from a collection, you specify its FQCN. For example,
community.general.ping. - Calling a Role: You can include a role from a collection in your playbook’s
rolessection.
---
- name: Use a collection to manage a web server
hosts: all
roles:
- community.general.nginx
tasks:
- name: Use a collection module
community.general.ping:
Using collections makes managing dependencies and sharing reusable content much more streamlined than the older method.
Ansible Commands Cheat Sheet
ansible
The ansible command is a powerful tool for running ad-hoc commands, which are single-line tasks executed directly from the command line without a playbook. It’s ideal for quick actions like checking system status or performing a one-off configuration change across multiple servers.
Basic Syntax
ansible <host-pattern> -m <module_name> -a "<module_arguments>" [options]
<host-pattern>: The hosts or host groups from your inventory to run the command on (e.g.,all,web_servers,db_01).-m <module_name>: The name of the module to execute (e.g.,ping,shell,apt).-a "<module_arguments>": Arguments to pass to the module.
Common Command-Line Options
| Option | Description |
| -i, –inventory | Specifies the inventory file or a comma-separated list of hosts. |
| -k, –ask-pass | Prompts for a connection password to connect to the managed hosts. |
| -b, –become | Runs the task with elevated privileges (like sudo). |
| –become-user | Specifies the user to become after privilege escalation (e.g., root). |
| -K, –ask-become-pass | Prompts for the sudo password. |
| -f, –forks | Sets the number of parallel processes to use, which controls how many hosts are managed at once. The default is 5. |
| -v, –verbose | Increases the verbosity of the output. Use -vvv for a detailed debug output. |
| -C, –check | Runs the command in “dry run” mode. No changes will be made, but Ansible will report what would have changed. |
| -D, –diff | Shows the differences in files and templates that would be changed in check mode. |
| –vault-password-file | Specifies a file that contains the Ansible Vault password. |
| –limit | Further restricts the host pattern to a specific set of hosts. |
Command Examples
| Example Command | Explanation |
ansible all -m ping | Tests connectivity to all hosts in the inventory. |
ansible web_servers -m command -a "df -h /" | Checks the disk space on the root (/) partition for all hosts in the web_servers group. |
ansible db_servers -b -K -m apt -a "name=postgresql state=present" | Connects to db_servers, prompts for a sudo password, and uses the apt module to install the postgresql package with elevated privileges. |
ansible all -m setup --tree /tmp/facts | Gathers facts from all hosts and saves the JSON output to individual files in the /tmp/facts directory. |
ansible-playbook
The ansible-playbook command is the main tool for running Ansible playbooks. It reads a YAML file and orchestrates the automation defined within it. Unlike the simple ansible command, ansible-playbook is used for multi-step, complex, and reusable automation jobs.
Basic Syntax
ansible-playbook <playbook.yml> [options]
<playbook.yml>: The path to the playbook file to execute.
Common and Important Options
| Option | Description | Example |
| -i, –inventory | Specifies the inventory file to use, overriding the default ansible.cfg setting. | ansible-playbook site.yml -i production |
| -e, –extra-vars | Sets additional variables at a high precedence, overriding others. Can be a single key=value pair or a path to a YAML file. | ansible-playbook deploy.yml -e "port=8080" |
| -C, –check | Runs in check mode or “dry run” mode. Ansible reports what changes it would make without applying them. | ansible-playbook upgrade.yml --check |
| -D, –diff | Shows the diff of files and templates that would be changed when used with --check. | ansible-playbook config.yml --check --diff |
| –limit | Restricts the playbook’s execution to a specific host or group of hosts from the inventory. | ansible-playbook site.yml --limit "db_servers" |
| –tags | Runs only the tasks or plays that have the specified tag(s). | ansible-playbook deploy.yml --tags "nginx,db" |
| –skip-tags | Skips plays and tasks that have the specified tag(s). | ansible-playbook all.yml --skip-tags "backup" |
| -b, –become | Runs tasks with elevated privileges (e.g., as root via sudo). | ansible-playbook install.yml -b -K |
| -K, –ask-become-pass | Prompts for the sudo password. | ansible-playbook install.yml -b -K |
| –start-at-task | Starts the playbook execution at the specified task name, skipping all prior tasks. | ansible-playbook long_playbook.yml --start-at-task "configure services" |
| –list-hosts | Parses the playbook and inventory and lists the hosts that would be targeted. | ansible-playbook my_playbook.yml --list-hosts |
| –list-tags | Lists all tags available in the playbook. | ansible-playbook deploy.yml --list-tags |
| –list-tasks | Lists all the tasks that would be executed by the playbook. | ansible-playbook config.yml --list-tasks |
| –syntax-check | Checks the playbook for syntax errors without executing any tasks. | ansible-playbook my_playbook.yml --syntax-check |
| –vault-password-file | Specifies a file that contains the Ansible Vault password. | ansible-playbook deploy.yml --vault-password-file ~/.vault_pass |
| -v, –verbose | Increases the verbosity of output. Use multiple times (e.g., -vvv) for more debug information. | ansible-playbook my_playbook.yml -vvv |
ansible-vault
The ansible-vault command is used to manage encrypted files and strings within Ansible. It’s a security feature that allows you to store sensitive data like passwords and API keys in a secure, encrypted format, which can be safely stored in version control systems.
Common Actions
The ansible-vault command operates using sub-commands, or “actions,” to perform specific tasks.
| Action | Description |
create | Creates a new encrypted file and opens it for editing. |
edit | Decrypts an existing encrypted file and opens it for editing. The file is re-encrypted upon saving. |
encrypt | Encrypts an existing plain text file. The original file is overwritten with the encrypted version. |
decrypt | Decrypts an encrypted file back into plain text. |
view | Views the decrypted contents of an encrypted file without editing it. |
rekey | Changes the encryption password for a vault file without decrypting it first. |
encrypt_string | Encrypts a single string and prints the encrypted output to the console. Useful for adding single secrets directly into a playbook or a vars file. |
Important Options and Examples
| Option | Description | Example |
--ask-vault-pass | Prompts for the vault password on the command line. | ansible-vault encrypt my_secrets.yml --ask-vault-pass |
--vault-password-file | Specifies a file containing the vault password. Recommended for automated scripts. | ansible-vault view my_secrets.yml --vault-password-file ~/.vault_pass |
--output | Specifies the output file for encrypt or decrypt actions. | ansible-vault encrypt credentials.txt --output encrypted_credentials.txt |
--encrypt-vault-id | Specifies which vault identity to use when encrypting if multiple IDs are defined. | ansible-vault encrypt my_file.txt --encrypt-vault-id staging |
--name | Defines a variable name for encrypt_string output. | ansible-vault encrypt_string --name my_api_key 'my_secret_key' |
ansible-inventory
The ansible-inventory command is used to display, verify, and manage your Ansible inventory. It helps you understand how Ansible views your hosts and groups, especially when dealing with dynamic inventories or complex group structures.
Common Actions
The command’s behavior is determined by the action flags you use.
| Action | Description | Example |
--list | Outputs the entire inventory as a JSON data structure. This is the most common use case for scripts and external tools. | ansible-inventory -i hosts.yml --list |
--host <HOST> | Shows detailed information (including variables and group memberships) for a specific host. | ansible-inventory -i hosts.yml --host web_01 |
--graph | Displays a text-based graph representation of your inventory, showing the hierarchical relationships between groups and hosts. | ansible-inventory -i hosts.yml --graph |
| –yaml / –json / –toml | Specifies the output format. By default, --list and --host output in JSON, but you can change it to YAML or TOML. | ansible-inventory -i hosts.yml --list --yaml |
Important Options
| Option | Description | Example |
| -i, –inventory | Specifies the inventory file to use. You can use this flag multiple times to combine inventories. | ansible-inventory -i prod.ini -i dev.ini --list |
| -e, –extra-vars | Sets additional variables that can be used to influence a dynamic inventory script. | ansible-inventory -i my_script.py -e "zone=us-east-1" --list |
| -l, –limit | Limits the inventory output to a specific subset of hosts. | ansible-inventory -i hosts.yml --list --limit "web_servers" |
| –vault-password-file | Specifies a file containing the password to decrypt any vaulted inventory files or variables. | ansible-inventory -i vaulted_vars.yml --list --vault-password-file ~/.vault_pass |
| -v, –verbose | Increases the verbosity of the output, which can be useful for debugging dynamic inventory scripts. | ansible-inventory -i my_script.py -vvv |
ansible-galaxy
The ansible-galaxy command is a tool used to manage reusable Ansible content, specifically roles and collections. It simplifies finding, installing, and creating these components from a central hub called Ansible Galaxy.
Common Actions
| Action | Description | Example |
collection init | Creates the basic directory structure for a new collection. | ansible-galaxy collection init my_namespace.my_collection |
collection install | Installs collections from Ansible Galaxy or a local file. | ansible-galaxy collection install community.general |
collection list | Lists all collections that are installed on your system. | ansible-galaxy collection list |
role init | Creates the skeleton framework for a new role. | ansible-galaxy role init my_webserver_role |
role install | Installs one or more roles from Ansible Galaxy. | ansible-galaxy role install geerlingguy.nginx |
role remove | Removes an installed role from your local system. | ansible-galaxy role remove geerlingguy.nginx |
Important Options
| Option | Description | Example |
| -r, –requirements-file | Installs roles or collections from a file listing them. This is a common way to manage dependencies. | ansible-galaxy install -r requirements.yml |
| –force | Overwrites an existing role or collection with the newly installed version. Useful for updating. | ansible-galaxy collection install my.collection --force |
| -p, –roles-path | Specifies the directory to install or search for roles in. | ansible-galaxy install geerlingguy.nginx -p /etc/ansible/roles |
| –collections-path | Specifies the directory to install or search for collections in. | ansible-galaxy collection install community.general --collections-path ~/ansible_collections |
ansible-pull
The ansible-pull command is used to set up a “pull” mode for Ansible automation. 🔄 Instead of a central control node pushing playbooks to managed nodes, ansible-pull is a command run on the managed node itself. It clones a Git repository containing playbooks and then runs them locally. This is a common pattern for managing many geographically distributed machines that can’t be easily reached from a central location.
How It Works
ansible-pull automates a simple three-step process on the managed host:
- It checks out the specified Git repository.
- It runs the specified playbook locally.
- It can be configured to run periodically as a cron job, ensuring the host is always in a desired state.
Basic Syntax
ansible-pull -U <repository-url> -C <commit-or-branch> [options]
-U <repository-url>: The URL of the Git repository to clone.-C <commit-or-branch>: The branch, tag, or commit to check out.
Common and Important Options
| Option | Description | Example |
-U, --url | Specifies the URL of the Git repository to pull from. | ansible-pull -U https://github.com/my/playbooks.git |
--accept-host-key | Automatically adds the repository’s host key to ~/.ssh/known_hosts if it doesn’t already exist. | ansible-pull -U git@github.com:my/playbooks.git --accept-host-key |
--checkout | Specifies the branch, tag, or commit to check out from the repository. | ansible-pull -U ... --checkout production |
-o, --only-if-changed | Only runs the playbook if the repository has been updated since the last pull. | ansible-pull -U ... -o |
--clean | Discards any local modifications in the repository before pulling. | ansible-pull -U ... --clean |
--full | Performs a full clone of the repository instead of a shallow one. | ansible-pull -U ... --full |
-t, --tags | Only runs the tasks or plays with the specified tag(s) in the playbook. | ansible-pull -U ... -t "config,web" |
--skip-tags | Skips tasks and plays that have the specified tag(s). | ansible-pull -U ... --skip-tags "backup" |
-f, --force | Forces the playbook to run even if the repository couldn’t be updated. | ansible-pull -U ... -f |
-v, --verbose | Increases the verbosity of the output. Use multiple times (e.g., -vvv) for more debug information. | ansible-pull -U ... -vvv |
ansible-config
The ansible-config command is used to inspect and manage Ansible’s configuration settings. ⚙️ It provides a way to view configuration values and their sources without having to manually locate and open the ansible.cfg file. This is useful for debugging and ensuring that Ansible is running with the correct settings.
Common Actions
| Action | Description | Example |
list | Lists all available configuration settings, including their default values and descriptions. | ansible-config list |
dump | Dumps the current, effective configuration settings, showing which values have been changed from their defaults. | ansible-config dump |
view | Shows the contents of the Ansible configuration file being used, as it’s being interpreted. | ansible-config view |
init | Creates a new ansible.cfg file with all the default options commented out. | ansible-config init --disabled > ansible.cfg |
get | Retrieves the value of a specific configuration setting. | ansible-config get inventory |
Important Options
| Option | Description | Example |
| -c, –config | Specifies a custom path to a configuration file to use for the command. | ansible-config dump -c my_custom.cfg |
| –only-changed | Used with dump to show only the settings that have been explicitly changed from their defaults. | ansible-config dump --only-changed |
| -t, –type | Filters the configuration list or dump to show settings for a specific plugin type (e.g., inventory). | ansible-config list --type inventory |
| –json | Outputs the configuration in JSON format, which is useful for machine parsing. | ansible-config dump --json |
| –format | Specifies the output format for various actions. Supported formats include yaml, json, ini, and plain. | ansible-config list --format json |
ansible-doc
The ansible-doc command is used to view the documentation for Ansible modules and plugins directly from your command line. 📖 It’s the fastest way to get information on a module’s parameters, usage, and return values without an internet connection, as the documentation is stored locally.
Common Actions
| Action | Description | Example |
ansible-doc <module> | Displays detailed documentation for a specific module, including its description, parameters, and examples. | ansible-doc ping |
ansible-doc -l | Lists all available modules installed on your system. | ansible-doc -l |
ansible-doc -s <module> | Shows a short, single-line “snippet” of a module’s basic usage in a playbook. | ansible-doc -s apt |
ansible-doc -t <type> -l | Lists all plugins of a specific type, such as inventory or lookup. | ansible-doc -t inventory -l |
ansible-doc -t <type> <plugin> | Displays detailed documentation for a specific plugin type. | ansible-doc -t lookup file |
Important Options
| Option | Description | Example |
| -j, –json | Formats the documentation output as a JSON object, which is useful for machine parsing. | ansible-doc apt --json |
| -l, –list | Lists all available modules or plugins, often used with the -t option. | ansible-doc -l |
| -s, –snippet | Displays a minimal playbook snippet for a module or plugin. | ansible-doc -s template |
| -t, –type | Specifies the type of plugin you want to document. The default is module, but others include inventory, lookup, connection, etc. | ansible-doc -t inventory -l |
| -F, –list_files | Lists plugin names and their source file locations. | ansible-doc -F |
ansible-console
The ansible-console command provides an interactive shell for running Ansible ad-hoc commands. 💻 It’s an excellent tool for real-time debugging, exploration, and quick testing of modules across multiple hosts without having to write a full playbook.
How It Works
When you start ansible-console, it connects to all hosts in your specified inventory. You can then use a command-line interface to execute modules, apply filters, and interact with the hosts. It’s a faster alternative to repeatedly running ansible commands from your regular shell.
Common Commands within the Console
| Command | Description | Example |
cd <group> | Changes the current working group of hosts. You can cd into a specific group name, a single host, or use all to select all hosts. | cd web_servers |
list | Shows the hosts currently in the active working set. | list |
<module> <arguments> | Executes a module directly. This is the main function of the console. | ping |
? or help | Displays a list of available commands and basic help. | ? |
exit | Exits the ansible-console session. | exit |
Important Options
These options are used when you first launch ansible-console to define the environment.
| Option | Description | Example |
| -i, –inventory | Specifies the inventory file to use. | ansible-console -i hosts.yml |
| -l, –limit | Limits the interactive session to a specific subset of hosts. | ansible-console -i hosts.yml --limit "web_servers" |
| -b, –become | Enters the session with elevated privileges, prompting for a password if needed. | ansible-console -i hosts.yml -b |
| -u, –user | Specifies the remote user to connect as. | ansible-console -i hosts.yml -u ubuntu |
| -f, –forks | Sets the number of parallel processes to use during the session. | ansible-console -i hosts.yml -f 10 |
| -v, –verbose | Increases the verbosity of the output. Use -vvv for more detailed debug messages. | ansible-console -i hosts.yml -vvv |