ansible setup
Chapter 0 — Setup & Environment
1. Theory
Ansible is an agentless automation tool: the control node pushes configuration to managed nodes over standard transports (SSH for Linux/Unix, WinRM for Windows) with no persistent daemon required on the target. Everything is driven by three inputs: an inventory (what hosts exist), modules (the units of work), and playbooks (YAML files declaring desired state).
2. Internal Working
When you run ansible or ansible-playbook, the control node:
1. Parses the inventory to resolve target hosts and their connection variables.
2. For each host, opens an SSH connection using the configured user/key.
3. Copies the relevant Python module code to a temporary directory on the remote host.
4. Executes the module remotely with JSON arguments, capturing JSON output.
5. Cleans up the temporary files (unless ANSIBLE_KEEP_REMOTE_FILES=1 is set).
No agent persists after the run — the "footprint" on managed nodes is just a Python
interpreter and SSH access.
3. Diagram
Control Node Managed Node
┌──────────────┐ SSH (port 22) ┌──────────────┐
│ ansible-cli │ ───────────────────▶│ /tmp/.ansible│
│ inventory │ │ module.py │
│ playbook.yml │◀─── JSON result ────│ (executed) │
└──────────────┘ └──────────────┘
4. Commands
# Install (control node only — pip is the most version-flexible option)
python3 -m pip install --user ansible
# Verify
ansible --version
ansible-config dump --only-changed
# Test connectivity to a host group
ansible all -i inventory.ini -m ping
# Check syntax without running
ansible-playbook site.yml --syntax-check
5. Code Examples
# inventory.ini
[web]
web1 ansible_host=192.168.56.11
web2 ansible_host=192.168.56.12
[web:vars]
ansible_user=vagrant
ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key
# ansible.cfg
[defaults]
inventory = inventory.ini
host_key_checking = False
retry_files_enabled = False
6. Real-world Example
A team manages 40 web servers behind a load balancer. Instead of SSH-ing into each one
to patch a config file, they run ansible web -m ping to confirm reachability, then a
playbook to roll out the change to all 40 in one command, with connection details
centralized in ansible.cfg and inventory.ini instead of scattered scripts.
7. Production Example
Production setups almost never use host_key_checking = False (shown above only to
reduce local-lab friction) — instead they pre-populate known_hosts via a bootstrap step,
and pin Ansible's version in a requirements.txt/pipx install so every engineer and CI
runner uses an identical version, avoiding "works on my machine" drift in module behavior.
8. Common Mistakes
- Installing Ansible via the OS package manager and getting a version many releases
behind current — prefer
pip/pipxfor control-node tooling. - Forgetting Ansible needs Python on the managed node too (
ansible_python_interpretermay need to be set explicitly on minimal/Alpine images). - Mixing tabs and spaces in YAML — Ansible playbooks are YAML and are whitespace-sensitive.
9. Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
UNREACHABLE! ... Permission denied (publickey) |
Wrong user or key path | Check ansible_user / ansible_ssh_private_key_file |
/bin/sh: python3: command not found |
No Python on managed node | Set ansible_python_interpreter=/usr/bin/python3.x or bootstrap Python via raw module |
Host key verification failed |
New host not in known_hosts |
ssh-keyscan the host first, or set host_key_checking=False in dev only |
10. Security Notes
- Never disable
host_key_checkingin production — it removes MITM protection for the control channel. - Prefer SSH key auth over password auth; disable password auth on managed nodes once key rollout is confirmed.
- Restrict which users can run
ansible-playbookon the control node — it effectively has root-equivalent reach across your fleet if playbooks usebecome: true.
11. Interview Questions
- Why is Ansible called "agentless"? No persistent daemon runs on managed nodes; it connects over SSH/WinRM and executes modules on demand.
- What does Ansible require on the managed node? Python (for most modules) and SSH/WinRM access — no Ansible installation needed there.
- What's the purpose of
ansible.cfg? Centralizes default settings (inventory path, SSH behavior, retries) instead of passing flags every run. - How does Ansible execute a module? It copies module code to the target, runs it with JSON arguments, and parses the JSON response.
- What happens if Python isn't present on the target? Most standard modules fail;
you'd need
raworscriptmodules, or bootstrap Python first.
12. Hands-on Lab
- Spin up two local containers as fake managed nodes:
docker run -d --name node1 -p 2201:22 rastasheep/ubuntu-sshd - Write an inventory pointing at
localhost:2201with the right port/user. - Run
ansible all -m pingand confirmSUCCESS. - Intentionally break the SSH key path and observe the exact error message.
13. Hacks
ANSIBLE_STDOUT_CALLBACK=yamlgives far more readable task output than the default.ansible -m setup <host> | lessis a fast way to browse all available facts for a host.
14. Workarounds
- On hosts with no Python 3 (old distros), use
ansible_python_interpreter=auto_silentto let Ansible auto-detect, or bootstrap withraw: apt-get install -y python3. - If
host_key_checkingcan't be disabled by policy, pre-seedknown_hostsin your provisioning step instead.
15. Exercises
- Configure an inventory with three groups (web, db, cache) and verify
ansible <group> -m pingagainst each independently. - Break Python on a target container deliberately and fix it using the
rawmodule.
16. Quiz
- What transport does Ansible use for Linux managed nodes by default?
- True/False: Ansible requires an agent installed on every managed node.
- Which file centralizes default CLI behavior (inventory path, SSH settings)?
- What environment variable improves default output readability?
- What module would you use to bootstrap Python on a host that doesn't have it?
Answer Key
- SSH
- False
ansible.cfgANSIBLE_STDOUT_CALLBACK=yamlraw