Skip to content
← DevOps foundations

Learning bite

Ansible and your first playbook

Understand the execution model and make one repeatable local file change.

Documentation reviewed2026-10-01 · 3 min read
On this page

Describe the host state you need

Terraform commonly creates infrastructure resources. Ansible commonly configures machines: files, users, packages, and services. Their capabilities overlap, so choose one clear owner for each setting. Two tools independently editing the same file make the result harder to predict.

Ansible runs from a control node, such as your Mac, and executes work on managed nodes, such as Linux VMs. An inventory names those targets. A playbook is a YAML file containing plays; each play selects hosts and a sequence of tasks. A task calls a module, a small unit that knows how to perform an operation and report its result.

For normal Linux automation, Ansible connects over SSH, sends module work to the target, runs it with a compatible Python interpreter, and receives structured results. There is no persistent Ansible agent to install on that target. Modules and connection types have their own requirements; “agentless” does not mean every machine needs no preparation. For this first exercise, the local connection makes the control machine its own target.

Install a compatible runtime

Follow the Ansible installation guide↗ and its Python support matrix. ansible-core supplies the runtime and built-in modules; the larger ansible package includes additional collections. A collection groups modules, plugins, and other reusable automation.

One option on macOS/Linux is a separate virtual environment. From a fresh ansible-practice directory, with a Python version supported by the Ansible release you choose:

bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install ansible-core
ansible --version

The installation downloads a package. Record the resolved Ansible and Python versions, and pin those versions when making your project reproducible. Keep .venv/ out of Git. If Python compatibility fails, select a supported pairing from the guide rather than installing into system Python.

Write one complete playbook

Save first.yml in that directory:

yaml
- name: Learn a local file change
  hosts: localhost
  connection: local
  gather_facts: false
  tasks:
    - name: Write our practice marker
      ansible.builtin.copy:
        dest: "{{ playbook_dir }}/first-marker.txt"
        content: "Ansible manages this practice file.\n"
        mode: '0600'

YAML indentation expresses structure: the play is a list item, tasks is a list inside it, and the module's arguments are nested under its name. Spaces matter; tabs are not a substitute. Quoting the mode keeps it a string. The Jinja expression {{ playbook_dir }} means the directory containing this playbook.

From this directory run:

bash
ansible-playbook -i localhost, first.yml --syntax-check
ansible-playbook -i localhost, first.yml
ansible-playbook -i localhost, first.yml
cat first-marker.txt

The comma tells Ansible that localhost, is an inline host list rather than a filename. Expect the marker content exactly as shown. If absent initially, the first copy task should report changed; with matching contents and permissions, the second should report no change. No SSH server or elevated privileges are needed for this local file.

Understand the second run

An idempotent operation can be repeated with the same desired inputs without causing additional changes once they match. The copy module compares the desired contents and metadata with the current file. This differs from blindly appending a line on every run.

Edit the marker text manually, then rerun the playbook. It should restore the desired line. That manual difference is drift. If you later remove the task, Ansible does not infer that it should delete the file; removal must be explicit or handled during cleanup.

Checkpoint: where does this task execute? On your control machine, because the local connection is explicit. Does changed=0 prove an application works? No application was started. Remove only first-marker.txt when finished and keep the playbook. Next, select and test a remote learning machine through inventory.

References: first playbook↗, copy module↗, and playbook introduction↗.

Your notes and evidence

Record observations, questions, or links to your work. Keep credentials out of your notes.

Loading saved progress…

Back up or restore this path

Progress and notes stay in this browser. A backup contains only this learning path.