ENGIMY.IO - CHEATSHEET
ANSIBLE × AUTOMATION
REFERENCE vAnsible Core 2.x

Ansible Quick Reference

Agentless automation – from ad‑hoc commands to complex, idempotent infrastructure as code.

Installation & Setup

# Install via pip (recommended)
pip install ansible
pip install ansible-core

# Verify
ansible --version

# Install via package manager (Ubuntu/Debian)
sudo apt update
sudo apt install ansible

# macOS
brew install ansible

# Configuration file hierarchy (lowest to highest precedence)
# 1. ANSIBLE_CONFIG (env var)
# 2. ./ansible.cfg
# 3. ~/.ansible.cfg
# 4. /etc/ansible/ansible.cfg

Inventory

Static Inventory (INI format)
# hosts.ini
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11

[dbservers]
db1 ansible_host=192.168.1.20 ansible_user=admin

[all:vars]
ansible_python_interpreter=/usr/bin/python3

# Group of groups
[production:children]
webservers
dbservers
Inventory in YAML
# hosts.yml
all:
  children:
    webservers:
      hosts:
        web1:
          ansible_host: 192.168.1.10
        web2:
          ansible_host: 192.168.1.11
    dbservers:
      hosts:
        db1:
          ansible_host: 192.168.1.20
Dynamic Inventory
  • AWS EC2: use aws_ec2 plugin.
  • Azure: azure_rm.
  • GCP: gcp_compute.
  • Custom scripts: executable that outputs JSON.
# Test inventory
ansible-inventory -i hosts.ini --list
ansible all -i hosts.ini --list-hosts

Ad‑hoc Commands

# Ping (ICMP + Python availability)
ansible all -i hosts.ini -m ping

# Shell / Command modules
ansible webservers -m shell -a "uptime"
ansible dbservers -m command -a "df -h"

# Copy file
ansible webservers -m copy -a "src=/local/file dest=/remote/file mode=0644"

# Install package
ansible webservers -m apt -a "name=nginx state=present" -b
ansible webservers -m yum -a "name=httpd state=latest" -b

# Service management
ansible webservers -m service -a "name=nginx state=restarted" -b

# Gather facts
ansible webservers -m setup
ansible webservers -m setup -a "filter=ansible_os_family"

Playbooks – Structure

---
- name: Deploy web application
  hosts: webservers
  become: true
  vars:
    app_port: 8080
    app_env: production

  tasks:
    - name: Ensure nginx is installed
      apt:
        name: nginx
        state: present

    - name: Start and enable nginx
      service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: Reload nginx
      service:
        name: nginx
        state: reloaded

Common Modules

Category Module Purpose
FilescopyCopy file from control to target
FilestemplateRender Jinja2 template
FilesfileManage files, dirs, symlinks, permissions
Systemapt / yumPackage management
SystemserviceManage systemd/init services
SystemuserManage user accounts
SystemfirewalldManage firewall rules
NetworkinguriHTTP requests
Cloudec2, azure_rmProvision cloud resources
GitgitClone / pull repositories
Dockerdocker_containerManage containers

Variables

Definition Sources (precedence high → low)
  • Extra vars (-e command line)
  • Playbook vars
  • Inventory host / group vars
  • Facts (gathered automatically)
  • Role defaults
# In playbook
vars:
  app_name: myapp
  versions:
    backend: 1.2.3
    frontend: 2.0.1

# Access
{{ app_name }}
{{ versions.backend }}

# Host vars (in inventory dir: host_vars/web1.yml)
---
ansible_host: 192.168.1.10
app_env: staging

# Group vars (group_vars/webservers.yml)
---
ntp_server: pool.ntp.org
Facts (System Information)
# Disable fact gathering for performance
- name: Fast playbook
  hosts: all
  gather_facts: false

# Use facts
{{ ansible_os_family }}
{{ ansible_distribution_version }}
{{ ansible_default_ipv4.address }}
{{ ansible_memtotal_mb }}

Conditionals

- name: Install Apache on Debian family
  apt:
    name: apache2
    state: present
  when: ansible_os_family == "Debian"

- name: Install httpd on RedHat family
  yum:
    name: httpd
    state: present
  when: ansible_os_family == "RedHat"

- name: Conditional with multiple conditions
  debug:
    msg: "Production environment"
  when:
    - env == "production"
    - app_port is defined

- name: Condition with failed task
  shell: /usr/bin/which nginx
  register: nginx_exists
  ignore_errors: true

- name: Only run if nginx exists
  debug:
    msg: "nginx is installed"
  when: nginx_exists.rc == 0

Loops

# Simple loop
- name: Create multiple users
  user:
    name: "{{ item }}"
    state: present
  loop:
    - alice
    - bob
    - charlie

# Loop with dict
- name: Install packages
  apt:
    name: "{{ item.name }}"
    state: "{{ item.state }}"
  loop:
    - { name: 'nginx', state: 'present' }
    - { name: 'postgresql', state: 'latest' }

# Loop over list of dicts with when
- name: Configure firewalls
  firewalld:
    port: "{{ item.port }}/{{ item.protocol }}"
    permanent: true
    immediate: true
    state: enabled
  loop:
    - { port: 80, protocol: tcp }
    - { port: 443, protocol: tcp }

# Until loop (retry)
- name: Wait for service to start
  shell: curl -s http://localhost:8080/health
  register: result
  until: result.stdout == "OK"
  retries: 10
  delay: 5

Templates (Jinja2)

# templates/nginx.conf.j2
server {
    listen {{ app_port }};
    server_name {{ server_name }};
    root /var/www/{{ app_name }};
    
    location / {
        try_files $uri $uri/ =404;
    }
}

# Playbook task
- name: Render nginx config
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/sites-available/default
  notify: Reload nginx
Common Jinja2 Filters
  • {{ value | default('fallback') }}
  • {{ my_list | join(',') }}
  • {{ my_dict | to_yaml }}
  • {{ my_string | upper }}
  • {{ ip | ipaddr('address') }}
  • {{ my_var | bool }}

Roles

Directory Structure
roles/
  common/
    tasks/
      main.yml
    handlers/
      main.yml
    vars/
      main.yml
    defaults/
      main.yml
    files/
    templates/
    meta/
      main.yml
  webserver/
    tasks/
      main.yml
    ...
Using Roles in Playbook
---
- name: Apply base configuration
  hosts: all
  roles:
    - common

- name: Setup web servers
  hosts: webservers
  roles:
    - webserver
    - { role: nginx, app_port: 8080 }  # with parameter
Ansible Galaxy (Public Roles)
# Install role from Galaxy
ansible-galaxy role install geerlingguy.docker

# Create new role skeleton
ansible-galaxy role init myrole

# List installed roles
ansible-galaxy role list

Handlers

Handlers run only when notified by a task (typically after a change).

- name: Restart nginx
  service:
    name: nginx
    state: restarted
  listen: "restart nginx"  # alternative to named handler

- name: Reload systemd
  systemd:
    name: myapp
    daemon_reload: true
    state: restarted

# In task:
- name: Update config
  template:
    src: app.conf.j2
    dest: /etc/myapp/app.conf
  notify:
    - Restart nginx
    - Reload systemd

Ansible Vault (Secrets Management)

# Encrypt a file
ansible-vault encrypt secrets.yml

# Decrypt
ansible-vault decrypt secrets.yml

# View encrypted file
ansible-vault view secrets.yml

# Edit encrypted file
ansible-vault edit secrets.yml

# Run playbook with vault password file
ansible-playbook playbook.yml --vault-password-file .vault_pass

# Encrypt a variable (--ask-vault-pass)
ansible-vault encrypt_string 'mysecret' --name 'db_password'

Tags and Includes

# Tag tasks
- name: Install packages
  apt:
    name: nginx
    state: present
  tags:
    - packages
    - nginx

- name: Configure app
  template:
    src: app.conf.j2
    dest: /etc/app.conf
  tags: 
    - config

# Run specific tags
ansible-playbook playbook.yml --tags "nginx,config"
ansible-playbook playbook.yml --skip-tags "packages"

# Include / import tasks
- name: Include common setup
  import_tasks: common/tasks/main.yml
- name: Include with variables
  include_tasks: setup.yml
  vars:
    setup_env: production

Best Practices

  • Use roles – for reusable, organised code.
  • Leverage variables – separate data from logic (group_vars, host_vars).
  • Make playbooks idempotent – run multiple times without side effects.
  • Use --check (dry‑run) – test changes before applying.
  • Use --diff – see what files changed.
  • Encrypt secrets – with Ansible Vault; never store plaintext passwords.
  • Use dynamic inventory – for cloud environments.
  • Set gather_facts to false when not needed for speed.
  • Use ansible-lint – validate playbook syntax and style.
  • Version control everything – playbooks, roles, inventory, vault files.
  • Use modules over shell/command – they are idempotent and safer.
  • Set retry_files_enabled = false in production to avoid leftover .retry files.

Debugging & Troubleshooting

# Verbose output ( -v, -vv, -vvv, -vvvv )
ansible-playbook playbook.yml -vvv

# Debug module
- name: Print variable
  debug:
    var: my_var

- name: Print message
  debug:
    msg: "The app port is {{ app_port }}"

# Check syntax
ansible-playbook playbook.yml --syntax-check

# Dry-run
ansible-playbook playbook.yml --check

# Step-by-step execution
ansible-playbook playbook.yml --step

# Limit to specific hosts
ansible-playbook playbook.yml --limit web1,web2

Performance Tuning

  • Increase forks – in ansible.cfg (default 5, try 20–50).
  • Use pipelining – reduces SSH overhead (enable in ansible.cfg).
  • Use control_persist – reuses SSH connections.
  • Disable fact gathering – with gather_facts: false.
  • Use strategy: free – faster parallel execution (instead of linear).
  • Cache facts – use cache plugin (Redis, Memcached, JSON).
# ansible.cfg performance settings
[defaults]
forks = 30
pipelining = True
timeout = 30

[ssh_connection]
control_path = /tmp/ansible-%%h-%%p
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
📌 Quick Reference
Ad‑hoc: ansible all -m ping
Playbook: ansible-playbook site.yml
Inventory: INI / YAML / dynamic plugins
Key modules: copy, template, file, apt/yum, service, user, git
Secrets: ansible‑vault encrypt / edit / view
Debug: -vvv, debug module, --check, --step
Best practice: Roles + group_vars + vault + idempotency
← Back to All Cheatsheets