Ansible is a configuration management system written in Python (Private) and maintained by Red Hat.


  • Inventory describes the systems we want to manage and groups them for easier management.
    • Static inventory, as an INI file (Private). Servers are grouped using headings, with nested groups denoted using colons (:) in section headings. Groups can be members of other groups.
    • Dynamic inventory, using configuration stores like Cobbler.
  • Tasks perform one-off operations, useful for exploration and quick configuration changes.
  • Modules perform actions, generally idempotently.
  • Tasks are instances of Modules, with a configuration.
  • Playbooks are user-configured sets of Tasks.
  • Facts provide data to be used for targeting.


  • Galaxy is a package manager for Ansible modules.
  • Tower provides a compliance/reporting dashboard.


Ansible is agent-less by default, using SSH to administrate systems remotely.


For Linux systems, Ansible is distributed as a single ansible package.


Ansible searches for its con figuration file in this order:

  1. The ANSIBLE_CONFIG environment variable overrides the search behaviour.
  2. ./ansible.cfg in the current working directory.
  3. ~/.ansible.cfg in your home directory.
  4. As a last resort, /etc/ansible/ansible.cfg.

By default, the configuration is structured as follows:

  • /etc/ansible/:
    • ansible.cfg:
      • [defaults]
        • inventory
        • remote_user
        • remote_ports
        • ask_pass
      • [privilege_escalation]
        • become
        • become_user
        • become_method
        • become_ask_pass



When expressing inventory as a static file, the inventory file looks something like this:



ansible-inventory can be used to examine the inventory's content.


Dynamic inventory is provided by inventory scripts, executable programs which generate the inventory contents automatically. They might be used together with a CMDB or asset register. They can be written in any programming language, and just need to be marked as executable and able to output a JSON structure like the following:

    "all": {
        "children": ["x"]

Running ad hoc tasks

Execute ad hoc tasks:

ansible host-pattern -m module [-a args] [-i inventory]

Common modules

Common modules (list more with ansible-doc -l):

  • copy copies a local file to the managed host.
  • file sets content and properties of files.
  • lineinfile ensures a specific line exists within a file.
  • ping performs a basic connectivity test.
  • synchronize copies files and directories using rsync.


The template module allows templating files using the Jinja template engine (Private):

- name: Generate the nginx server {}
      src: nginx.server.j2
      dest: /etc/nginx/conf.d/server.conf
      owner: root
      group: root
      mode: "0600"

Useful variables:

Lookup plugins allow templating using data from outside of Ansible. There are two functions for interacting with them:

  • lookup(plugin, object) yields a comma-delimited string of items; and
  • query(plugin, object) yields a list of items.

Some common lookup plugins:

  • file reads file content.
  • lines gets content of a file as a list of lines.
  • template renders a template and yields output.
  • url fetches content of a web page or API query.

Details of others are available in the documentation:

ansible-doc -t lookup

Host patterns

Host patterns denote which systems upon which a task should be executed.

  • all specifies all hosts.
  • Host and group names.


Playbooks define automated tasks for Ansible to execute. They describe the desired state of the environment using YAML (*.yml). Ordering is top to bottom, in the definition order.

They're made up of the following files:

  • ansible.cfg configures Ansible.
  • inventory defines the hosts and groups.
  • group_vars/
    • all/
      • vars.yml defines variables applied to all deployments.
    • <environment>/
      • vars.yml defines variables applied to just the <environment> environment.
  • host_vars/
  • requirements.yml lists dependent roles
  • site.yml defines the primary Playbook

The structure:

- name: The name of the Playbook
  hosts: webservers
      key: value
    - vars/webservers.yaml
    - name: The name of the job
            property: value

Playbooks can be executed as follows:

ansible-playbook some-playbook

To perform a dry-run, specify the -C (--check) switch.


Variables can be declared at multiple scopes, with those at the bottom taking precedence:

  1. CLI arguments
  2. Role defaults
  3. Inventory file or script group variables
  4. Inventory group_vars/all
  5. Playbook group_vars/all
  6. Inventory group_vars/*
  7. Playbook group_vars/*
  8. Inventory file or script host variables
  9. Inventory host_vars/*
  10. Playbook host_vars/*
  11. Host facts (including cached set_facts)
  12. Play vars
  13. Play vars_prompt
  14. Play vars_files
  15. Role variables (defined in role's /vars/main.yml)
  16. Block variables
  17. Task variables
  18. include_vars
  19. set_facts and register variables
  20. Role (and include_role) parameters
  21. include_* parameters
  22. CLI --extra-vars


Vault encrypts secrets stored in Playbooks for safe storage in source code management systems. It's managed using the ansible-vault CLI:

  • create
  • view
  • edit
  • encrypt
  • decrypt
  • rekey to change a key.

Encryption keys are specified using the --vault-id parameter, and are named in the form label@source. prompt is a commonly used source, causing Ansible to prompt the user for the encryption passphrase.

In task definitions, include_vars can be used to load variables.


Loops allow reducing duplication, and altering the structure of a playbook based upon variable contents.

- name: loops
  hosts: all
    - name: list
            msg: "{{ item }}"
          - a
          - b
    - name: dict
            msg: "({{ item.x }}, {{ item.y }})"
          - { x: 1, y: 1 }
          - { x: 2, y: 2 }
    - name: list from variable
            msg: "{{ item }}"
        loop: "{{ some_variable }}"


Tasks can include a register key, making its execution result available as a variable for later conditional evaluation.


Conditionals can be used to constrain execution of a module based on variables. They're specified using the when key on a task. Conditions:

  • bool_value and not bool_value
  • var is defined and var is not defined
  • x == y and x != y
  • x < y, x <= y, x >= y, x > y
  • value in set
  • and and or can be used to combine conditions

When when is specified as a list, all conditions in the list must evaluate to true (they're grouped by and). Parentheses can be used for grouping conditions.

ansible_facts is a dictionary of values about the host which may be useful here:


Handlers provide a publisher-subscriber model for delaying or re-applying modules based on changes happening elsewhere. A notifying task can specify a notify key, which will cause all tasks with the same value in their listen key to re-run.

Note that handlers will run most once after all notifications to the handler in the Play have completed.


Blocks allow grouping logically related tasks together, and allow for a try-except-finally approach to error handling:

  - name: Do a bunch of things
        - name: Step one
                msg: Step one
        - name: Step two
                msg: Step two
        - name: Rescue
                msg: Failed
        - name: Always
                msg: Complete


Roles package tasks in a form allowing reuse with a different set of variables, allowing Playbooks to scale to larger projects through composition of smaller, focused modules.

ansible-galaxy init some-role creates a structure like the following:

  • some-role/ is the root of the role.
    • defaults/ contains default values, intended to be overridden in Plays.
      • main.yml
    • files/
    • handlers/
      • main.yml
    • meta/ contains authorship, licensing and dependency metadata about the role.
      • main.yml
    • tasks/ is similar to the tasks section of a Play.
      • main.yml
    • templates/
    • tests/
      • inventory
      • test.yml
    • vars/ contains values not intended for overriding in Plays.
      • main.yml

Roles are consumed in the roles section of a Playbook:

- name: Some Playbook
  hosts: all
    - some-role