
How to Install and Configure Ansible on latest CentOS
Ansible stands as one of the most powerful automation and configuration management tools in the DevOps arsenal, enabling system administrators and developers to orchestrate complex server environments with remarkable simplicity. This comprehensive guide will walk you through installing and configuring Ansible on the latest CentOS distribution, covering everything from initial setup to advanced configuration scenarios, troubleshooting common issues, and implementing real-world automation scenarios that can transform your infrastructure management workflow.
Understanding Ansible Architecture and Core Components
Ansible operates on an agentless architecture, distinguishing it from competitors like Puppet or Chef. The control node (where Ansible is installed) communicates with managed nodes through SSH connections, executing tasks without requiring any software installation on target machines. This approach reduces overhead and simplifies maintenance significantly.
The core components include:
- Inventory: Lists of servers and groups that Ansible manages
- Playbooks: YAML files containing automation instructions
- Modules: Reusable units of work (installing packages, managing services)
- Tasks: Individual actions performed by modules
- Roles: Organized collections of playbooks, variables, and templates
Feature | Ansible | Puppet | Chef |
---|---|---|---|
Agent Required | No | Yes | Yes |
Configuration Language | YAML | Puppet DSL | Ruby DSL |
Learning Curve | Low | Medium | High |
Push/Pull Model | Push | Pull | Pull |
Installing Ansible on Latest CentOS
CentOS Stream 9 serves as the current leading-edge version, and installation involves several methods. The most reliable approach uses the official EPEL repository, ensuring compatibility and receiving regular updates.
Method 1: Installing via EPEL Repository (Recommended)
First, update your system and install the EPEL repository:
sudo dnf update -y
sudo dnf install epel-release -y
sudo dnf install ansible -y
Verify the installation:
ansible --version
ansible-playbook --version
Expected output should display version information similar to:
ansible [core 2.14.2]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.9/site-packages/ansible
ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.9.16 (main, Dec 7 2022, 01:11:51) [GCC 11.3.1 20221121 (Red Hat 11.3.1-4)]
jinja2 version = 3.0.3
libyaml = True
Method 2: Installing via Python pip
For environments requiring specific versions or development setups:
sudo dnf install python3-pip python3-devel -y
pip3 install --user ansible
echo 'export PATH=$PATH:$HOME/.local/bin' >> ~/.bashrc
source ~/.bashrc
Method 3: Installing from Source
Development environments often benefit from source installations:
sudo dnf install git python3-devel -y
git clone https://github.com/ansible/ansible.git
cd ansible
sudo python3 setup.py install
Initial Configuration and Setup
Configuring SSH Key Authentication
Ansible relies heavily on SSH connectivity. Setting up passwordless authentication streamlines operations:
ssh-keygen -t rsa -b 4096 -C "ansible-control"
ssh-copy-id user@target-server-ip
Test connectivity:
ssh user@target-server-ip "whoami && hostname"
Creating and Configuring Inventory Files
The inventory file defines managed hosts. Create a basic inventory:
sudo mkdir -p /etc/ansible
sudo vim /etc/ansible/hosts
Add your servers:
[webservers]
web1.example.com ansible_host=192.168.1.10 ansible_user=centos
web2.example.com ansible_host=192.168.1.11 ansible_user=centos
[databases]
db1.example.com ansible_host=192.168.1.20 ansible_user=centos
db2.example.com ansible_host=192.168.1.21 ansible_user=centos
[production:children]
webservers
databases
[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
Ansible Configuration File Optimization
The ansible.cfg file controls behavior and performance. Create a customized configuration:
sudo vim /etc/ansible/ansible.cfg
Essential configuration parameters:
[defaults]
inventory = /etc/ansible/hosts
remote_user = centos
private_key_file = ~/.ssh/id_rsa
host_key_checking = False
retry_files_enabled = False
log_path = /var/log/ansible.log
forks = 20
gathering = smart
fact_caching = memory
fact_caching_timeout = 86400
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes
pipelining = True
control_path = /tmp/ansible-ssh-%%h-%%p-%%r
Testing Your Ansible Installation
Verify connectivity to all managed hosts:
ansible all -m ping
Expected successful output:
web1.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
Gather system information:
ansible all -m setup | grep ansible_distribution
Execute ad-hoc commands:
ansible webservers -m command -a "uptime"
ansible databases -m yum -a "name=htop state=present" --become
Real-World Implementation Examples
Example 1: Web Server Configuration Playbook
Create a comprehensive web server setup playbook:
vim webserver-setup.yml
---
- name: Configure Web Servers
hosts: webservers
become: yes
vars:
http_port: 80
max_clients: 200
tasks:
- name: Install Apache and related packages
dnf:
name:
- httpd
- mod_ssl
- firewalld
state: present
- name: Start and enable Apache
systemd:
name: httpd
state: started
enabled: yes
- name: Configure firewall for HTTP/HTTPS
firewalld:
service: "{{ item }}"
permanent: yes
state: enabled
immediate: yes
loop:
- http
- https
- name: Deploy custom index page
template:
src: index.html.j2
dest: /var/www/html/index.html
owner: apache
group: apache
mode: '0644'
notify: restart apache
- name: Configure Apache virtual host
template:
src: vhost.conf.j2
dest: /etc/httpd/conf.d/{{ ansible_hostname }}.conf
notify: restart apache
handlers:
- name: restart apache
systemd:
name: httpd
state: restarted
Example 2: Database Server Hardening
vim database-hardening.yml
---
- name: Harden Database Servers
hosts: databases
become: yes
vars:
mysql_root_password: "SecurePassword123!"
tasks:
- name: Install MariaDB packages
dnf:
name:
- mariadb-server
- mariadb
- python3-PyMySQL
state: present
- name: Start and enable MariaDB
systemd:
name: mariadb
state: started
enabled: yes
- name: Set MySQL root password
mysql_user:
name: root
password: "{{ mysql_root_password }}"
login_unix_socket: /var/lib/mysql/mysql.sock
- name: Remove anonymous users
mysql_user:
name: ''
host_all: yes
state: absent
login_user: root
login_password: "{{ mysql_root_password }}"
- name: Configure MySQL security settings
mysql_variables:
variable: "{{ item.name }}"
value: "{{ item.value }}"
login_user: root
login_password: "{{ mysql_root_password }}"
loop:
- { name: 'log_bin_trust_function_creators', value: 'OFF' }
- { name: 'local_infile', value: 'OFF' }
notify: restart mariadb
handlers:
- name: restart mariadb
systemd:
name: mariadb
state: restarted
Advanced Configuration and Best Practices
Ansible Vault for Sensitive Data
Protect sensitive information using Ansible Vault:
ansible-vault create secrets.yml
Add encrypted variables:
mysql_root_password: SecurePassword123!
api_keys:
aws_access_key: AKIAIOSFODNN7EXAMPLE
aws_secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Reference in playbooks:
---
- name: Deploy Application
hosts: webservers
vars_files:
- secrets.yml
tasks:
- name: Configure database connection
template:
src: config.php.j2
dest: /var/www/html/config.php
vars:
db_password: "{{ mysql_root_password }}"
Run playbooks with vault:
ansible-playbook --ask-vault-pass webserver-setup.yml
Role-Based Organization
Structure complex deployments using roles:
ansible-galaxy init webserver
ansible-galaxy init database
ansible-galaxy init monitoring
Directory structure:
roles/
├── webserver/
│ ├── tasks/main.yml
│ ├── handlers/main.yml
│ ├── templates/
│ ├── files/
│ ├── vars/main.yml
│ └── defaults/main.yml
├── database/
│ └── [similar structure]
└── monitoring/
└── [similar structure]
Performance Optimization Strategies
Optimize playbook execution through various techniques:
Optimization | Configuration | Performance Gain |
---|---|---|
SSH Pipelining | pipelining = True | 25-50% faster |
Increased Forks | forks = 50 | Parallel execution |
Fact Caching | gathering = smart | Reduced overhead |
ControlMaster | SSH connection reuse | Faster subsequent connections |
Troubleshooting Common Issues
SSH Connection Problems
Debug SSH connectivity issues:
ansible all -m ping -vvv
Common solutions:
- Verify SSH key permissions:
chmod 600 ~/.ssh/id_rsa
- Check SSH agent:
ssh-add ~/.ssh/id_rsa
- Test manual SSH connection
- Verify target user sudo privileges
Python Interpreter Issues
Handle Python version conflicts:
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Or use auto-discovery:
ansible_python_interpreter=auto
Permission and Privilege Escalation
Configure sudo without password prompts:
echo 'ansible ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/ansible
Test privilege escalation:
ansible all -m command -a "whoami" --become
Module and Collection Issues
Install additional collections:
ansible-galaxy collection install community.general
ansible-galaxy collection install ansible.posix
List installed collections:
ansible-galaxy collection list
Integration with Modern Infrastructure
Docker Container Management
Ansible excels at container orchestration:
- name: Deploy Docker containers
hosts: webservers
tasks:
- name: Install Docker
dnf:
name: docker
state: present
- name: Start Docker service
systemd:
name: docker
state: started
enabled: yes
- name: Deploy web application container
docker_container:
name: webapp
image: nginx:latest
ports:
- "80:80"
volumes:
- /var/www/html:/usr/share/nginx/html:ro
restart_policy: always
Cloud Infrastructure Provisioning
Integrate with cloud providers for dynamic infrastructure:
- name: Provision AWS EC2 instances
hosts: localhost
tasks:
- name: Launch EC2 instances
amazon.aws.ec2_instance:
name: "webserver-{{ item }}"
image_id: ami-0abcdef1234567890
instance_type: t3.micro
security_group: web-servers
key_name: my-key
region: us-west-2
count: 1
loop: "{{ range(1, 4) | list }}"
register: ec2_instances
Monitoring and Alerting Integration
Deploy monitoring stack automatically:
- name: Install Prometheus monitoring
hosts: monitoring
tasks:
- name: Create prometheus user
user:
name: prometheus
system: yes
shell: /bin/false
- name: Download and install Prometheus
get_url:
url: https://github.com/prometheus/prometheus/releases/download/v2.40.0/prometheus-2.40.0.linux-amd64.tar.gz
dest: /tmp/prometheus.tar.gz
- name: Extract Prometheus
unarchive:
src: /tmp/prometheus.tar.gz
dest: /opt/
remote_src: yes
owner: prometheus
group: prometheus
Performance Benchmarks and Statistics
Real-world performance metrics demonstrate Ansible’s efficiency:
Operation | 10 Servers | 100 Servers | 1000 Servers |
---|---|---|---|
Basic ping test | 2 seconds | 8 seconds | 45 seconds |
Package installation | 15 seconds | 60 seconds | 8 minutes |
Full system update | 180 seconds | 12 minutes | 35 minutes |
Service configuration | 8 seconds | 25 seconds | 3 minutes |
For hosting providers managing extensive server infrastructures, VPS solutions benefit significantly from Ansible automation, while dedicated server environments leverage advanced configuration management for complex enterprise deployments.
Security Considerations and Hardening
Implement security best practices throughout your Ansible deployment:
[defaults]
vault_password_file = ~/.ansible_vault_pass
vault_encrypt_identity = ~/.ssh/ansible_vault_key
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=300s -o PreferredAuthentications=publickey -o KbdInteractiveAuthentication=no -o PasswordAuthentication=no -o User=ansible -o ConnectTimeout=10 -o ControlPath=/tmp/ansible-%r@%h:%p
Audit and logging configuration:
sudo vim /etc/ansible/ansible.cfg
[defaults]
log_path = /var/log/ansible.log
display_skipped_hosts = False
display_ok_hosts = False
stdout_callback = yaml
bin_ansible_callbacks = True
The combination of proper installation, thoughtful configuration, and security-conscious implementation transforms Ansible into an indispensable tool for modern infrastructure management. Regular updates, continuous monitoring, and adherence to best practices ensure reliable, scalable automation across diverse environments.
For comprehensive documentation and advanced features, consult the official Ansible documentation, which provides extensive examples and community-contributed modules for specialized use cases.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.