Ansible is not magic, and it is not complicated. It is a declarative automation tool that answers one question:
“What should the system look like when I’m done?”
In two articles, you’ll learn the core concepts of Ansible and apply them through small, practical tasks.
We explain how to set up a fully functional WordPress website using Ansible to install and configure everything you need: PHP, a database, and a web server.
First things first. Let’s understand how Ansible works and learn how to use it with simple tasks.
1. What Ansible Is (and Is Not)
What Ansible is
- Agentless automation tool (no daemon on target machines)
- Uses SSH (or WinRM for Windows)
- Written in Python, configured in YAML
- Focused on idempotency (safe to run multiple times)
What Ansible is not
- Not a configuration language like Bash
- Not a replacement for Docker or Kubernetes
- Not a CI/CD system (but integrates well with them)
Key idea:
Ansible describes the desired state, not step-by-step instructions.
2. The Ansible Execution Model (Big Picture)
When you run Ansible:
- You run
ansibleoransible-playbookfrom your machine - Ansible connects to target hosts via SSH
- It runs modules remotely
- Modules report whether they changed anything
- Ansible prints a summary
No agent. No polling. No persistent connection.
3. Inventory: “Which machines do I manage?”
The inventory defines where Ansible runs.
Minimal inventory (INI format)
[servers]
server1 ansible_host=192.168.1.10 ansible_user=deploy
YAML inventory (recommended)
all:
hosts:
server1:
ansible_host: 192.168.1.10
ansible_user: deploy
ansible_port: 2222
Important ideas:
- Inventory is data, not code
- You can attach variables to hosts and groups
- Inventory can be static (files) or dynamic (cloud APIs)
Mini-task
Run:
ansible all -i inventory.yml -m ping
If you see pong, Ansible works.
4. Modules: The Building Blocks
Ansible does almost nothing itself.
It calls modules.
Examples:
apt→ install packagesuser→ manage usersservice→ start/stop servicescopy→ copy filestemplate→ generate config files
Example: install a package
ansible all -m apt -a "name=vim state=present" --become
Why modules matter
- They are idempotent
- They know how to check the current state
- They return structured results
Bad mindset:
shell: apt install vim -y
Good mindset:
apt:
name: vim
state: present
5. Playbooks: Describing Desired State
A playbook is a list of plays.
A play map:
hosts → tasks
Minimal playbook
- name: Install basic tools
hosts: all
become: true
tasks:
- name: Install vim
apt:
name: vim
state: present
Run it:
ansible-playbook site.yml
Rerun it.
Notice: no changes → idempotency.
6. Tasks: Small, Explicit Actions
A task is:
- One module call
- With clear intent
- With a descriptive name
Good task
- name: Install curl
apt:
name: curl
state: present
Bad task
- name: Do stuff
shell: |
apt update
apt install curl -y
Rule of thumb:
If a task name doesn’t read like English, rewrite it.
7. Variables: Making Playbooks Reusable
Hardcoding values is how automation dies.
Variables in a playbook
vars:
package_name: curl
- name: Install package
apt:
name: "{{ package_name }}"
state: present
Variables from the inventory
server1:
ansible_host: 192.168.1.10
app_user: deploy
Variables allow:
- Environment differences (dev/prod)
- Reusable roles
- Cleaner templates
8. Handlers: Reacting to Change
Handlers run only if notified.
Example
- name: Copy config
copy:
src: app.conf
dest: /etc/app.conf
notify: Restart app
handlers:
- name: Restart app
service:
name: app
state: restarted
Key insight:
Handlers prevent unnecessary restarts.
9. Templates: Config Files Done Right
Templates use Jinja2.
Template (nginx.conf.j2)
server {
listen {{ port }};
server_name {{ domain }};
}
Task
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
This is how you avoid:
- Copy-paste configs
- Environment-specific files
- Manual edits on servers
10. Roles: Scaling Without Chaos
When playbooks grow, you need structure.
A role is a self-contained unit:
roles/
web/
tasks/
handlers/
templates/
defaults/
Roles allow:
- Reuse
- Testing
- Clear ownership
- Clean playbooks
Playbook with roles
- hosts: all
roles:
- web
- database
This is how real teams use Ansible.
11. Idempotency: The Core Principle
Idempotency means:
Running the same playbook multiple times leads to the same result.
Why it matters:
- Safe automation
- Easy recovery
- Predictable deployments
Ansible success metric:
You can run your playbook anytime without fear.
12. How to Think in Ansible (Mental Shift)
❌ “How do I do this?”
✅ “What should exist?”
❌ “Run this command.”
✅ “Ensure this state.”
❌ “One big script.”
✅ “Many small, clear tasks.”
If you adopt this mindset, Ansible becomes simple.
13. Small Practice Assignment (Before the Next Article)
Do this before reading the WordPress HOW-TO:
- Create an inventory with one Debian host
- Write a playbook that:
- Updates apt cache
- Installs
curl,vim,htop - Ensures
lighttpdis installed (not configured yet)
- Add a handler that restarts lighttpd only if needed
- Run the playbook twice
If this feels boring — good.
That means automation is working.
What’s Next
In the following article, we’ll apply everything you learned here to a real, production-style task:
Automatically installing WordPress on Debian using
lighttpd + MariaDB + PHP-FPM — cleanly, reproducibly, and safely.