Skip to content
DevOps devops iac 5 min read

What is Ansible?

Ansible is an open-source automation tool that configures servers, installs software, and deploys applications for you — instead of you typing the same commands by hand on every machine. You write down what you want a server to look like in a simple text file, and Ansible logs in over SSH (Secure Shell, the standard encrypted way to access a remote Linux machine) and makes it happen. It is one of the most popular tools in DevOps because it is easy to learn, needs nothing special installed on the servers you manage, and uses plain YAML files that read almost like English.

The problem Ansible solves

Imagine you have one Ubuntu server. You SSH in, run apt update, install Nginx, edit a config file, open a firewall port, and start the service. That is fine for one server.

Now imagine you have ten servers — or you need to rebuild that one server next month and can’t remember every command you ran. Doing it by hand is slow, and humans forget steps. This leads to configuration drift, where servers that should be identical slowly become different over time, causing bugs that are painful to track down.

Ansible fixes this by letting you describe the desired state of a server once, in a file you can save in Git, review, and re-run anytime. The file becomes the single source of truth for how your servers are built.

How Ansible works — agentless and push-based

Two ideas make Ansible stand out:

Agentless. An “agent” is a background program that some tools require you to install on every server you want to manage. Ansible needs no agent. It only needs two things that almost every Linux server already has: SSH access and Python (a programming language Ansible uses to run its tasks). You install Ansible on one machine — your laptop or a small “control node” server — and it manages everything else from there.

Push-based. Ansible pushes changes out from the control node to the target servers when you run it. You stay in control of exactly when things happen. (Some other tools are “pull-based,” where each server periodically asks a central server for instructions — more on that below.)

Here is the basic flow:

Control node (your laptop)
        |
        |  SSH connection
        v
  Managed servers (web1, web2, db1...)

A typical run looks like this:

ansible-playbook -i inventory.ini site.yml

Output:

PLAY [Configure web servers] ***************************************************

TASK [Install Nginx] ***********************************************************
changed: [web1]
ok: [web2]

PLAY RECAP *********************************************************************
web1 : ok=2  changed=1  unreachable=0  failed=0
web2 : ok=2  changed=0  unreachable=0  failed=0

Idempotency — the most important idea

Idempotency means you can run the same Ansible playbook (the file with your instructions) over and over, and the result is always the same. If Nginx is already installed, Ansible leaves it alone and reports ok. If it is missing, Ansible installs it and reports changed. It never blindly re-installs or duplicates work.

Notice the output above: web1 shows changed=1 (it installed Nginx), but web2 shows changed=0 (Nginx was already there, so nothing happened). This is what makes Ansible safe to re-run — unlike a raw shell script, which might error out or do damage if you run it twice.

Idempotency is not automatic for every task. Built-in Ansible modules (like apt or service) are idempotent by design. But if you use the shell or command module to run raw commands, you are responsible for making them safe to re-run. Prefer the proper module whenever one exists.

Playbooks — your automation in YAML

A playbook is the file where you list the tasks you want Ansible to perform. It is written in YAML (a simple, indentation-based text format — “YAML Ain’t Markup Language”). Here is a small but real playbook that installs and starts Nginx on Ubuntu:

---
- name: Configure web servers
  hosts: webservers
  become: true            # run tasks with sudo

  tasks:
    - name: Install Nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true

    - name: Make sure Nginx is running and enabled
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

Each - name: is a human-readable description. become: true tells Ansible to use sudo (run as administrator). Each task calls a module — a small, reusable unit of work like apt (manage Ubuntu packages) or service (manage systemd services). You almost never write raw shell commands.

Why Ansible is beginner-friendly

  • Nothing to install on servers. If you can SSH into a box, you can manage it. No agents, no extra ports, no central database.
  • Readable files. YAML playbooks are easy to read even if you’ve never seen Ansible before.
  • Safe to re-run. Idempotency means experimenting won’t break things.
  • Push when you want. You decide exactly when changes go out, which is reassuring while learning.
  • Huge community. Thousands of ready-made roles exist on Ansible Galaxy (a public library of shareable automation).

Ansible vs other approaches — when to use which

ToolModelNeeds agent?Best for
AnsiblePush, over SSHNoConfiguring existing servers, app deploys, ad-hoc tasks
Puppet / ChefPull (server checks in)YesVery large fleets needing constant enforcement
TerraformDeclarative provisioningNoCreating cloud infrastructure (VMs, networks, load balancers)
Bash scriptsImperativeNoTiny one-off jobs on a single machine

When to use Ansible: configuring and maintaining Linux servers, installing and updating software, rolling out app releases, and running occasional fixes across many machines at once.

When NOT to use Ansible: to create the cloud resources themselves (the virtual machines, networks, and disks). That is provisioning, and Terraform is the better fit. A common pattern is Terraform to build the servers, Ansible to configure them — see the linked pages below.

Best practices

  • Keep playbooks, inventories, and roles in Git so every change is reviewed and reversible.
  • Prefer real modules (apt, service, copy) over the shell/command modules so your tasks stay idempotent.
  • Run with --check (a “dry run” that shows what would change) before applying to production.
  • Store secrets like passwords with Ansible Vault, never in plain text in your playbooks.
  • Organise reusable logic into roles instead of one giant playbook as your setup grows.
  • Always give every task a clear name: so the output is readable and easy to debug.
  • Test changes on a staging server first; never run a brand-new playbook against all servers at once.
Last updated June 15, 2026
Was this helpful?