Automate system administration and deployment tasks across multiple servers.
Installation
Linux/Ubuntu
# Package manager installation
sudo apt update
sudo apt install ansible
# Or with pip
pip install ansible
# Verify installation
ansible --version
macOS
# Homebrew installation
brew install ansible
# Or with pip
pip install ansible
Windows (WSL/Git Bash)
# Via pip
pip install ansible
# Or WSL with Ubuntu
# Follow Linux installation above
Basic Commands
| Command | Description |
|---|
ansible --version | Display Ansible version |
ansible --help | Show help information |
ansible-playbook playbook.yml | Run a playbook |
ansible-inventory -i hosts list | List inventory |
ansible all -m ping | Test connectivity to all hosts |
ansible webservers -a 'uptime' | Run ad-hoc command |
ansible-galaxy install role-name | Install role from Galaxy |
ansible-vault create secrets.yml | Create encrypted file |
Inventory Management
| Command | Description |
|---|
ansible-inventory -i hosts --list | Display inventory in JSON |
ansible-inventory -i hosts --graph | Display inventory as tree |
ansible-inventory -i hosts --host hostname | Show host variables |
ansible all -i hosts --list-hosts | List all hosts in inventory |
ansible webservers -i hosts --list-hosts | List hosts in group |
Ad-Hoc Commands
# Run command on all hosts
ansible all -i hosts -m shell -a 'date'
# Run with sudo
ansible all -i hosts -m shell -a 'apt update' --become
# Run on specific group
ansible webservers -i hosts -a 'systemctl restart nginx'
# Run with output
ansible all -i hosts -m command -a 'ls -la /home' -v
# Copy file to hosts
ansible all -i hosts -m copy -a 'src=/tmp/file.txt dest=/tmp/'
# Install package
ansible all -i hosts -m apt -a 'name=curl state=present' --become
# Manage services
ansible all -i hosts -m service -a 'name=nginx state=started' --become
# Run with variables
ansible all -i hosts -m debug -a 'msg={{ ansible_os_family }}'
Playbook Structure
---
- name: Configure web servers
hosts: webservers
become: yes
vars:
http_port: 80
max_clients: 200
tasks:
- name: Install Apache
apt:
name: apache2
state: present
- name: Start Apache
service:
name: apache2
state: started
enabled: yes
- name: Create config file
template:
src: apache.conf.j2
dest: /etc/apache2/apache2.conf
notify: restart apache
handlers:
- name: restart apache
service:
name: apache2
state: restarted
Commonly Used Modules
| Module | Purpose |
|---|
apt/yum/dnf | Package management |
service/systemd | Service management |
copy | Copy files to hosts |
template | Render Jinja2 templates |
shell/command | Execute commands |
user/group | Manage users/groups |
file | Manage files/directories |
git | Clone/update repositories |
lineinfile | Edit files line-by-line |
debug | Print debug messages |
assert | Test conditions |
Roles
Create a role
ansible-galaxy init my_role
Role structure
my_role/
├── tasks/main.yml
├── handlers/main.yml
├── templates/
├── files/
├── vars/main.yml
├── defaults/main.yml
└── meta/main.yml
Use a role in playbook
---
- hosts: all
roles:
- common
- webserver
- { role: monitoring, version: '2.0' }
Variables and Facts
# List all facts for a host
ansible hostname -m setup
# Filter specific facts
ansible hostname -m setup -a 'filter=ansible_os_family'
# Use variables in playbook
ansible-playbook site.yml -e "deploy_user=john"
# Use variable file
ansible-playbook site.yml -e "@vars.yml"
Handlers
handlers:
- name: restart web server
service:
name: nginx
state: restarted
listen: "web service changed"
tasks:
- name: Update config
copy:
src: nginx.conf
dest: /etc/nginx/
notify: "web service changed"
Conditionals
tasks:
- name: Install on Debian
apt:
name: curl
when: ansible_os_family == "Debian"
- name: Install on RedHat
yum:
name: curl
when: ansible_os_family == "RedHat"
- name: Run if registered variable set
debug:
msg: "Service running"
when: service_status.rc == 0
Loops
tasks:
- name: Install packages
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- curl
- git
- name: Create users
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
loop:
- { name: 'john', groups: 'sudo' }
- { name: 'jane', groups: 'www-data' }
Ansible Galaxy
# Search for roles
ansible-galaxy search nginx
# Install role
ansible-galaxy install geerlingguy.nginx
# Install from requirements
ansible-galaxy install -r requirements.yml
# List installed roles
ansible-galaxy list
# Remove role
ansible-galaxy remove geerlingguy.nginx
Configuration
ansible.cfg
[defaults]
inventory = ./hosts
host_key_checking = False
private_key_file = ~/.ssh/id_rsa
remote_user = ansible
Vault - Encrypt Sensitive Data
# Create encrypted file
ansible-vault create secrets.yml
# Edit encrypted file
ansible-vault edit secrets.yml
# Encrypt existing file
ansible-vault encrypt vars.yml
# Decrypt file
ansible-vault decrypt secrets.yml
# View encrypted file
ansible-vault view secrets.yml
# Run playbook with vault
ansible-playbook site.yml --ask-vault-pass
# Use vault password file
ansible-playbook site.yml --vault-password-file=~/.vault_pass
Debugging
# Verbose output (more -v flags = more detail)
ansible-playbook site.yml -v
ansible-playbook site.yml -vv
ansible-playbook site.yml -vvv
# Debug module
- debug:
msg: "Variable value: {{ my_var }}"
verbosity: 1
# Register and debug output
- shell: whoami
register: whoami_result
- debug:
var: whoami_result
Common Patterns
Web Server Setup
---
- name: Setup web server
hosts: webservers
become: yes
tasks:
- name: Update package cache
apt:
update_cache: yes
- name: Install Nginx
apt:
name: nginx
state: latest
- name: Enable Nginx
service:
name: nginx
enabled: yes
state: started
- name: Copy config
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: reload nginx
handlers:
- name: reload nginx
service:
name: nginx
state: reloaded
Application Deployment
---
- name: Deploy application
hosts: app_servers
tasks:
- name: Clone repository
git:
repo: https://github.com/user/app.git
dest: /var/www/app
version: main
- name: Install dependencies
shell: cd /var/www/app && pip install -r requirements.txt
- name: Run migrations
shell: cd /var/www/app && python manage.py migrate
- name: Restart app
service:
name: myapp
state: restarted
Best Practices
- Use version control for playbooks and roles
- Use vault for sensitive data (passwords, tokens, keys)
- Leverage idempotency - tasks should be safe to run multiple times
- Use handlers for state changes that require service restarts
- Organize code into roles for reusability
- Test playbooks in development first
- Use assertions to validate changes
- Document complex logic with comments
- Use meaningful variable names
- Keep tasks simple and focused
Environment Variables
| Variable | Purpose |
|---|
ANSIBLE_CONFIG | Path to ansible.cfg |
ANSIBLE_INVENTORY | Path to inventory file |
ANSIBLE_REMOTE_USER | Remote user for connections |
ANSIBLE_PRIVATE_KEY_FILE | Path to SSH key |
ANSIBLE_VAULT_PASSWORD_FILE | Path to vault password |
ANSIBLE_BECOME_PASS | Sudo password |
Resources
Last updated: 2026-03-30|Ansible 2.10+