SynfraCore
Synfracore
Start Learning
Navigation

Academies

Platform

RoadmapsLabsCertificationsInterviewPYQsAI AssistantCareer
Start Learning Free🗺️ Learning Roadmaps

AnsibleAdvanced

Production patterns, performance, security hardening

✍️
Written by senior engineers. Reviewed for technical accuracy.· Updated 2025 · SynfraCore Ansible Team
Expert Content

Ansible — Advanced

Ansible Vault — Encrypting Secrets

Ansible Vault encrypts sensitive files (passwords, keys, certificates) so you can safely commit them to version control.

bash
# Create a new encrypted file
ansible-vault create secret.txt
# New Vault password: mypassword
# Confirm New Vault password: mypassword
# Opens editor — type your secret content and save

# View encrypted file — it looks like this:
cat secret.txt
$ANSIBLE_VAULT;1.1;AES256
64633234613936303336
32363332373562333736...  (encrypted gibberish)

# Edit an encrypted file
ansible-vault edit secret.txt

# Encrypt an existing file
ansible-vault encrypt secret2.txt
# New Vault password:
# Confirm New Vault password:
# Encryption successful

# Decrypt a file permanently
ansible-vault decrypt secret.txt

# Change the vault password (rekey)
ansible-vault rekey secret2.txt
# Vault password: (old password)
# New Vault password: (new password)
# Confirm New Vault password:
# Rekey successful
# Note: must enter old password before entering new one

Using Vault in Playbooks

yaml
# vars/secrets.yml (encrypted with ansible-vault)
db_password: "myS3cr3tP@ssw0rd"
api_key: "sk-abc123def456"

# playbook.yml
---
- name: Deploy app with secrets
  hosts: webservers
  vars_files:
    - vars/secrets.yml    # Ansible decrypts this at runtime

  tasks:
    - name: Configure database
      template:
        src: db.conf.j2
        dest: /etc/myapp/db.conf
bash
# Run playbook with vault password
ansible-playbook playbook.yml --ask-vault-pass

# Or use a password file (better for automation)
echo "mypassword" > ~/.vault_pass
chmod 600 ~/.vault_pass
ansible-playbook playbook.yml --vault-password-file ~/.vault_pass

# Or set in ansible.cfg
[defaults]
vault_password_file = ~/.vault_pass

Ansible Roles

Roles are the standard way to organize playbooks into reusable, shareable components.

Role Directory Structure

roles/
└── httpd-role/
    ├── tasks/
    │   └── main.yml       # main task list
    ├── handlers/
    │   └── main.yml       # handlers
    ├── templates/
    │   └── index.j2       # Jinja2 templates
    ├── files/
    │   └── httpd.conf     # static files to copy
    ├── vars/
    │   └── main.yml       # role variables (high priority)
    ├── defaults/
    │   └── main.yml       # default variables (lowest priority)
    ├── meta/
    │   └── main.yml       # role metadata, dependencies
    └── README.md

Creating a Role

bash
# Create role structure automatically
ansible-galaxy init httpd-role
cd httpd-role
yaml
# tasks/main.yml
---
- name: Install httpd
  yum:
    name: httpd
    state: latest

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

- name: Create index.html using Jinja2
  template:
    src: index.j2
    dest: /var/www/html/index.html
jinja2
{# templates/index.j2 #}
Welcome to {{ inventory_hostname }}

This is an Apache Web Server.

Please contact {{ sysadmin }} for any questions or concerns.
yaml
# defaults/main.yml — default variable values (can be overridden)
---
sysadmin: sysadmin@example.com
yaml
# handlers/main.yml
---
- name: Restart httpd
  service:
    name: httpd
    state: restarted

Using Roles in Playbooks

yaml
# apache-role.yml
---
- name: Use the httpd-role
  hosts: webservers
  roles:
    - httpd-role              # apply the role

# Override role defaults
- name: Use role with custom vars
  hosts: webservers
  roles:
    - role: httpd-role
      vars:
        sysadmin: admin@mycompany.com

# Static import (processed at parse time)
- name: Apply roles
  hosts: all
  tasks:
    - import_role:
        name: httpd-role

# Dynamic include (processed at runtime)
- name: Apply role conditionally
  hosts: all
  tasks:
    - include_role:
        name: db_role
      when: inventory_hostname in groups['dbservers']

Ansible Galaxy — Public Roles

bash
# Search for community roles
ansible-galaxy search nginx

# Install a role from Galaxy
ansible-galaxy install geerlingguy.nginx
ansible-galaxy install geerlingguy.mysql

# Install multiple roles from requirements file
cat requirements.yml
---
- name: geerlingguy.nginx
  version: 3.0.0
- name: geerlingguy.mysql
  version: 4.3.2

ansible-galaxy install -r requirements.yml

# List installed roles
ansible-galaxy list

# Roles are installed to ~/.ansible/roles/ by default

Managing Software — Module Reference

Modules for package management:

yaml
# package — distro-agnostic (auto-detects yum/apt/dnf)
- package:
    name: vim
    state: present

# yum — RHEL/CentOS specific
- yum:
    name: httpd
    state: latest        # present, absent, latest

# apt — Debian/Ubuntu specific
- apt:
    name: nginx
    state: present
    update_cache: yes    # run apt update first

# yum_repository — add YUM repos
- yum_repository:
    name: zabbix-monitoring
    description: Zabbix 5.2 Repo
    baseurl: https://repo.zabbix.com/zabbix/5.2/rhel/8/x86_64/
    enabled: yes
    gpgcheck: no

# package_facts — get info about installed packages
- package_facts:
    manager: auto

- debug:
    msg: "nginx version: {{ ansible_facts.packages['nginx'][0]['version'] }}"

# rpm_key — GPG key management
- rpm_key:
    key: https://packages.chef.io/chef.asc
    state: present

# redhat_subscription — RHEL subscription management
- redhat_subscription:
    state: present
    username: user@redhat.com
    password: "{{ rhsm_password }}"

Real Example: Add Zabbix Repo and Install Agent

yaml
---
- name: Manage Software
  hosts: node1
  become: yes
  tasks:
    - name: Add Zabbix repository
      yum_repository:
        name: zabbix-monitoring
        description: "Zabbix 5.2 Repo"
        baseurl: https://repo.zabbix.com/zabbix/5.2/rhel/8/x86_64/
        enabled: yes
        gpgcheck: no

    - name: Install zabbix-agent
      yum:
        name: zabbix-agent
        state: present

    - name: Display zabbix-agent info
      package_facts:
        manager: auto

    - name: Show installed version
      debug:
        msg: "zabbix-agent version: {{ ansible_facts.packages['zabbix-agent'][0]['version'] }}"

RHEL System Roles (NTP Example)

RHEL System Roles are pre-built roles from Red Hat:

bash
# Install RHEL System Roles
dnf install rhel-system-roles -y
# Roles installed to: /usr/share/ansible/roles/
yaml
# Configure NTP with timesync role
---
- name: Configure NTP using timesync role
  hosts: node1
  vars:
    timesync_ntp_servers:
      - hostname: 0.north-america.pool.ntp.org
        iburst: yes
      - hostname: 1.north-america.pool.ntp.org
        iburst: yes
      - hostname: 2.north-america.pool.ntp.org
        iburst: yes
      - hostname: 3.north-america.pool.ntp.org
        iburst: yes
  roles:
    - rhel-system-roles.timesync
bash
# Verify NTP is configured on node1
ansible node1 -m command -a "cat /etc/chrony.conf"
# node1 | CHANGED | rc=0 >>
# # Ansible managed
# server 0.north-america.pool.ntp.org iburst
# ...

ansible node1 -m command -a "timedatectl"
# Local time:     Sat 2020-11-14 21:08:46 CST
# System clock synchronized: yes

Ansible Troubleshooting

bash
# Verbose mode — see exactly what Ansible is doing
ansible-playbook playbook.yml -v     # basic
ansible-playbook playbook.yml -vv    # more detail
ansible-playbook playbook.yml -vvv   # connection debug (SSH level)
ansible-playbook playbook.yml -vvvv  # maximum (plugin level)

# Check mode (dry run) — shows what WOULD change, makes no changes
ansible-playbook playbook.yml --check

# Start at a specific task
ansible-playbook playbook.yml --start-at-task="Install nginx"

# Run only specific tags
ansible-playbook playbook.yml --tags "install,configure"
ansible-playbook playbook.yml --skip-tags "restart"

# List tasks without running them
ansible-playbook playbook.yml --list-tasks

# List hosts that would be targeted
ansible-playbook playbook.yml --list-hosts

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

# Limit to specific hosts
ansible-playbook playbook.yml --limit node1
ansible-playbook playbook.yml --limit "node1,node2"
ansible-playbook playbook.yml --limit webservers

# Step through tasks one at a time (confirm each)
ansible-playbook playbook.yml --step

Common Errors and Fixes

bash
# Error: "UNREACHABLE" 
# Fix: Check SSH connectivity and host key
ssh -i ~/.ssh/id_rsa user@nodeIP
# If first time: accept fingerprint manually, then Ansible works

# Error: "Missing sudo password"
# Fix: Add become_pass or configure NOPASSWD in sudoers
ansible-playbook playbook.yml --ask-become-pass

# Error: "Python not found on managed node"  
# Fix: Install Python or specify interpreter
ansible all -m ping -e "ansible_python_interpreter=/usr/bin/python3"

# Error: "Permission denied reading /etc/shadow"
# Fix: Add become: yes to play or task
- name: Read shadow file
  command: cat /etc/shadow
  become: yes

# Error: Module fails but want to continue
# Fix: ignore_errors on that specific task
- name: Task that might fail
  command: might-fail
  ignore_errors: yes

Dynamic Inventory

Instead of static inventory files, generate inventory dynamically from cloud APIs:

bash
# AWS EC2 dynamic inventory
pip install boto3
cat aws_ec2.yml:
---
plugin: aws_ec2
regions:
  - ap-south-1
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: instance_type
    prefix: type

ansible-inventory -i aws_ec2.yml --list    # show all hosts
ansible-playbook -i aws_ec2.yml playbook.yml

# Azure dynamic inventory
pip install azure-cli-core azure-mgmt-compute
ansible-playbook -i azure_rm.yml playbook.yml

ansible-doc — Built-in Documentation

bash
# List all available modules
ansible-doc -l

# Get full documentation for a module
ansible-doc yum
ansible-doc copy
ansible-doc template
ansible-doc user
ansible-doc service
ansible-doc file
ansible-doc blockinfile    # add a block of text to a file
ansible-doc lineinfile     # manage single lines in a file

# Short synopsis only
ansible-doc -s yum
Share:
Join our Community
Daily tips, job alerts, interview help — join engineers learning together
Quick Check — Ansible
1 / 1

What is the first step when optimizing a production system?

Up Next
🗺️
AnsibleRoadmap
Step-by-step structured learning path from zero to expert
Also Worth Exploring
← Back to all Ansible modules
IntermediateRoadmap