What is Ansible?

Ansible is an open-source automation tool that lets you configure servers, deploy applications, and orchestrate complex workflows — all using simple YAML files called playbooks.

Why developers love Ansible:

  • Agentless — no software to install on target machines, just SSH
  • YAML-based — human-readable, version-controllable
  • Idempotent — run playbooks multiple times safely
  • Batteries included — 3,000+ built-in modules for every task

Prerequisites

  • A Linux/macOS machine (or Windows with WSL) — see How to Install Ansible
  • Basic terminal/command-line knowledge
  • SSH access to at least one remote host (or use localhost)

Step 1: Install Ansible

# Quick install via pip
pip3 install ansible

# Verify
ansible --version

Or try our Ansible Playground — run playbooks in your browser with zero setup.

Step 2: Create Your Inventory

The inventory defines which hosts Ansible manages:

# inventory.ini
[webservers]
web1 ansible_host=192.168.1.10 ansible_user=ubuntu
web2 ansible_host=192.168.1.11 ansible_user=ubuntu

[dbservers]
db1 ansible_host=192.168.1.20 ansible_user=centos

Test connectivity:

ansible all -i inventory.ini -m ping

Step 3: Write Your First Playbook

Create first-playbook.yml:

---
- name: My first Ansible playbook
  hosts: webservers
  become: true

  tasks:
    - name: Ensure Apache is installed
      ansible.builtin.apt:
        name: apache2
        state: present
        update_cache: true

    - name: Start Apache service
      ansible.builtin.service:
        name: apache2
        state: started
        enabled: true

    - name: Deploy index page
      ansible.builtin.copy:
        content: "<h1>Hello from {{ inventory_hostname }}</h1>"
        dest: /var/www/html/index.html

Run it:

ansible-playbook -i inventory.ini first-playbook.yml

Step 4: Understand Key Concepts

Modules

Modules are the units of work in Ansible. Common ones:

ModulePurposeExample
ansible.builtin.aptInstall packages (Debian)apt: name=nginx state=present
ansible.builtin.yumInstall packages (RHEL)yum: name=httpd state=present
ansible.builtin.copyCopy filescopy: src=file.txt dest=/tmp/
ansible.builtin.templateTemplate files with Jinja2template: src=app.conf.j2 dest=/etc/
ansible.builtin.serviceManage servicesservice: name=nginx state=started
ansible.builtin.fileManage files/directoriesfile: path=/data state=directory
ansible.builtin.userManage usersuser: name=deploy state=present
ansible.builtin.debugPrint messagesdebug: msg="Hello"

Variables

---
- name: Using variables
  hosts: webservers
  vars:
    http_port: 8080
    app_name: myapp

  tasks:
    - name: Show variables
      ansible.builtin.debug:
        msg: "{{ app_name }} runs on port {{ http_port }}"

Loops

- name: Install multiple packages
  ansible.builtin.apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - git
    - curl
    - htop

Conditionals

- name: Install on Debian only
  ansible.builtin.apt:
    name: nginx
    state: present
  when: ansible_os_family == "Debian"

- name: Install on RHEL only
  ansible.builtin.yum:
    name: nginx
    state: present
  when: ansible_os_family == "RedHat"

Handlers

Handlers run only when notified by a task that made a change:

tasks:
  - name: Deploy nginx config
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: Restart nginx

handlers:
  - name: Restart nginx
    ansible.builtin.service:
      name: nginx
      state: restarted

Step 5: Organize with Roles

Roles structure your automation into reusable components:

roles/
  webserver/
    tasks/
      main.yml
    handlers/
      main.yml
    templates/
      nginx.conf.j2
    defaults/
      main.yml
    vars/
      main.yml

Use a role in a playbook:

---
- name: Configure web servers
  hosts: webservers
  become: true
  roles:
    - webserver

Create a role skeleton:

ansible-galaxy init roles/webserver

Step 6: Use Ansible Vault for Secrets

Never store passwords in plain text:

# Create encrypted file
ansible-vault create secrets.yml

# Edit encrypted file
ansible-vault edit secrets.yml

# Run playbook with vault
ansible-playbook playbook.yml --ask-vault-pass

Common Ad-Hoc Commands

# Ping all hosts
ansible all -m ping

# Check uptime
ansible all -m command -a "uptime"

# Copy a file
ansible webservers -m copy -a "src=file.txt dest=/tmp/"

# Install a package
ansible webservers -m apt -a "name=nginx state=present" --become

# Restart a service
ansible webservers -m service -a "name=nginx state=restarted" --become

# Gather facts
ansible web1 -m setup

What's Next?

  1. Practice — Use the Ansible Playground to experiment
  2. Follow Learning Paths — Structured courses at /learning-paths
  3. Browse 800+ Tutorials — Real-world examples at /articles
  4. Read the Books — Check out Luca Berton's Ansible books

This tutorial is part of AnsibleByExample — 800+ practical Ansible tutorials by Luca Berton.