Ansible in one page
Agentless config management explained — the mental model, the execution flow, and the commands you'll actually use.
· 6 min read
Most config-management tools require you to install something on every server you manage. Ansible does not. Here is the whole tool in one page.
The one-paragraph version
Ansible is agentless — there's no daemon on the target servers. From your laptop, you run a command. Ansible SSHes into each target, copies small Python scripts called modules, runs them, deletes them, and shows you what changed. That's it. The "configuration" lives in YAML files on your machine that describe the desired end state, and the modules are smart enough to skip work that's already done (idempotent).
What happens when you run a command
Every Ansible run follows the same flow:
- You type
ansible-playbook site.ymlon your laptop. - Ansible reads the inventory to find target hosts.
- For each host, open an SSH connection.
- Copy a small Python module (e.g.
apt,copy,service) into a temp directory on the target. - Run the module with arguments pulled from your YAML.
- The module reports back
okorchanged. - Delete the module. Close the connection.
No background process is left behind. The only software the target needs is SSH and Python — both already present on every Linux server you'd care about.
Why "idempotent" matters
Running the same playbook twice should leave the system in the exact same state as running it once. That property — called idempotency — is what makes Ansible safe to run on a Friday afternoon.
If a module would be a no-op, it skips. If a config file already matches the desired content, it does not rewrite it. The output tells you exactly what changed:
PLAY RECAP
public_ec2 : ok=12 changed=0 unreachable=0 failed=0Zero changed means: the system already looks how the playbook describes it.
Anatomy: inventory + playbook
Two kinds of YAML do most of the work.
Inventory — who to talk to. Lives in inventories/<env>/hosts:
[public]
public_ec2 ansible_host=54.12.34.56
[private]
db1 ansible_host=10.0.1.10
db2 ansible_host=10.0.1.11Playbook — what to do. Lives in playbooks/<name>.yml:
- hosts: public
become: yes
tasks:
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
enabled: yesThe playbook says "I want nginx installed and running." Ansible figures out the verbs.
The commands you'll actually use
Memorize five. Look up the rest when you need them.
Sanity check first
ansible all -m pingVerifies SSH works and Python is reachable on every host. Changes nothing. Always run this when you add a new host or rotate SSH keys.
Dry run before real apply
ansible-playbook playbooks/site.yml --checkReports what would change without making any changes. The seatbelt before any real run.
Real apply
ansible-playbook playbooks/site.ymlFull configuration across the entire inventory. The default, most common command.
Scope by group or single host
ansible-playbook playbooks/public.yml
ansible-playbook playbooks/private.yml
ansible-playbook playbooks/site.yml --limit public_ec2Groups (public, private) come from the inventory. --limit narrows further to a single host or pattern. Useful when only one tier needs changes — or when you're rolling out cautiously, one box at a time.
Scope by tag
ansible-playbook playbooks/public.yml --tags buildEach task in a playbook can carry tags. Use this when you only want to "rebuild the binary" and skip everything else (installing system packages, restarting services, etc.).
Debug what Ansible sees for a host
ansible public_ec2 -m debug -a "var=hostvars[inventory_hostname]"When a task does the wrong thing, the cause is usually a variable you didn't expect. This dumps every variable Ansible knows about the host — facts, group_vars, host_vars, the lot.
Ad-hoc commands, no playbook needed
ansible all -m shell -a "uptime"
ansible private -m shell -a "systemctl status postgresql" --becomeFor one-off ops: status checks, quick diagnostics. -m shell runs a shell command; --become runs it as root via sudo. Think of this as "ssh-for-loop with structure."
Encrypted secrets
ansible-vault edit inventories/staging/group_vars/private.ymlVault encrypts variable files at rest. The unencrypted content only exists in memory while the play runs — plaintext credentials never sit on disk or in git.
Collection dependencies
ansible-galaxy collection install -r requirements.ymlRun this once after cloning the repo, or whenever requirements.yml changes. Collections are how external modules ship — AWS, GCP, Kubernetes, community plugins, etc.
When to reach for Ansible
Reach for it when:
- You manage more than three servers by hand.
- You want infra changes to live next to code in git.
- You don't want to install an agent on every box.
Skip it when:
- You only manage one laptop — way too much machinery.
- You need real-time state convergence. Ansible runs when you run it, not on a schedule. Puppet or Chef fit that better.
- You're already all-in on Kubernetes — Helm charts and operators cover the same ground for the container side.
Closing
Ansible's value is that it's boring. SSH, Python, YAML. Nothing wakes you up at 2am because the agent died on a node — because there is no agent. If you've avoided it because the YAML feels verbose, the trade is fair: explicit YAML now, no surprises later.