sn sysnerdunderstand it from the kernel up
← curriculum map
Ansible
Tool · ~45 min · 4 labs
map / The stack / Ansible
The stack Tool ~45 min requires: Linux

Ansible

Ansible is declarative convergence over SSH: describe the end state and let it make reality match, safely re-runnable. Where Terraform provisions infra, Ansible configures it.

Before you start. Install Ansible (sudo apt install -y ansible). You can target localhost, or reuse the Multipass VMs from the Linux module as an inventory.
Q1An ad-hoc command over the transportwarm-up

Ansible pushes over SSH (or local) and reports back. Start with the simplest possible action.

Task

Ping the local connection through Ansible.

Verify it yourself
verify
$ ansible localhost -m ping

You get "ping": "pong" — Ansible reached the host and ran a module.

Reveal solution
solution
$ ansible localhost -m ping
Q2Idempotency — run it twicecore

The core idea: a playbook describes an end state, not steps. Run it again and nothing changes — changed=0. This is what makes automation safe to repeat.

Task

Write a playbook that ensures a file exists, then run it twice.

Verify it yourself
verify
$ ansible-playbook site.yml   # second run

First run: changed=1. Second run: changed=0 — the end state already holds. That's idempotency.

Reveal solution
solution
$ cat > site.yml <<EOF
- hosts: localhost
  tasks:
    - name: ensure file
      copy: { content: "managed", dest: "/tmp/managed.txt" }
EOF
$ ansible-playbook site.yml
$ ansible-playbook site.yml   # changed=0
Q3Templating with Jinja2core

Configs are generated from templates + variables, so one playbook fits many hosts.

Task

Render a template that injects a variable into a file.

Verify it yourself
verify
$ cat /tmp/rendered.conf

The rendered file contains your variable's value — one template, many possible outputs.

Reveal solution
solution
$ echo "greeting = {{ msg }}" > tmpl.j2
$ cat > tpl.yml <<EOF
- hosts: localhost
  vars: { msg: "hello from ansible" }
  tasks:
    - template: { src: tmpl.j2, dest: /tmp/rendered.conf }
EOF
$ ansible-playbook tpl.yml
$ cat /tmp/rendered.conf
Sponsored

Reach engineers who read the man page

Native, contextual, no tracking — this is how the curriculum stays free.

Q4Break-and-fix — the non-idempotent taskdebug

Using command/shell for everything breaks idempotency — it runs every time and always reports changed. The fix is a proper module or a creates: guard.

Task

Write a task that always reports changed, then make it idempotent.

Verify it yourself
verify
$ ansible-playbook bad.yml   # second run still changed — then fix and re-check

Adding creates: (or switching to a state-based module) makes the second run report changed=0. Idempotency restored.

Reveal solution
solution
# bad:  - shell: touch /tmp/x        (always changed)
# good: - shell: touch /tmp/x
#         args: { creates: /tmp/x }   (changed only once)
What you just built

Push over SSH, idempotent end-state tasks, templating — Ansible converges hosts safely and repeatably. Terraform builds the servers; Ansible configures them; both plug into your GitHub Actions pipelines.