Ansible is an open source automation tool for configuration management, application deployment and agentless orchestration.
Installation
Platform Command Ubuntu/Debian sudo apt update && sudo apt install ansibleCentOS/RHEL sudo yum install ansiblePython pip pip3 install ansiblemacOS (Homebrew) brew install ansible
Recommended project structure
ansible-project/
├── inventory/ # Inventories
│ ├── production/
│ │ ├── hosts.ini
│ │ └── group_vars/
│ └── staging/
│ └── hosts.ini
├── roles/ # Reusable roles
│ ├── common/
│ ├── nginx/
│ └── mysql/
├── playbooks/ # Main playbooks
│ ├── site.yml
│ └── webservers.yml
├── group_vars/ # Variables per group
├── host_vars/ # Variables per host
└── ansible.cfg # Configuration
ansible.cfg file
[defaults]
inventory = inventory/ # Default inventory folder
remote_user = ansible # Default SSH user
host_key_checking = False # No SSH key verification (dev)
retry_files_enabled = False # No .retry files
gathering = smart # Smart facts gathering
fact_caching = memory # Cache facts in memory
[ssh_connection]
ssh_args = -o ControlMaster= auto -o ControlPersist= 60s # Persistent SSH connections
pipelining = True # SSH optimization
Inventory management
Action Command Create inventory echo "[servers]" > inventory/hosts.iniGlobal ping test ansible all -m pingGroup ping test ansible webservers -m pingAd-hoc command ansible all -a "uptime"System info ansible all -m setupOther inventory ansible all -i staging/hosts.ini -m ping
Inventory file example
[webservers]
web1 ansible_host= 192.168.1.50 ansible_user= admin
web2 ansible_host= 192.168.1.51 ansible_user= admin
[databases]
db1 ansible_host= 192.168.1.20 ansible_user= root
[all:vars]
ansible_python_interpreter= /usr/bin/python3
ansible_ssh_private_key_file= ~/.ssh/id_rsa
Useful inventory variables
# SSH connection
ansible_host= 192.168.1.50 # Server IP
ansible_user= admin # SSH user
ansible_port= 2222 # SSH port (default: 22)
ansible_ssh_private_key_file= ~/.ssh/key # Private key
# Python
ansible_python_interpreter= /usr/bin/python3
# Sudo
ansible_become= yes # Use sudo
ansible_become_user= root # Sudo user
Playbook execution
Action Command Run playbook ansible-playbook playbook.ymlTest mode (dry-run) ansible-playbook playbook.yml --checkVerbose mode ansible-playbook playbook.yml -vvvLimit to hosts ansible-playbook playbook.yml --limit webserversList tasks ansible-playbook playbook.yml --list-tasksDirect host ansible-playbook -i "192.168.1.50," playbook.yml
Basic playbook structure
---
- name : Web servers configuration
hosts : webservers
become : yes
vars :
nginx_port : 80
tasks :
- name : Install nginx
apt :
name : nginx
state : present
update_cache : yes
- name : Start nginx
service :
name : nginx
state : started
enabled : yes
handlers :
- name : restart nginx
service :
name : nginx
state : restarted
Role management
Ansible Galaxy is a community hub for shared roles (optional)
Action Command Create role structure ansible-galaxy init nginxCreate manually mkdir -p roles/nginx/{tasks,handlers,templates,files,vars,defaults}Install community role ansible-galaxy install geerlingguy.nginxList installed roles ansible-galaxy listRemove a role ansible-galaxy remove geerlingguy.nginxSearch for roles ansible-galaxy search nginx
requirements.yml file
The requirements.yml file allows you to list and automatically install multiple roles or collections with a single command.
# requirements.yml - Dependencies declaration
---
roles :
# From Galaxy (user.role)
- name : geerlingguy.nginx
version : " 3.1.4 "
- name : geerlingguy.docker
version : " 7.0.2 "
# From a Git repo
- name : custom-role
src : https://github.com/user/ansible-custom-role.git
version : main
collections :
# Collections from Galaxy
- name : community.general
version : " 8.0.0 "
- name : ansible.posix
Install from requirements.yml:
Action Command Install roles ansible-galaxy install -r requirements.ymlInstall collections ansible-galaxy collection install -r requirements.ymlForce reinstall ansible-galaxy install -r requirements.yml --force
Role structure
roles/nginx/
├── tasks/main.yml # Main tasks
├── handlers/main.yml # Triggered actions (restart services)
├── templates/ # Jinja2 files (.j2)
├── files/ # Static files to copy
├── vars/main.yml # Role variables
├── defaults/main.yml # Default variables
└── meta/main.yml # Metadata (dependencies, etc.)
Using roles in a playbook
---
- name : Web servers deployment
hosts : webservers
become : yes
roles :
- common # Basic configuration
- nginx # Nginx installation and config
- firewall # Firewall configuration
# Or with parameters
- name : Config with variables
hosts : webservers
roles :
- role : nginx
vars :
nginx_port : 8080
nginx_user : www-data
Essential modules
Package management
# APT (Ubuntu/Debian)
- name : Install nginx
apt :
name : nginx
state : present
update_cache : yes
# YUM/DNF (CentOS/RHEL/Fedora)
- name : Install httpd
yum :
name : httpd
state : present
# Universal package
- name : Install git
package :
name : git
state : present
File management
# Copy file
- name : Copy configuration
copy :
src : files/nginx.conf
dest : /etc/nginx/nginx.conf
owner : root
group : root
mode : ' 0644 '
backup : yes
# Jinja2 template
- name : Generate dynamic config
template :
src : templates/config.j2
dest : /etc/app/config.conf
# Create folder
- name : Create directory
file :
path : /opt/myapp
state : directory
mode : ' 0755 '
Service management
# Control service
- name : Start and enable nginx
service :
name : nginx
state : started
enabled : yes
# Systemd service
- name : Reload systemd
systemd :
name : myapp
state : reloaded
daemon_reload : yes
Ansible Vault
Action Command Create encrypted file ansible-vault create secrets.ymlEdit file ansible-vault edit secrets.ymlView content ansible-vault view secrets.ymlChange password ansible-vault rekey secrets.ymlEncrypt existing file ansible-vault encrypt vars.ymlDecrypt file ansible-vault decrypt vars.ymlRun with vault ansible-playbook site.yml --ask-vault-pass
Best practices
Practice Description Idempotence Tasks always produce the same result Naming Clearly name all tasks Testing Use --check before deployment Roles Organize into reusable roles Secrets Encrypt with ansible-vault Tags Use tags for partial executions