Writing Your First Playbook

AnsibleBeginner
Practice Now

Introduction

In the previous lab, you ran a single command (ansible ... -m ping). While useful for quick checks, the real power of Ansible lies in Playbooks.

A playbook is a text file containing automation instructions. Unlike a normal shell script, a playbook usually focuses on the desired end state rather than every low-level command step.

That desired-state model is one of the most important Ansible ideas. Instead of saying "run these commands exactly," you usually describe the condition that should be true when automation finishes.

Playbooks are written in YAML, a human-readable data format. This helps make automation easier to review, share, and maintain.

In this lab, you will write a playbook that turns a server into a web server by:

  1. Installing Nginx (a popular web server).
  2. Ensuring the Nginx service is running.

You will then run this playbook to configure your local machine.

Create the Playbook File

We will start by creating the playbook file. By convention, the main playbook is often named site.yml.

First, make sure you are in the project directory:

cd ~/project

Now, create and open a new file named site.yml using the nano text editor:

nano site.yml

At the very top of the file, type three dashes. This marks the start of a YAML document.

---

YAML Rules to Remember:

  • Indentation is critical! You must use spaces (usually 2), not tabs. If your indentation is wrong, Ansible will complain.
  • Save the file often. In nano, press Ctrl+O then Enter to save, but keep the file open for the next steps.

Define the Play

A playbook consists of one or more "plays". A play maps a group of hosts to the tasks you want to run on them.

This mapping from host group to tasks is what lets one playbook scale from one machine to many. The logic stays in one place, while the inventory decides where it applies.

In your site.yml file, add the following lines below the ---.

---
- hosts: webservers
  become: yes

Understanding the code:

  • - hosts: webservers: This tells Ansible, "Run these instructions on every server listed in the [webservers] group in my inventory."
  • become: yes: This is like typing sudo before a command. It gives Ansible root privileges, which are needed to install software.

Make sure - hosts starts at the very beginning of the line (no spaces before the dash).

Save the file (Ctrl+O, Enter).

Add an Installation Task

Now we need to tell Ansible what to do. We do this by adding a list of tasks. Each task uses a module.

We will use the apt module (since we are on Ubuntu) to install Nginx.

Update your site.yml to look like this:

---
- hosts: webservers
  become: yes
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present

Understanding the code:

  • tasks:: Starts the list of tasks.
  • - name: ...: A description for humans. This will be printed to the screen when you run the playbook.
  • apt:: Calls the apt module.
  • name: nginx: Specifies the package we want.
  • state: present: This is the key "Declarative" part. We aren't saying "install it now". We are saying "ensure it is present".
    • If it's missing, Ansible installs it.
    • If it's already there, Ansible does nothing. This property is called Idempotency.

Idempotency is central to configuration management. It means you can safely run the same automation repeatedly and expect consistent results rather than duplicated side effects.

Check your indentation:

  • tasks should align with become.
  • - name should be indented (2 spaces).
  • apt should align with name.
  • name and state should be indented further under apt.

Save the file.

Add a Service Task

Just installing software isn't enough; we need to make sure the program is running. We use the service module for this.

This also shows how playbooks express system state in layers. One task ensures the package exists, and another ensures the service is active. Together they describe the end condition you want the host to reach.

Add a second task to your list in site.yml.

---
- hosts: webservers
  become: yes
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present

    - name: Start nginx
      service:
        name: nginx
        state: started

Understanding the code:

  • service:: This module manages system services (like systemctl).
  • state: started: Ensures the service is running. If it's stopped, Ansible starts it.

Important: The - for the second task must align exactly with the - of the first task.

Save and exit nano (Ctrl+X, then Y, then Enter).

Run the Playbook

Now comes the fun part: running your automation!

We use the ansible-playbook command. We need to tell it which playbook to run (site.yml) and which inventory to use (hosts.ini).

Run this command:

ansible-playbook site.yml -i hosts.ini

Watch the output. You will see:

  1. Gathering Facts: Ansible checks the system details first.
  2. Install nginx: It will show changed (yellow) because it had to install the package.
  3. Start nginx: It will show changed (yellow) if it had to start the service.

If you run the exact same command a second time, the output will be green and say ok. This means "Everything is already in the desired state, so I didn't change anything."

Finally, verify manually that Nginx is running:

systemctl status nginx

You should see "Active: active (running)".

Summary

In this lab, you wrote your first Ansible Playbook. You learned:

  1. YAML Syntax: How to structure a playbook with proper indentation.
  2. Plays: Defining hosts (where to run) and become (use sudo).
  3. Tasks: Using modules like apt (to install) and service (to start).
  4. Idempotency: The concept that running the playbook multiple times is safe and stable.

You have moved from running manual commands to defining "Infrastructure as Code."