All skills
Skillintermediate
Common Ansible Module Usage Patterns
- name: Install specific version ansible.builtin.apt: name: nginx=1.18.0-0ubuntu1 state: present
Claude Code Knowledge Pack7/10/2026
Overview
Common Ansible Module Usage Patterns
Core Modules (ansible.builtin)
Package Management
ansible.builtin.package (Universal)
- name: Install package (OS-agnostic)
ansible.builtin.package:
name: nginx
state: present
ansible.builtin.apt (Debian/Ubuntu)
- name: Install package with apt
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
cache_valid_time: 3600
- name: Install specific version
ansible.builtin.apt:
name: nginx=1.18.0-0ubuntu1
state: present
- name: Install multiple packages
ansible.builtin.apt:
name:
- nginx
- postgresql
- redis-server
state: present
ansible.builtin.dnf (RHEL 8+/CentOS 8+) - Recommended
# NOTE: Use ansible.builtin.dnf for RHEL 8+ and CentOS 8+
# ansible.builtin.yum is deprecated in favor of dnf for modern RHEL systems
- name: Install package with dnf
ansible.builtin.dnf:
name: nginx
state: present
update_cache: true
- name: Install from specific repository
ansible.builtin.dnf:
name: nginx
state: present
enablerepo: epel
- name: Install multiple packages
ansible.builtin.dnf:
name:
- nginx
- postgresql
- redis
state: present
ansible.builtin.yum (RHEL 7/CentOS 7 - Legacy)
# NOTE: Only use for RHEL 7/CentOS 7 systems
# For RHEL 8+ use ansible.builtin.dnf instead
- name: Install package with yum (legacy systems)
ansible.builtin.yum:
name: nginx
state: present
update_cache: true
- name: Install from specific repository (legacy)
ansible.builtin.yum:
name: nginx
state: present
enablerepo: epel
File Operations
ansible.builtin.file
# Create directory
- name: Create directory
ansible.builtin.file:
path: /opt/app/config
state: directory
mode: '0755'
owner: appuser
group: appgroup
recurse: true
# Create symbolic link
- name: Create symlink
ansible.builtin.file:
src: /opt/app/current
dest: /opt/app/releases/v1.2.3
state: link
# Remove file/directory
- name: Remove file
ansible.builtin.file:
path: /tmp/tempfile
state: absent
# Set permissions
- name: Set file permissions
ansible.builtin.file:
path: /etc/app/secret.key
mode: '0600'
owner: root
group: root
ansible.builtin.copy
# Copy file from control node
- name: Copy configuration file
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
mode: '0644'
owner: root
group: root
backup: true
validate: 'nginx -t -c %s'
# Copy with inline content
- name: Create file with content
ansible.builtin.copy:
content: |
server {
listen 80;
server_name example.com;
}
dest: /etc/nginx/sites-available/example
mode: '0644'
# Remote copy (on target host)
- name: Copy file on remote host
ansible.builtin.copy:
src: /tmp/source.txt
dest: /opt/destination.txt
remote_src: true
ansible.builtin.template
- name: Deploy configuration from template
ansible.builtin.template:
src: templates/app_config.j2
dest: /etc/app/config.yml
mode: '0644'
owner: appuser
group: appgroup
backup: true
validate: '/usr/bin/app validate %s'
ansible.builtin.fetch
- name: Fetch file from remote to control node
ansible.builtin.fetch:
src: /var/log/app/error.log
dest: /tmp/logs/{{ inventory_hostname }}/
flat: true
ansible.builtin.lineinfile
- name: Ensure line is present
ansible.builtin.lineinfile:
path: /etc/hosts
line: '192.168.1.100 app.local'
state: present
- name: Replace or add line with regexp
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin no'
state: present
backup: true
notify: Restart sshd
- name: Remove line
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: '.*old-server.*'
state: absent
ansible.builtin.blockinfile
- name: Add block of text
ansible.builtin.blockinfile:
path: /etc/hosts
block: |
192.168.1.10 web1.local
192.168.1.11 web2.local
192.168.1.20 db1.local
marker: "# {mark} ANSIBLE MANAGED BLOCK - SERVERS"
backup: true
Service Management
ansible.builtin.service
- name: Ensure service is running
ansible.builtin.service:
name: nginx
state: started
enabled: true
- name: Restart service
ansible.builtin.service:
name: nginx
state: restarted
- name: Stop and disable service
ansible.builtin.service:
name: apache2
state: stopped
enabled: false
ansible.builtin.systemd
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true
- name: Start and enable service
ansible.builtin.systemd:
name: myapp
state: started
enabled: true
daemon_reload: true
- name: Mask service
ansible.builtin.systemd:
name: apache2
masked: true
User and Group Management
ansible.builtin.user
- name: Create user
ansible.builtin.user:
name: appuser
uid: 1500
group: appgroup
groups: docker,sudo
shell: /bin/bash
home: /home/appuser
createhome: true
state: present
- name: Set user password
ansible.builtin.user:
name: appuser
password: "{{ user_password | password_hash('sha512') }}"
update_password: always
- name: Add SSH key
ansible.builtin.user:
name: appuser
ssh_key_bits: 4096
ssh_key_file: .ssh/id_rsa
ansible.builtin.group
- name: Create group
ansible.builtin.group:
name: appgroup
gid: 1500
state: present
ansible.builtin.authorized_key
- name: Add SSH authorized key
ansible.builtin.authorized_key:
user: appuser
state: present
key: "{{ lookup('file', '/home/user/.ssh/id_rsa.pub') }}"
- name: Add multiple keys
ansible.builtin.authorized_key:
user: appuser
state: present
key: "{{ item }}"
loop:
- ssh-rsa AAAAB3... user1@host
- ssh-rsa AAAAB3... user2@host
Command Execution
ansible.builtin.command
- name: Run command (no shell processing)
ansible.builtin.command: /usr/bin/make install
args:
chdir: /opt/app
creates: /opt/app/bin/app
register: make_result
changed_when: make_result.rc == 0
- name: Run with environment variables
ansible.builtin.command: /opt/app/deploy.sh
environment:
APP_ENV: production
DB_HOST: localhost
ansible.builtin.shell
- name: Run shell command (with pipes/redirects)
ansible.builtin.shell: cat /var/log/app.log | grep ERROR > /tmp/errors.txt
args:
executable: /bin/bash
changed_when: false
- name: Use shell with creates
ansible.builtin.shell: /opt/install.sh
args:
creates: /opt/app/installed.flag
ansible.builtin.script
- name: Run script from control node
ansible.builtin.script: scripts/setup.sh
args:
creates: /etc/app/setup.done
Git Operations
ansible.builtin.git
- name: Clone repository
ansible.builtin.git:
repo: https://github.com/user/repo.git
dest: /opt/app
version: main
force: true
- name: Clone specific branch/tag
ansible.builtin.git:
repo: https://github.com/user/repo.git
dest: /opt/app
version: v1.2.3
- name: Clone with SSH key
ansible.builtin.git:
repo: git@github.com:user/repo.git
dest: /opt/app
key_file: /home/deploy/.ssh/id_rsa
accept_hostkey: true
Archive Operations
ansible.builtin.unarchive
- name: Extract archive from control node
ansible.builtin.unarchive:
src: files/app.tar.gz
dest: /opt/
owner: appuser
group: appgroup
- name: Extract remote archive
ansible.builtin.unarchive:
src: /tmp/app.tar.gz
dest: /opt/
remote_src: true
- name: Download and extract
ansible.builtin.unarchive:
src: https://example.com/app.tar.gz
dest: /opt/
remote_src: true
ansible.builtin.archive
- name: Create archive
ansible.builtin.archive:
path:
- /opt/app/config
- /opt/app/data
dest: /tmp/backup.tar.gz
format: gz
Download Operations
ansible.builtin.get_url
- name: Download file
ansible.builtin.get_url:
url: https://example.com/file.tar.gz
dest: /tmp/file.tar.gz
mode: '0644'
checksum: sha256:abc123...
- name: Download with authentication
ansible.builtin.get_url:
url: https://secure.example.com/file.tar.gz
dest: /tmp/file.tar.gz
url_username: user
url_password: "{{ download_password }}"
URI/API Operations
ansible.builtin.uri
- name: Check API endpoint
ansible.builtin.uri:
url: http://localhost:8080/health
method: GET
status_code: 200
register: health_check
until: health_check.status == 200
retries: 5
delay: 10
- name: POST to API
ansible.builtin.uri:
url: https://api.example.com/deploy
method: POST
body_format: json
body:
version: "1.2.3"
environment: production
headers:
Authorization: "Bearer {{ api_token }}"
status_code: [200, 201]
- name: Download response to file
ansible.builtin.uri:
url: https://api.example.com/data
method: GET
dest: /tmp/data.json
Cron Jobs
ansible.builtin.cron
- name: Add cron job
ansible.builtin.cron:
name: "Daily backup"
minute: "0"
hour: "2"
job: "/opt/backup.sh"
user: root
state: present
- name: Add cron job with special time
ansible.builtin.cron:
name: "Reboot task"
special_time: reboot
job: "/opt/startup.sh"
- name: Remove cron job
ansible.builtin.cron:
name: "Daily backup"
state: absent
Debug and Assert
ansible.builtin.debug
- name: Print variable
ansible.builtin.debug:
var: ansible_distribution
- name: Print message
ansible.builtin.debug:
msg: "Server IP: {{ ansible_default_ipv4.address }}"
- name: Conditional debug
ansible.builtin.debug:
msg: "This is a production server"
when: env == "production"
ansible.builtin.assert
- name: Validate configuration
ansible.builtin.assert:
that:
- ansible_distribution in ['Ubuntu', 'Debian']
- app_port | int > 0
- app_port | int < 65536
- db_password is defined
fail_msg: "Configuration validation failed"
success_msg: "Configuration is valid"
quiet: false
Set Facts
ansible.builtin.set_fact
- name: Set computed fact
ansible.builtin.set_fact:
app_full_version: "{{ app_name }}-{{ app_version }}"
deployment_time: "{{ ansible_date_time.iso8601 }}"
- name: Set fact with conditional
ansible.builtin.set_fact:
db_host: "{{ 'localhost' if env == 'dev' else 'db.prod.example.com' }}"
- name: Combine facts
ansible.builtin.set_fact:
app_config:
name: "{{ app_name }}"
version: "{{ app_version }}"
port: "{{ app_port }}"
Include and Import
ansible.builtin.include_tasks
- name: Include tasks dynamically
ansible.builtin.include_tasks: "{{ ansible_os_family }}.yml"
- name: Include with variables
ansible.builtin.include_tasks: deploy.yml
vars:
app_version: "1.2.3"
ansible.builtin.import_tasks
- name: Import tasks statically
ansible.builtin.import_tasks: common.yml
ansible.builtin.include_vars
- name: Load variables from file
ansible.builtin.include_vars:
file: "{{ env }}.yml"
- name: Load all YAML files from directory
ansible.builtin.include_vars:
dir: vars/
extensions:
- yml
- yaml
Wait Operations
ansible.builtin.wait_for
- name: Wait for port to be available
ansible.builtin.wait_for:
port: 8080
delay: 5
timeout: 300
state: started
- name: Wait for file to exist
ansible.builtin.wait_for:
path: /opt/app/ready
state: present
timeout: 300
- name: Wait for service to stop
ansible.builtin.wait_for:
port: 8080
state: stopped
timeout: 60
Error Handling with Block/Rescue/Always
Basic Block with Rescue
- name: Handle errors gracefully
block:
- name: Attempt risky operation
ansible.builtin.command: /opt/risky_script.sh
- name: This won't run if above fails
ansible.builtin.debug:
msg: "Script succeeded"
rescue:
- name: Handle failure
ansible.builtin.debug:
msg: "Script failed, performing recovery"
- name: Log error details
ansible.builtin.copy:
content: "{{ ansible_failed_result }}"
dest: /var/log/error.log
Block with Rescue and Always
- name: Deploy with rollback capability
block:
- name: Stop application
ansible.builtin.service:
name: myapp
state: stopped
- name: Deploy new version
ansible.builtin.copy:
src: app-v2.jar
dest: /opt/app/app.jar
backup: true
register: deploy_result
- name: Start application
ansible.builtin.service:
name: myapp
state: started
rescue:
- name: Rollback on failure
ansible.builtin.copy:
remote_src: true
src: "{{ deploy_result.backup_file }}"
dest: /opt/app/app.jar
when: deploy_result.backup_file is defined
- name: Start application with old version
ansible.builtin.service:
name: myapp
state: started
always:
- name: Verify application is running
ansible.builtin.wait_for:
port: 8080
timeout: 60
Configuration Update with Validation and Backup
- name: Update config with validation
block:
- name: Deploy new configuration
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
backup: true
validate: 'nginx -t -c %s'
register: config_update
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
rescue:
- name: Restore backup on failure
ansible.builtin.copy:
remote_src: true
src: "{{ config_update.backup_file }}"
dest: /etc/nginx/nginx.conf
when: config_update.backup_file is defined
- name: Reload nginx with old config
ansible.builtin.service:
name: nginx
state: reloaded
always:
- name: Verify nginx is responding
ansible.builtin.uri:
url: http://localhost/health
status_code: 200
Accessing Error Variables in Rescue
- name: Use error variables
block:
- name: Task that might fail
ansible.builtin.command: /opt/backup.sh
register: backup_result
rescue:
- name: Log failed task name
ansible.builtin.debug:
msg: "Failed task: {{ ansible_failed_task.name }}"
- name: Log error details
an