Installation & Setup
Installation Methods
Using pip (Recommended)
# Install Ansible
pip install ansible
# Upgrade Ansible
pip install --upgrade ansible
# Install specific version
pip install ansible==6.0.0
# Install with additional collections
pip install ansible[azure,aws,gcp]
Using Package Managers
Ubuntu/Debian
# Update package index
sudo apt update
# Install software-properties-common
sudo apt install software-properties-common
# Add Ansible PPA
sudo add-apt-repository --yes --update ppa:ansible/ansible
# Install Ansible
sudo apt install ansible
CentOS/RHEL/Fedora
# CentOS/RHEL 8
sudo dnf install epel-release
sudo dnf install ansible
# CentOS/RHEL 7
sudo yum install epel-release
sudo yum install ansible
# Fedora
sudo dnf install ansible
macOS
# Using Homebrew
brew install ansible
# Using MacPorts
sudo port install py39-ansible
Using Docker
# Pull Ansible image
docker pull ansible/ansible
# Run Ansible in container
docker run -it --rm -v $(pwd):/ansible ansible/ansible
# Create alias for easier use
alias ansible-docker='docker run -it --rm -v $(pwd):/ansible ansible/ansible'
Initial Configuration
Configuration File Locations
# System-wide configuration
/etc/ansible/ansible.cfg
# User-specific configuration
~/.ansible.cfg
# Project-specific configuration
./ansible.cfg
# Check current configuration
ansible-config view
ansible-config dump
Basic ansible.cfg
[defaults]
# Inventory file location
inventory = ./inventory
# Default user for SSH connections
remote_user = ansible
# SSH key file
private_key_file = ~/.ssh/id_rsa
# Disable SSH key checking
host_key_checking = False
# Default module path
library = /usr/share/ansible
# Roles path
roles_path = ./roles
# Retry files
retry_files_enabled = False
# Gathering facts
gathering = smart
fact_caching = memory
# Logging
log_path = ./ansible.log
# Output format
stdout_callback = yaml
bin_ansible_callbacks = True
[ssh_connection]
# SSH timeout
timeout = 30
# SSH retries
retries = 3
# Pipelining (faster execution)
pipelining = True
# Control persist
control_path = ~/.ansible/cp/ansible-ssh-%%h-%%p-%%r
Environment Variables
# Configuration file
export ANSIBLE_CONFIG=./ansible.cfg
# Inventory file
export ANSIBLE_INVENTORY=./inventory
# Roles path
export ANSIBLE_ROLES_PATH=./roles
# Library path
export ANSIBLE_LIBRARY=./library
# SSH args
export ANSIBLE_SSH_ARGS='-o ControlMaster=auto -o ControlPersist=60s'
# Disable host key checking
export ANSIBLE_HOST_KEY_CHECKING=False
# Remote user
export ANSIBLE_REMOTE_USER=ansible
# Become user
export ANSIBLE_BECOME_USER=root
# Logging
export ANSIBLE_LOG_PATH=./ansible.log
SSH Configuration
SSH Key Setup
# Generate SSH key
ssh-keygen -t rsa -b 4096 -C "ansible@example.com"
# Copy public key to target hosts
ssh-copy-id -i ~/.ssh/id_rsa.pub user@target-host
# Add key to SSH agent
ssh-add ~/.ssh/id_rsa
# Test SSH connection
ssh user@target-host
SSH Config File
# ~/.ssh/config
Host ansible-host-*
User ansible
IdentityFile ~/.ssh/ansible_key
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
ControlMaster auto
ControlPath ~/.ssh/ansible-%r@%h:%p
ControlPersist 60s
Host production-*
User root
IdentityFile ~/.ssh/production_key
Port 2222
Host staging-*
User deploy
IdentityFile ~/.ssh/staging_key
ProxyJump bastion-host
SSH with Bastion/Jump Host
# SSH config for bastion
Host bastion
HostName bastion.example.com
User bastion-user
IdentityFile ~/.ssh/bastion_key
Host production-server
HostName 10.0.1.100
User ansible
IdentityFile ~/.ssh/production_key
ProxyJump bastion
User Management
Create Ansible User
# Create ansible user on target hosts
sudo useradd -m -s /bin/bash ansible
# Add to sudo group
sudo usermod -aG sudo ansible
# Set up passwordless sudo
echo "ansible ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/ansible
# Set up SSH key
sudo -u ansible mkdir -p /home/ansible/.ssh
sudo -u ansible touch /home/ansible/.ssh/authorized_keys
sudo -u ansible chmod 700 /home/ansible/.ssh
sudo -u ansible chmod 600 /home/ansible/.ssh/authorized_keys
# Add public key
echo "ssh-rsa AAAAB3NzaC1yc2E... ansible@controller" | sudo -u ansible tee -a /home/ansible/.ssh/authorized_keys
Ansible User Playbook
---
- name: Setup Ansible user
hosts: all
become: yes
vars:
ansible_user: ansible
ansible_ssh_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
tasks:
- name: Create ansible user
user:
name: '{{ ansible_user }}'
group: '{{ ansible_user }}'
createhome: yes
shell: /bin/bash
state: present
- name: Add ansible user to sudo group
user:
name: '{{ ansible_user }}'
groups: sudo
append: yes
- name: Set up passwordless sudo
lineinfile:
path: /etc/sudoers.d/ansible
line: '{{ ansible_user }} ALL=(ALL) NOPASSWD:ALL'
create: yes
validate: 'visudo -cf %s'
- name: Create .ssh directory
file:
path: '/home/{{ ansible_user }}/.ssh'
state: directory
owner: '{{ ansible_user }}'
group: '{{ ansible_user }}'
mode: '0700'
- name: Add SSH key
authorized_key:
user: '{{ ansible_user }}'
key: '{{ ansible_ssh_key }}'
state: present
Testing Installation
Basic Tests
# Check Ansible version
ansible --version
# Test local connection
ansible localhost -m ping
# Test inventory
ansible-inventory --list
# Test configuration
ansible-config dump --only-changed
Connection Tests
# Test all hosts
ansible all -m ping
# Test specific host
ansible webservers -m ping -i inventory
# Test with different user
ansible all -m ping -u ansible
# Test with become
ansible all -m ping -b
# Test with custom key
ansible all -m ping --private-key ~/.ssh/custom_key
Directory Structure
Project Structure
ansible-project/
├── ansible.cfg
├── inventory/
│ ├── production
│ ├── staging
│ └── group_vars/
│ ├── all.yml
│ ├── webservers.yml
│ └── databases.yml
├── playbooks/
│ ├── site.yml
│ ├── deploy.yml
│ └── maintenance.yml
├── roles/
│ ├── common/
│ ├── webserver/
│ └── database/
├── files/
├── templates/
├── vars/
└── vault/
Best Practices Structure
project/
├── ansible.cfg
├── requirements.yml
├── inventories/
│ ├── production/
│ │ ├── hosts
│ │ └── group_vars/
│ └── staging/
│ ├── hosts
│ └── group_vars/
├── playbooks/
│ ├── site.yml
│ ├── common.yml
│ └── roles/
│ ├── requirements.yml
│ └── internal/
├── collections/
└── logs/
Troubleshooting
Common Issues
# SSH connection issues
ansible all -m ping -vvv
# Permission denied
ansible all -m ping -u root --ask-pass
# Host key verification failed
export ANSIBLE_HOST_KEY_CHECKING=False
# Module not found
ansible-galaxy collection install community.general
# Python interpreter issues
ansible all -m ping -e ansible_python_interpreter=/usr/bin/python3
Debug Commands
# Verbose output
ansible-playbook playbook.yml -v
ansible-playbook playbook.yml -vv
ansible-playbook playbook.yml -vvv
# Dry run
ansible-playbook playbook.yml --check
# Show differences
ansible-playbook playbook.yml --check --diff
# Step through playbook
ansible-playbook playbook.yml --step
# Start from specific task
ansible-playbook playbook.yml --start-at-task="Task name"
Log Configuration
# ansible.cfg
[defaults]
log_path = /var/log/ansible.log
display_skipped_hosts = False
display_ok_hosts = False
# Custom callback plugins
stdout_callback = yaml
callback_whitelist = profile_tasks, timer
Security Considerations
SSH Security
# Disable SSH password authentication
# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
# Use SSH agent forwarding carefully
ForwardAgent no
# Restrict SSH access
AllowUsers ansible
File Permissions
# Secure private keys
chmod 600 ~/.ssh/id_rsa
# Secure ansible.cfg
chmod 600 ansible.cfg
# Secure inventory files
chmod 600 inventory/*
# Secure vault files
chmod 600 vault/*
Network Security
# Use jump hosts for production
# ansible.cfg
[ssh_connection]
ssh_args = -o ProxyJump=bastion-host
# Use VPN for remote access
# Custom SSH config for VPN
Host vpn-*
ProxyCommand nc -X connect -x vpn-proxy:1080 %h %p
Performance Optimization
Parallelism
# ansible.cfg
[defaults]
forks = 20
host_key_checking = False
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 3600
[ssh_connection]
pipelining = True
control_path = ~/.ansible/cp/ansible-ssh-%%h-%%p-%%r
Fact Caching
# Redis fact caching
[defaults]
fact_caching = redis
fact_caching_connection = localhost:6379:0
fact_caching_timeout = 3600
# JSON file caching
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 3600
Connection Optimization
# Use persistent connections
[ssh_connection]
pipelining = True
control_path = ~/.ansible/cp/ansible-ssh-%%h-%%p-%%r
control_path_dir = ~/.ansible/cp
# SSH multiplexing
ssh_args = -o ControlMaster=auto -o ControlPersist=60s