Guides / Configuration Management

How to Install & Set Up Ansible

Install Ansible — agentless automation for provisioning, configuration management, and app deployment — then build an inventory, write an idempotent playbook, and organize it into roles.

Updated 202610-step setupDownload Ansible →

Prerequisites

  • ✓A Linux/macOS control node with Python 3.9+ — this is the only machine that needs Ansible installed
  • ✓SSH access (key-based, ideally) to the machines you want to manage, plus a Python interpreter on each of them — no agent or daemon runs on the managed side

Why 'agentless' actually matters

Ansible doesn't run anything persistent on the machines it manages. Every run, the control node connects over plain SSH, copies over a small Python script for whatever module the task calls, executes it, and cleans up — there's no daemon to keep patched or a port to expose beyond SSH itself.

The other property worth understanding up front is idempotency: a well-written task describes a desired end state ('this package is installed', 'this file has this content'), not a command to run. Re-running the exact same playbook against a host that's already correct should report changed=0 across the board — that's what lets you safely run the same playbook nightly instead of only once.

Install with pip (recommended)

terminal
python3 -m pip install --user ansible

Install from your distribution

Ubuntu (PPA)
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
RHEL / CentOS Stream (EPEL)
sudo dnf install -y epel-release
sudo dnf install -y ansible-core
Fedora
sudo dnf install -y ansible-core
macOS (Homebrew)
brew install ansible
!

ansible-core is the engine; the full ansible metapackage (pip install ansible) additionally pulls in the large community collection of modules — install that instead of ansible-core if you need modules beyond the built-ins.

Install the bleeding-edge devel branch from source

For a feature or bugfix that hasn't shipped in a release yet, pip can install directly from the devel branch on GitHub — genuinely the same thing the release packages above build from, just unreleased.

terminal
python3 -m pip install --user git+https://github.com/ansible/ansible.git@devel
!

devel is a moving target and not meant for production control nodes — use a release install for anything you depend on.

Verify the installation

terminal
ansible --version

Build an inventory

The inventory is just the list of hosts Ansible can target, grouped however makes sense for you — by role, by environment, whatever. INI is the classic format; YAML reads better once you start attaching per-group variables.

inventory.ini
[web]
192.0.2.10
192.0.2.11

[db]
192.0.2.20

[web:vars]
http_port=8080
the same inventory in YAML
all:
  children:
    web:
      hosts:
        192.0.2.10: {}
        192.0.2.11: {}
      vars:
        http_port: 8080
    db:
      hosts:
        192.0.2.20: {}

Ad-hoc commands — Ansible without a playbook

For a one-off task, you don't need a whole playbook — the ansible CLI runs a single module against a group directly. Good for checking connectivity, gathering facts, or a quick fix across a fleet.

terminal
ansible -i inventory.ini web -m ping
ansible -i inventory.ini web -m apt -a "name=curl state=present" --become
ansible -i inventory.ini all -m setup -a "filter=ansible_distribution*"

Write your first playbook

A playbook is a YAML file of plays, each targeting a group of hosts and running an ordered list of tasks. Handlers are tasks that only fire when notified — the standard pattern for 'restart the service, but only if its config actually changed'.

site.yml
- name: Configure web servers
  hosts: web
  become: true
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present
        update_cache: true

    - name: Deploy site config
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: Reload nginx

    - name: Ensure nginx is running
      service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: Reload nginx
      service:
        name: nginx
        state: reloaded
dry-run, then apply
ansible-playbook -i inventory.ini site.yml --check --diff
ansible-playbook -i inventory.ini site.yml
!

--check simulates the run and --diff shows what would change, without touching anything — always worth running before the real thing on hosts you care about.

Organize larger projects with roles

Once a playbook grows past a handful of tasks, a role gives you a standard directory layout (tasks/, handlers/, templates/, defaults/, vars/) that Ansible auto-loads by convention — and it's reusable across playbooks and shareable via Ansible Galaxy.

scaffold a role and use it
ansible-galaxy init roles/webserver
site.yml, referencing the role instead of inline tasks
- name: Configure web servers
  hosts: web
  become: true
  roles:
    - webserver

Keep secrets out of Git with Ansible Vault

Passwords and API keys shouldn't sit in plaintext next to your playbooks. Vault encrypts a file (or just a single variable) with a password you supply at run time.

terminal
ansible-vault create group_vars/web/vault.yml
ansible-playbook -i inventory.ini site.yml --ask-vault-pass

Documentation & Knowledge Base

Official DocumentationAnsible Documentation →Knowledge Base & CommunityAnsible Community Forum →
Download Ansible— all versions & official links→

Related Guides

Puppet (OSS)Install guide →Salt (SaltStack)Install guide →Chef InfraInstall guide →

Need Ansible deployed and managed for you?

We're OpenStack Dev — we design, deploy, and operate production DevOps infrastructure.

Get in TouchAll Install Guides