How to Install Ansible on RHEL 9, CentOS Stream 9, Ubuntu 24.04 & Debian 12 – Complete 2025 Guide

Introduction to Ansible

What is Ansible?

📑 Table of Contents

Ansible is an open-source automation platform that enables configuration management, application deployment, infrastructure provisioning, and orchestration across multiple systems. With its agentless architecture and simple YAML-based playbooks, Ansible has become the industry standard for IT automation.

Unlike other configuration management tools, Ansible doesn’t require agents on managed nodes – it uses SSH for Linux/Unix systems and WinRM for Windows, making it lightweight and easy to deploy.

In this comprehensive guide, we’ll walk you through installing Ansible on modern Linux distributions including:

  • Red Hat Enterprise Linux (RHEL) 9
  • CentOS Stream 9 / AlmaLinux 9 / Rocky Linux 9
  • Ubuntu 24.04 LTS (Noble Numbat) and 22.04 LTS
  • Debian 12 (Bookworm) and Debian 11

We’ll cover official repository installation, pip installation, and complete environment setup with SSH key authentication.

Lab Environment Setup

Building the Test Environment

For this tutorial, we’ll set up a typical Ansible environment with one control node and multiple managed nodes. You can follow along with physical servers, virtual machines, or cloud instances.

Example Lab Setup:

ansiblecontrol  - 192.168.122.10 (RHEL 9)
node1           - 192.168.122.11 (RHEL 9)
node2           - 192.168.122.12 (Ubuntu 24.04)
node3           - 192.168.122.13 (Debian 12)

Note: Ansible is typically installed only on the control node, not on managed nodes.

Prerequisites

Before installing Ansible, ensure you have:

  • A Linux system for the control node (physical, VM, or cloud instance)
  • Root or sudo access on all nodes
  • Network connectivity between control node and managed nodes
  • Python 3.9 or later (pre-installed on most modern distributions)
  • SSH access to managed nodes

Verify Python Version

Check your Python version on the control node:

# For Python 3
python3 --version

# Expected output (example):
# Python 3.9.18

Installing Ansible on RHEL 9 / CentOS Stream 9

Method 1: Using RHEL Subscription Manager (RHEL 9 Only)

If you have an active Red Hat subscription, you can install Ansible from official Red Hat repositories:

# Register your system (if not already registered)
sudo subscription-manager register

# List available Ansible repositories
sudo subscription-manager repos | grep ansible

# Enable the Ansible repository
sudo subscription-manager repos --enable=ansible-automation-platform-2.4-for-rhel-9-x86_64-rpms

# Install Ansible
sudo dnf install ansible-core -y

# Verify installation
ansible --version

Method 2: Using EPEL Repository (RHEL 9, CentOS Stream, AlmaLinux, Rocky)

For CentOS Stream 9, AlmaLinux 9, Rocky Linux 9, or RHEL 9 without subscription, use EPEL:

# Install EPEL repository
sudo dnf install epel-release -y

# Install Ansible
sudo dnf install ansible -y

# Verify installation
ansible --version

Expected Output:

ansible [core 2.16.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ansible/.ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.18 (main, Jan 24 2024, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

Method 3: Using Python pip (All Distributions)

Install the latest Ansible version using pip:

# Install pip if not already installed
sudo dnf install python3-pip -y

# Install Ansible via pip
pip3 install --user ansible

# Add to PATH (add to ~/.bashrc for persistence)
export PATH=$PATH:~/.local/bin

# Verify installation
ansible --version

Installing Ansible on Ubuntu 24.04 / 22.04 LTS

The Ansible PPA provides the latest stable version:

# Update package index
sudo apt update

# Install software-properties-common (if not installed)
sudo apt install software-properties-common -y

# Add Ansible PPA repository
sudo add-apt-repository --yes --update ppa:ansible/ansible

# Install Ansible
sudo apt install ansible -y

# Verify installation
ansible --version

Method 2: Using Ubuntu’s Default Repository

Ubuntu 24.04 includes Ansible in its default repositories:

# Update package index
sudo apt update

# Install Ansible
sudo apt install ansible -y

# Verify installation
ansible --version

Note: The default repository version may be older than the PPA version.

Method 3: Using Python pip

# Install pip
sudo apt update
sudo apt install python3-pip -y

# Install Ansible
pip3 install --user ansible

# Add to PATH
export PATH=$PATH:~/.local/bin

# Verify installation
ansible --version

Installing Ansible on Debian 12 / Debian 11

Method 1: Using Debian’s Official Repository

# Update package index
sudo apt update

# Install Ansible
sudo apt install ansible -y

# Verify installation
ansible --version

Method 2: Using Python pip (Latest Version)

# Update and install pip
sudo apt update
sudo apt install python3-pip python3-venv -y

# Install Ansible
pip3 install --user ansible

# Add to PATH
export PATH=$PATH:~/.local/bin

# Make PATH permanent
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc
source ~/.bashrc

# Verify installation
ansible --version

Post-Installation Configuration

1. Create Ansible User (Best Practice)

It’s recommended to create a dedicated user for running Ansible automation:

On Control Node:

# Create ansible user
sudo useradd -m -s /bin/bash ansible
sudo passwd ansible

# Switch to ansible user
su - ansible

On All Managed Nodes:

# Create ansible user on each managed node
sudo useradd -m -s /bin/bash ansible
sudo passwd ansible

2. Configure Sudo Privileges

Grant passwordless sudo access to the ansible user on all nodes (control node and managed nodes):

# Edit sudoers file safely
sudo visudo

# Add this line at the end:
ansible    ALL=(ALL)    NOPASSWD: ALL

Or create a dedicated sudoers file:

# Create sudoers file for ansible user
echo "ansible ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/ansible
sudo chmod 440 /etc/sudoers.d/ansible

3. Configure Hostname Resolution

If you don’t have DNS configured, update /etc/hosts on all nodes:

sudo vi /etc/hosts

# Add these entries:
192.168.122.10  ansiblecontrol
192.168.122.11  node1
192.168.122.12  node2
192.168.122.13  node3

4. Set Up SSH Key-Based Authentication

On the Control Node (as ansible user):

# Generate SSH key pair
ssh-keygen -t ed25519 -C "ansible@ansiblecontrol"

# Press Enter for all prompts to accept defaults

Output:

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/ansible/.ssh/id_ed25519):
Created directory '/home/ansible/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ansible/.ssh/id_ed25519
Your public key has been saved in /home/ansible/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ansible@ansiblecontrol

Copy SSH Key to All Managed Nodes:

# Copy to node1
ssh-copy-id ansible@node1

# Copy to node2
ssh-copy-id ansible@node2

# Copy to node3
ssh-copy-id ansible@node3

Test Passwordless SSH:

# Test connection to each node
ssh ansible@node1 'hostname'
ssh ansible@node2 'hostname'
ssh ansible@node3 'hostname'

If successful, you should see the hostname of each node without being prompted for a password.

5. Create Ansible Inventory

Create an inventory file to define your managed nodes:

# Create inventory directory
mkdir -p ~/ansible
cd ~/ansible

# Create inventory file
vi inventory.ini

Basic Inventory Example:

[webservers]
node1 ansible_host=192.168.122.11
node2 ansible_host=192.168.122.12

[databases]
node3 ansible_host=192.168.122.13

[all:vars]
ansible_user=ansible
ansible_python_interpreter=/usr/bin/python3

Test Inventory:

# List all hosts
ansible all -i inventory.ini --list-hosts

# Expected output:
#   hosts (3):
#     node1
#     node2
#     node3

6. Create Ansible Configuration File

Create a custom Ansible configuration file for your project:

vi ~/ansible/ansible.cfg

Configuration Example:

[defaults]
inventory = ./inventory.ini
remote_user = ansible
host_key_checking = False
deprecation_warnings = False
interpreter_python = auto_silent

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

Verifying Ansible Installation

Test 1: Check Ansible Version

ansible --version

Test 2: Ping All Managed Nodes

cd ~/ansible
ansible all -m ping

Expected Output:

node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
node2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3.12"
    },
    "changed": false,
    "ping": "pong"
}
node3 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3.11"
    },
    "changed": false,
    "ping": "pong"
}

Test 3: Run Ad Hoc Command

# Check uptime on all nodes
ansible all -a "uptime"

# Check disk space
ansible all -a "df -h"

# Check OS version on RHEL-based systems
ansible webservers -a "cat /etc/redhat-release"

# Check OS version on Debian-based systems
ansible databases -a "cat /etc/os-release"

Test 4: Run a Simple Playbook

Create a test playbook:

vi ~/ansible/test-playbook.yml

Playbook Content:

---
- name: Test Ansible Configuration
  hosts: all
  become: yes
  tasks:
    - name: Ensure a test file exists
      file:
        path: /tmp/ansible-test.txt
        state: touch
        mode: '0644'

    - name: Gather and display OS information
      debug:
        msg: "This is {{ ansible_distribution }} {{ ansible_distribution_version }}"

    - name: Check connectivity
      ping:

Run the Playbook:

ansible-playbook test-playbook.yml

Expected Output:

PLAY [Test Ansible Configuration] *******************************************

TASK [Gathering Facts] ******************************************************
ok: [node1]
ok: [node2]
ok: [node3]

TASK [Ensure a test file exists] ********************************************
changed: [node1]
changed: [node2]
changed: [node3]

TASK [Gather and display OS information] ************************************
ok: [node1] => {
    "msg": "This is RedHat 9.3"
}
ok: [node2] => {
    "msg": "This is Ubuntu 24.04"
}
ok: [node3] => {
    "msg": "This is Debian 12"
}

TASK [Check connectivity] ***************************************************
ok: [node1]
ok: [node2]
ok: [node3]

PLAY RECAP ******************************************************************
node1                      : ok=4    changed=1    unreachable=0    failed=0
node2                      : ok=4    changed=1    unreachable=0    failed=0
node3                      : ok=4    changed=1    unreachable=0    failed=0

Common Installation Issues and Solutions

Issue 1: Python Not Found

Error:

The module failed to execute correctly, you probably need to set the interpreter.

Solution:

# Install Python 3 on managed nodes
# RHEL/CentOS:
sudo dnf install python3 -y

# Ubuntu/Debian:
sudo apt install python3 -y

# Or specify Python interpreter in inventory:
ansible_python_interpreter=/usr/bin/python3

Issue 2: SSH Connection Refused

Error:

fatal: [node1]: UNREACHABLE! => {"msg": "Failed to connect to the host via ssh"}

Solution:

# Ensure SSH service is running on managed nodes
sudo systemctl status sshd
sudo systemctl start sshd
sudo systemctl enable sshd

# Check firewall rules (RHEL/CentOS)
sudo firewall-cmd --list-services
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --reload

# Check firewall (Ubuntu/Debian)
sudo ufw status
sudo ufw allow ssh

Issue 3: Permission Denied (publickey)

Error:

Permission denied (publickey,password)

Solution:

# Verify SSH key was copied correctly
ssh-copy-id -f ansible@node1

# Check SSH key permissions on control node
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

# Check authorized_keys on managed node
ssh ansible@node1 'chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys'

Issue 4: Sudo Password Required

Error:

Missing sudo password

Solution:

# Add passwordless sudo for ansible user
echo "ansible ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/ansible

# Or run playbooks with --ask-become-pass
ansible-playbook playbook.yml --ask-become-pass

Issue 5: Module Not Found

Error:

ERROR! couldn't resolve module/action 'community.general.xxx'

Solution:

# Install Ansible collections
ansible-galaxy collection install community.general
ansible-galaxy collection install ansible.posix

Ansible Version Comparison

Distribution Installation Method Ansible Version Python Version
RHEL 9 RHEL Subscription 2.14+ (ansible-core) Python 3.9
RHEL 9 EPEL 2.14+ Python 3.9
CentOS Stream 9 EPEL 2.14+ Python 3.9
Ubuntu 24.04 PPA 2.16+ Python 3.12
Ubuntu 22.04 PPA 2.16+ Python 3.10
Debian 12 Official Repo 2.14+ Python 3.11
Any Distribution pip (latest) 2.16+ Python 3.9+

Best Practices for Ansible Installation

If installing via pip, use Python virtual environments:

# Create virtual environment
python3 -m venv ~/ansible-venv

# Activate virtual environment
source ~/ansible-venv/bin/activate

# Install Ansible
pip install ansible

# Deactivate when done
deactivate

2. Pin Ansible Versions in Production

# Install specific version
pip install ansible==2.16.3

# Create requirements.txt
echo "ansible==2.16.3" > requirements.txt
pip install -r requirements.txt

3. Install Common Collections

# Install essential collections
ansible-galaxy collection install ansible.posix
ansible-galaxy collection install community.general
ansible-galaxy collection install ansible.netcommon
ansible-galaxy collection install community.docker

4. Use Ansible Vault for Secrets

# Create encrypted file for passwords/secrets
ansible-vault create secrets.yml

# Edit encrypted file
ansible-vault edit secrets.yml

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

5. Keep Ansible Updated

# Update via dnf/apt
sudo dnf update ansible -y
sudo apt update && sudo apt upgrade ansible -y

# Update via pip
pip install --upgrade ansible

Next Steps with Ansible

Now that you have Ansible installed and configured, explore these topics:

1. Create Your First Playbook

Start with simple tasks like installing packages, managing services, or copying files:

---
- name: Install and start Apache
  hosts: webservers
  become: yes
  tasks:
    - name: Install Apache
      package:
        name: "{{ 'httpd' if ansible_os_family == 'RedHat' else 'apache2' }}"
        state: present

    - name: Start Apache service
      service:
        name: "{{ 'httpd' if ansible_os_family == 'RedHat' else 'apache2' }}"
        state: started
        enabled: yes

2. Organize Code with Roles

Create reusable Ansible roles for common tasks:

# Create role structure
ansible-galaxy init roles/webserver
ansible-galaxy init roles/database

3. Use Ansible Galaxy

Leverage community roles and collections:

# Search for roles
ansible-galaxy search nginx

# Install role from Galaxy
ansible-galaxy install geerlingguy.nginx

4. Integrate with CI/CD

Use Ansible in your automation pipelines with Jenkins, GitLab CI, or GitHub Actions.

5. Explore AWX/Ansible Tower

For enterprise features like web UI, RBAC, and job scheduling, explore AWX (open source) or Ansible Automation Platform.

Frequently Asked Questions

1. What’s the difference between ansible and ansible-core?

ansible-core is the minimal Ansible package containing the core engine and built-in modules. ansible is the full package that includes ansible-core plus community collections. For most use cases, install the full ansible package.

2. Can I install Ansible on Windows?

No, Ansible control nodes must run on Linux/Unix systems. However, Ansible can manage Windows nodes using WinRM. You can run Ansible on Windows using WSL (Windows Subsystem for Linux).

3. Do I need to install Ansible on managed nodes?

No! Ansible is agentless. You only install Ansible on the control node. Managed nodes only need Python and SSH access.

4. Which Python version does Ansible require?

Ansible 2.14+ requires Python 3.9 or later on the control node. Managed nodes can use Python 3.6+ (though 3.9+ is recommended).

5. Should I use EPEL or pip for installation?

For production systems, use package managers (dnf/apt) for easier updates and system integration. Use pip when you need the latest version or specific version pinning for development/testing.

6. How do I upgrade Ansible?

# Via package manager
sudo dnf update ansible -y    # RHEL/CentOS
sudo apt update && sudo apt upgrade ansible -y  # Ubuntu/Debian

# Via pip
pip install --upgrade ansible

7. Can I have multiple Ansible versions installed?

Yes, using Python virtual environments:

# Create separate environments for different versions
python3 -m venv ~/ansible-2.14
source ~/ansible-2.14/bin/activate
pip install ansible==2.14.0

python3 -m venv ~/ansible-2.16
source ~/ansible-2.16/bin/activate
pip install ansible==2.16.0

8. What if my managed nodes use different OS distributions?

No problem! Ansible works across different distributions. Use conditional logic in playbooks:

- name: Install package on different OS
  package:
    name: "{{ 'httpd' if ansible_os_family == 'RedHat' else 'apache2' }}"
    state: present

9. How do I uninstall Ansible?

# Via package manager
sudo dnf remove ansible -y        # RHEL/CentOS
sudo apt remove ansible -y        # Ubuntu/Debian

# Via pip
pip uninstall ansible

10. Where can I find more Ansible resources?

Conclusion

You’ve successfully installed Ansible on modern Linux distributions including RHEL 9, CentOS Stream 9, Ubuntu 24.04, and Debian 12. You’ve also configured SSH key-based authentication, created an inventory file, and verified your installation with test commands and playbooks.

Ansible’s agentless architecture and simple YAML syntax make it an excellent choice for automating infrastructure at any scale – from a handful of servers to thousands of nodes across multiple cloud providers.

Key Takeaways:

  • Ansible is only installed on the control node, not on managed nodes
  • Use package managers (dnf/apt) for production, pip for development
  • SSH key-based authentication is essential for automation
  • Create dedicated ansible user with passwordless sudo
  • Test your installation with ansible all -m ping
  • Start with simple ad hoc commands before writing complex playbooks

Start small with simple playbooks, gradually build complexity, and leverage the vast Ansible community resources available. Happy automating!

For more Ansible tutorials and automation guides, explore our Ansible category and Ansible Variables and Precedence Guide.

Was this article helpful?

R

About Ramesh Sundararamaiah

Red Hat Certified Architect

Expert in Linux system administration, DevOps automation, and cloud infrastructure. Specializing in Red Hat Enterprise Linux, CentOS, Ubuntu, Docker, Ansible, and enterprise IT solutions.