A hands-on, progressive collection of Ansible playbooks designed to teach core concepts step by step — from your first ping to provisioning AWS infrastructure. Each numbered file builds on ideas introduced in the previous ones.
- Ansible installed (
pip install ansibleor your distro's package manager) - SSH access to managed nodes (for
webgroup plays) - Python 3 on managed nodes
- For AWS plays:
boto3,botocore, and theamazon.awscollection - For IP filter play:
ansible.utilscollection
| File | Purpose |
|---|---|
| ansible.cfg | Minimal config that points Ansible at the local inventory.ini so you don't have to pass -i every time. |
| inventory.ini | Defines host groups (backend, frontend, web, local), a parent group (expense:children), host-level variables, group variables, and connection credentials. |
| course.yaml | External variables file used by vars_files examples. Demonstrates separating data from playbooks. |
1-playbook.yaml — Your First Playbook
Teaches the basic playbook anatomy: name, hosts, tasks. Uses gather_facts: no to skip fact collection for speed.
- Modules:
ansible.builtin.ping
2-nginx.yaml — Privilege Escalation & Services
Introduces become: true for sudo and chaining multiple tasks (install + start + enable a service).
- Modules:
ansible.builtin.package,ansible.builtin.service
3-hello-world.yaml — Debug Output
The simplest way to print messages from a play.
- Modules:
ansible.builtin.debug
4-multiplay.yaml — Multiple Plays
Shows that a single YAML file can contain multiple plays. Introduces connection: local for managing the control node itself (no SSH needed).
- Modules:
ansible.builtin.debug
5-vars.yaml — Play-Level Variables
Define variables under vars: at the play level and reference them with Jinja2 {{ }} syntax.
6-task-vars.yaml — Task-Level Variables
Task-scoped variables override play-level ones, but only inside that task. Demonstrates variable scope.
7-vars.yaml — Variables From Files
Pull variables out of the playbook into a separate file using vars_files. Keeps playbooks reusable across environments.
8-vars-prompt.yaml — Interactive Prompts
Collect variables at runtime with vars_prompt. The private flag controls whether input is hidden (e.g., for passwords).
9-vars-inventory.yaml — Group-Level Inventory Vars
Variables defined under [group:vars] in the inventory file are available to all hosts in that group.
10-vars-inventory.yaml — Host-Level Inventory Vars
Variables defined directly on a host line in the inventory (e.g., host1 COURSE="...") are scoped to that host only.
11-vars-args.yaml — Command-Line Variables
Pass variables at runtime via --extra-vars (or -e). These have the highest precedence.
12-vars-preference.yaml — Variable Precedence
Combines all the above techniques in one file (commented out) so you can experiment and learn the order:
- Command line /
--extra-vars - Task-level
- Files (
vars_files) - Prompt (
vars_prompt) - Play-level (
vars) - Inventory
- Roles
13-data-types.yaml — YAML Data Types
Demonstrates strings, numbers, booleans, lists ([]), and maps ({}) — the building blocks of every playbook.
14-conditions.yaml — The when Keyword
Run tasks only when a condition is true. Uses comparison operators (>, <=).
15-facts.yaml — Ansible Facts
Print all auto-discovered system facts (ansible_facts) — OS family, IP, memory, hostname, etc.
16-conditions.yaml — Conditions + Facts (Real-World)
Combines facts and when to install nginx using the right package manager: dnf on RHEL, apt on Debian/Ubuntu.
- Modules:
ansible.builtin.dnf,ansible.builtin.apt
17-loops.yaml — Simple Loop
Iterate a list with loop: and reference each element via {{ item }}.
18-loops.yaml — Loop With a Module
Install multiple packages by looping over a list of names.
19-loops.yaml — Loop With Dictionaries
Loop over a list of dicts to drive multiple module arguments at once (item.name, item.state) — install some packages, remove others in one task.
20-filters.yaml — Jinja2 Filters
A tour of common filters:
default()— handle undefined variablessplit()— string → listdict2items/items2dict— convert between maps and listsupper/lower— case conversionmin/max— list aggregationansible.utils.ipaddr— IP validation- Also introduces
tags:to run a single task selectively.
21-shell-command.yaml — Shell vs Command
Shows the difference between shell (supports redirection, pipes) and command (safer, no shell features). Uses register: to capture output and demonstrates how command failures behave.
- Modules:
ansible.builtin.shell,ansible.builtin.command
22-ec2-route53.yaml — AWS Provisioning
End-to-end example: install AWS Python libs, launch multiple EC2 instances in a loop, capture their IPs with register, then create Route 53 DNS A-records — including a conditional public-IP record only for the frontend.
- Modules:
ansible.builtin.pip,amazon.aws.ec2_instance,amazon.aws.route53 - Concepts: registers, looping over registered results,
whenwith loop items
23-nginx.yaml — Rolling Deployments
Uses serial: 10 to run the play on 10 hosts at a time (rolling update pattern) and shows how tags: lets you skip or run individual tasks.
- Modules:
ansible.builtin.package,ansible.builtin.service
# Run a basic playbook
ansible-playbook 1-playbook.yaml
# Override variables from the command line
ansible-playbook 11-vars-args.yaml -e "COURSE=Ansible DURATION=10HRS TRAINER=Sivakumar"
# Run only tagged tasks
ansible-playbook 20-filters.yaml --tags uppertolower
# Limit to a single host group
ansible-playbook 16-conditions.yaml --limit web| Module | Used For |
|---|---|
ansible.builtin.ping |
Connectivity check |
ansible.builtin.debug |
Print messages and variables |
ansible.builtin.package |
OS-agnostic package management |
ansible.builtin.dnf / ansible.builtin.apt |
Distro-specific package management |
ansible.builtin.service |
Manage systemd/init services |
ansible.builtin.shell / ansible.builtin.command |
Run arbitrary commands |
ansible.builtin.pip |
Install Python packages |
amazon.aws.ec2_instance |
Provision EC2 instances |
amazon.aws.route53 |
Manage Route 53 DNS records |
ansible.utils.ipaddr |
IP address filter/validation |
Work through the files in numeric order. Each file is small on purpose — read it, run it, modify a value, run it again. By the time you reach 22-ec2-route53.yaml, you'll be combining variables, loops, registers, conditions, and external collections in a real provisioning workflow.