Ansible guide
What Ansible does in production
Ansible pushes desired state to servers: install packages, drop config files, restart services, create users, harden SSH. It is agentless — only SSH and Python on the target (or Windows WinRM). Teams run playbooks from laptops, bastions, or CI (Jenkins, GitHub Actions). It complements Terraform, which provisions cloud resources; Ansible often configures VMs after Terraform creates them.
Core concepts
- Control node — machine where you run
ansible-playbook - Managed node / host — target server in inventory
- Inventory — INI or YAML list of hosts and groups
- Playbook — YAML file with plays (mapped to host groups)
- Task — one module invocation with parameters
- Module — unit of work (
apt,copy,service) - Role — reusable bundle of tasks, handlers, templates, defaults
- Handler — task run only when notified (e.g. restart nginx)
Minimal playbook
---
- name: Web servers
hosts: web
become: true
tasks:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
- name: Ensure nginx running
ansible.builtin.service:
name: nginx
state: started
enabled: true
How a run works
- Inventory — resolve host list and variables per group
- Facts — gather OS, network, mounts (
setupmodule) unless disabled - Tasks — execute in order; each module reports changed/ok/failed
- Handlers — flush at end of play if notified
- Idempotency — second run should show mostly
ok, notchanged
Inventory
Static inventory.ini or dynamic inventory scripts (cloud APIs).
Groups like [web], [db]; children and group vars in
group_vars/, host-specific in host_vars/. Connection
details: ansible_host, ansible_user,
ansible_ssh_private_key_file — see the
SSH lab for keys and agent setup.
Become (privilege escalation)
become: true uses sudo (default) to run tasks as root. Requires
passwordless sudo or --ask-become-pass. Misconfigured become is a
frequent source of playbook failures on fresh VMs.
Variables and templates
Variables come from inventory, playbooks, roles, extra vars (-e), and
facts. Templates use Jinja2 (.j2 files) rendered by
the template module — typical for nginx, systemd unit files, and app
config.
Roles and splitting large playbooks
A single playbook with hundreds of inline tasks becomes hard to read, test, and reuse. Production repos break work into roles — one role per logical concern (base OS hardening, nginx, application deploy, monitoring agent). Thin entry playbooks wire roles together; each role owns its tasks, files, and templates.
Recommended layout:
site.yml— top-level playbook; one play per host group, lists rolesroles/common/— users, packages, sysctl, firewall baselineroles/nginx/— web server install, config, handlersroles/myapp/— app binaries, env files, service unitgroup_vars/andhost_vars/— environment-specific values
Standard role directories: tasks/, handlers/,
templates/, files/, defaults/ (easy overrides),
vars/ (higher precedence), and optional meta/main.yml for
role dependencies. Put reusable defaults in defaults/main.yml; callers
override in inventory or group_vars without editing the role.
---
# site.yml — keep plays short; delegate detail to roles
- name: Web tier
hosts: web
become: true
roles:
- role: common
- role: nginx
- role: myapp
- name: Database tier
hosts: db
become: true
roles:
- role: common
- role: postgresql
When to extract a role: repeated task blocks across plays, a
component owned by a different team, or anything you might reuse in another project.
Use import_role / include_role for conditional or
mid-play inclusion; list roles under roles: for the common case.
Pin third-party roles from Galaxy in requirements.yml and vendor them
in roles/ or document versions — same discipline as
Terraform modules.
Collections and Galaxy
Modules live in collections (e.g. ansible.builtin,
community.general). Install with ansible-galaxy collection install
or pin in requirements.yml. Galaxy shares roles and
collections — vendor with version pins for reproducible runs.
ansible.cfg
inventory— default inventory pathremote_user— SSH userhost_key_checking— SSH host key policyretry_files_enabled— write.retryon failure
Learning resources
- Ansible documentation — docs.ansible.com
- Getting started — Getting started guide
- Module index — Collection modules
- Ansible Galaxy — galaxy.ansible.com